乐趣区

花点时间弄懂XSS攻击

最近在 segmentfault 发现了刘小夕.
很喜欢刘小夕写出来的技术博文,被安排的明明白白.
此文章为学习刘小夕的 WEB 安全笔记. 欢迎大家也去 Pick 她.
文章最后有原文链接.

前端有哪几种攻击方式?

XSS 攻击.CSRF 攻击. 点击劫持以及 URL 跳转漏洞

什么是 XSS 攻击?

XSS(Cross-Site Scripting, 跨站脚本攻击)是一种代码注入攻击。攻击者在目标网站上注入恶意代码,当用户 (被攻击者) 登录网站时就会执行这些恶意代码,通过这些脚本可以读取 cookie,session tokens,或者网站其他敏感的网站信息,对用户进行钓鱼欺诈。

XSS 的本质:恶意代码未经过滤,与网站的正常代码混在一起,浏览器无法分辨哪些脚本是可信的,导致恶意脚本被执行。由于直接在用户的终端代码执行,恶意代码能够直接获取用户的信息,利用这些信息冒充用户向网站发起攻击请求.

XSS 攻击有哪些类型?

反射型 XSS

反射型 XSS 漏洞常见于通过 URL 传递参数的功能,如网站搜索,跳转等。由于需要用户主动打开恶意的 URL 才能生效,攻击者往往会结合多种手段诱导用户点击.
POST 的内容也可以触发反射型 XSS,只不过它的触发条件比较苛刻(构建表单提交页面,并引导用户点击),所以非常少见.

反射型 XSS 的攻击步骤

1. 攻击者构造出特殊的 URL,其中包含恶意代码.
2. 用户打开有恶意代码的 URL 时,网站服务器端将恶意代码从 URL 取出,拼接在 HTML 返回给浏览器.
3. 用户浏览器接收到响应后解析执行,混在其中的恶意代码也会被执行。
4. 恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户行为,调用目标网站接口执行攻击者指定的操作.

注意:Chrome 和 Safari 能够检测到 url 上的 xss 攻击,将网页拦截掉,但是其他浏览器不行,如 IE 和 Firefox。

如何防御反射型 XSS 攻击

对 url 查询参数进行转义后再输出到页面。

app.get('/welcome',function(req,res){
  // 对查询参数进行编码,避免反射型 XSS 攻击
  res.send(`${encodeURIComponent(req.query.type)}`);
})

DOM 型 XSS

DOM 型 XSS 攻击,实际上就是前端 javascript 代码不够严谨,把不可信的内容插入到了页面,在使用.innerHTML、.outerHTML、.appendChild、document.write()等 API 时要特别小心,不要把不可信的数据作为 HTML 插入到页面上,尽量使用.innerText、.textContent、.setAttribut()等.

DOM 型 XSS 的攻击步骤

1. 攻击者构造出特殊数据,其中包含恶意代码。
2. 用户浏览器执行了恶意代码
3. 恶意窃取用户数据并发送到攻击者的网站,或冒充用户行为,调用目标网站接口执行攻击者指定的操作.

如何防御 DOM 型 XSS 攻击

防范 DOM 型 XSS 攻击的核心就是对输入内容进行转义(DOM 中的内联事件监听顺和链接跳转都能把字符串作为代码运行,需对内容进行检查).
1. 对于 url 链接(例如图片的 src 属性)那么直接使用 encodeURIComponent 来转义。
2. 对于非 url,我们可以进行编码:

function encodeHtml(str){return str.replace(/"/g,'"')
            .replace(/'/g,''')
            .replace(/</g,'&lt;')
            .replace(/>/g,'&gt;')
}

DOM 型 XSS 攻击中,取出和执行恶意代码由浏览器端完成,属于前端 javascript 自身的安全漏洞.

存储型 XSS

恶意脚本永久存储在目标服务器上。当浏览器请求数据时,脚本从服务器传回并执行,影响范围比反射型和 DOM 型 XSS 更大。存储型 XSS 攻击的原因仍然是没有做好数据过滤:前端提交数据至服务器端时,没有做好过滤; 服务端在按受到数据时,在存储之前,没有做过滤; 前端从服务器端请求到数据,没有过滤输出。

存储型 XSS 的攻击步骤

1. 攻击者将恶意代码提交到目标网站的数据库中。
2. 用户打开目标网站时,网站服务端将恶意代码从数据库中取出,拼接在 HTML 中返回给浏览器。
3. 用户浏览器接收到响应后解析执行,混在其中的恶意代码也被执行。
4. 恶意代码窃取用户数据并发送到攻击者的网站,或冒充用户行为,凋用目标网站接口执行攻击者指定的操作.
这种攻击常见于带有用户保存数据的网站功能,如论坛发帖,商品评论,用户私信等。

如何防范存储型 XSS 攻击

1. 前端数据传递给服务器之彰,先转义 / 过滤(防范不了抓包修改数据的情况)
2. 服务器接收到数据,在存储到数据库之前,进行转义和过滤
3. 前端接收到服务器传递过来的数据,在展示到页面前,先进行转义 / 过滤.

function getList()
{$.get('/getComments2').then(res=> {if(res.code === 0){
      let list ="";
      $each(res.comments,(index,comment)=>{content = encodeHtml(comment.content);
        console.log(comment.content,'*****',content);
        lists += '<li class="list-group-item"><span>${comment.username};</span>${content}';
      });
      $('.list-group').html(lists);
     }   
   }
  )
}

除了谨慎的转义,其他一些手段来防范 XSS 攻击:
1.Content Security Policy
在服务端使用 HTTP 的 Content-Security-Policy 头部来指定策略,或者在前端设置 meta 标答。
例如下面的配置只允许加载同域下的资源:

Content-Security-Policy:default-src 'self'` 请输入代码 `
<meta http-equiv="Content-Security-Policy" content="form-action'self';">

前端和服务器设置 CSP 的效果相同.

严格的 CSP 在 XSS 的防范中可以起到以下的作用
1. 禁止加载外域代码,防止复杂的逻辑攻击.
2. 禁止外域提交,网站被攻击后,用户数据不会被泄露到外域
3. 禁止内联脚本执行(规则较严格,目前发现 github 使用)
4. 禁止未授权的脚本执行
5. 合理使用上报可以及时发现 XSS,利用尽快修复问题.

2. 输入内容长度控制
对于不受信任的输入,都应该限定一个合理的长度。虽无法完全防止 XSS 发生,但是可以增加 XSS 攻击的难度。

3. 输入内容限制
对于部分输入,可以限定不能包含特殊字符或者仅能输入数字等。

4. 其他安全措施
HTTP-only Cookie: 禁止 JavaScript 读取某些敏感 Cookie,攻击者完成 XSS 注入后也无法窃取此 Cookie
验证码:防止脚本冒充用户提交危险操作

XSS 检测

1. 使用通用 XSS 攻击字串手动检测 XSS 漏洞, 如:

jaVasCript:/*-/*`/*\`/*'/*"/**/(/* */oNcliCk=alert() )//%0D%0A%0d%0a//</stYle/</titLe/</teXtarEa/</scRipt/--!>\x3csVg/<sVg/oNloAd=alert()//>\x3e

能够检测到存在于 HTML 属性、HTML 文字内容、HTML 注释、跳转链接、内联 Javascript 字符串、内联 CSS 样式表等多种上下文中的 XSS 漏洞,也能检测 eval()、setTimeout()、setInterval()、Function()、innerHTML、document.write()等 DOM 型 XSS 漏洞,并且能绕过一些 XSS 过滤器.
2. 安全扫描工具
Arachni
Mozilla HTTP Observatory
w3af

退出移动版