Web网站安全头号大敌XSS漏洞解决最佳实践

2023年 7月 10日 27.5k 0

引言

Web网站安全头号大敌XSS漏洞解决最佳实践

XSS 是目前最普遍的 Web 应用安全漏洞,它带来的危害是巨大的,是 Web 安全的头号大敌。关键词:

  • 跨站
  • 脚本(JavaScript、Java、 VBScript、ActiveX、 Flash 或者 HTML)
  • 注入
  • 执行
1. 什么是 XSS 漏洞?

XSS 攻击:跨站脚本攻击(Cross Site Scripting),为不和 前端层叠样式表(Cascading Style Sheets)CSS 混淆,故将跨站脚本攻击缩写为 XSS。XSS(跨站脚本攻击)是指恶意攻击者往 Web 页面里插入恶意 Script 代码,当用户浏览该页时,嵌入其中 Web 里面的 Script 代码会被执行,从而达到恶意攻击用户的目的。类似于 sql 注入。是目前最普遍的 Web 应用安全漏洞,也是 Web 攻击中最常见的攻击方式之一。XSS( 跨站脚本攻击)攻击通常指的是通过利用网页开发时留下的漏洞,通过巧妙的方法注入恶意指令代码到网页,使用户加载并执行攻击者恶意制造的网页程序。这些恶意网页程序通常是 JavaScript,但实际上也可以包括 Java、 VBScript、ActiveX、 Flash 或者甚至是普通的 HTML。攻击成功后,攻击者可能得到包括但不限于更高的权限(如执行一些操作)、私密网页内容、会话和 cookie 等各种内容。

2. XSS 漏洞攻击原理及攻击手段

HTML 是一种超文本标记语言,通过将一些字符特殊地对待来区别文本和标记,例如,小于符号( JSP---> 9.5 DOM 型 XSS

  • 避免 .innerHTML、.outerHTML、document.write() 的使用,应使用 .textContent、.setAttribute() 等。
  • Vue/React 技术栈,避免使用 v-html/dangerouslySetInnerHTML
  • 尤其注意 onclick、onerror、onload、onmouseover 、eval()、setTimeout()、setInterval() 以及 a 标签的 href
  • 可使用 OWASP  esapi4js : esapi.js
10. 后端服务编码实践

通过 https://start.spring.io/ 快速创建 springboot 应用:Web网站安全头号大敌XSS漏洞解决最佳实践Web网站安全头号大敌XSS漏洞解决最佳实践Web网站安全头号大敌XSS漏洞解决最佳实践解压并在 IDEA 导入刚刚创建的 xss-demo 项目在 pom.xml 添加相关依赖:      org.owasp.antisamy      antisamy      1.5.7     com.alibaba     fastjson     1.2.62 修改 xss-demo 工程包结构如下:Web网站安全头号大敌XSS漏洞解决最佳实践Web网站安全头号大敌XSS漏洞解决最佳实践XSSFilter 编码如下:/** * @program: xss-demo * @author: Mr.Zhang * @create: 2021-02-21 15:45 **/public class XssFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpServletRequest = (HttpServletRequest) request; HttpServletRequest req = (HttpServletRequest) request; String path = req.getServletPath(); //注解配置的是urlPatterns="/*"(过滤所有请求),所以这里对不需要过滤的静态资源url,作忽略处理(大家可以依照具体需求配置) String[] exclusionsUrls = {".js", ".gif", ".jpg", ".png", ".css", ".ico"}; for (String str : exclusionsUrls) { if (path.contains(str)) { chain.doFilter(request, response); return; } } chain.doFilter(new XssRequestWrapper(httpServletRequest), response); }}XssRequestWrapper 包装类编码如下:/** * @program: xss-demo * @author: Mr.Zhang * @create: 2021-02-21 15:46 **/@Slf4jpublic class XssRequestWrapper extends HttpServletRequestWrapper { public XssRequestWrapper(HttpServletRequest request) { super(request); } /** * 获取策略文件,直接使用jar中自带的ebay策略文件 */ private static InputStream inputStream = XssRequestWrapper.class.getClassLoader() .getResourceAsStream("antisamy-ebay.xml"); private static Policy policy = null; static { try { // 使用静态代码块处理策略对象的创建 policy = Policy.getInstance(inputStream); } catch (PolicyException e) { e.printStackTrace(); } } /** * 使用AntiSamy进行过滤数据 * @param html * @return */ private String xssClean(String html) { String cleanHTML = ""; try { AntiSamy antiSamy = new AntiSamy(); CleanResults scan = antiSamy.scan(html, policy); cleanHTML = scan.getCleanHTML(); } catch (ScanException e) { e.printStackTrace(); } catch (PolicyException e) { e.printStackTrace(); } return cleanHTML; } /** * 重写处理请求参数的方法 * @param name * @return */ @Override public String[] getParameterValues(String name) { String[] values = super.getParameterValues(name); // 判断参数有值,如果没有值,直接返回 if (values == null) { return null; } // 遍历参数数组,使用AntiSamy进行过滤 int len = values.length; String[] newValues = new String[len]; for (int i = 0; i < len; i++) { // 过滤前的数据 log.info("使用AntiSamy进行过滤清理,过滤清理之前的数据:{}", values[i]); // 进行过滤 newValues[i] = xssClean(values[i]); // 过滤后的数据 log.info("使用AntiSamy进行过滤清理,过滤清理之后的数据:{}", newValues[i]); } //返回过滤后的结果 return newValues; } /** * 重写处理json数据的方法 * @return * @throws IOException */ @Override public ServletInputStream getInputStream() throws IOException { // 读取流 BufferedReader reader = new BufferedReader( new InputStreamReader(super.getInputStream(), "UTF-8")); // 获取json格式的数据 StringBuilder sb = new StringBuilder(); String inputStr; while ((inputStr = reader.readLine()) != null) { sb.append(inputStr); } // 把json转为map Map map = JSON.parseObject(sb.toString(), Map.class); // 过滤前 log.info("json过滤前:{}", sb.toString()); // 对map中的value值进行AntiSamy的过滤 map.keySet().forEach(k -> { map.put(k, xssClean(map.get(k).toString())); }); // 过滤后 String json = JSON.toJSONString(map); log.info("json过滤后:{}", json); // 把json数据转为流的格式进行返回 ByteArrayInputStream bais = new ByteArrayInputStream(json.getBytes()); return new ServletInputStream() { @Override public boolean isFinished() { return false; } @Override public boolean isReady() { return false; } @Override public void setReadListener(ReadListener listener) { } @Override public int read() throws IOException { return bais.read(); } }; }}AntiSamyConfig 配置过滤器类编码如下:/** * @program: xss-demo * @author: Mr.Zhang * @create: 2021-02-21 15:58 **/@Configurationpublic class AntiSamyConfig { /** * 配置xss过滤器 * @return */ @Bean public FilterRegistrationBean create() { FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new XssFilter()); filterRegistrationBean.addUrlPatterns("/*"); filterRegistrationBean.setOrder(1); return filterRegistrationBean; }}User 实体类:/** * @program: xss-demo * @author: Mr.Zhang * @create: 2021-02-21 15:42**/@Datapublic class User { private int id; private String name; private int age;}UserController 测试控制器类编码如下:/** * @program: xss-demo * @author: Mr.Zhang * @create: 2021-02-21 15:43 **/@Slf4j@RestController@RequestMapping("user")public class UserController { /** * 表单 * @param user * @return */ @PostMapping("save") public String save(User user) { log.info("name={}, age={}", user.getName(), user.getAge()); return JSON.toJSONString(user); } /** * json数据格式请求体 * @param user * @return */ @PostMapping("json") public String saveJson(@RequestBody User user) { log.info("user={}", user.toString()); return JSON.toJSONString(user); }}application.properties 配置文件为空,运行启动类后默认端口号8080。Postman 模拟表单数据请求及响应效果如下:Web网站安全头号大敌XSS漏洞解决最佳实践后端程序控制台日志打印如下:Web网站安全头号大敌XSS漏洞解决最佳实践Web网站安全头号大敌XSS漏洞解决最佳实践Postman 模拟 json 数据请求及响应效果如下:Web网站安全头号大敌XSS漏洞解决最佳实践Web网站安全头号大敌XSS漏洞解决最佳实践后端程序控制台日志打印如下:Web网站安全头号大敌XSS漏洞解决最佳实践Web网站安全头号大敌XSS漏洞解决最佳实践以上两个情况,请求参数中隐藏的 xss 攻击代码被过滤器过滤后再进入 Contrlloer 层处理。

11. 能不能根本上解决问题,即浏览器自动禁止外部注入恶意脚本?

开启 CSP (内容安全策略 Content Security Policy)方法:设置 HTTP 的 头部字段

resp.setHeader("Content-Security-Policy","default-src http: https:");

设置网页的标签

CSP 常见可选策略设置如下:

策略 含义
default-src http: https: ; 只能通过外联的方式引用 js 和 css
default-src 'self' http://smart4j.cn/; 只能在指定的域下加载文件(包含 img)
form-action 'self''; form 表单的只能在指定域提交
script-src 'self'; 只限制 js 文件在同域加载文件
report-uri /report; 向指定uri发送违规报告(不支持 meta 方式)

相关文章

Mallox勒索软件新Linux变种现世
伪装成破解程序和商业工具的新型恶意软件正在传播
Orcinius后门新样本分析
Poseidon窃取程序通过Google广告感染Mac用户
大选开始之际,欧盟各政党遭受 DDoS 攻击
微软2024

发布评论