Cross-Site Scripting(跨站脚本攻击)简称 XSS,是一种代码注入攻击。攻击者通过在目标网站上注入恶意脚本,使之在用户的浏览器上运行。利用这些恶意脚本,攻击者可获取用户的敏感信息如 Cookie、SessionID 等,进而危害数据安全。
本质:
用户提交的数据未经过滤,渲染到了HTML上,结果被浏览器当成了代码,浏览器无法分辨哪些代码是可信的,导致恶意代码被执行。
注入的入口
在部分情况下,由于输入的限制,注入的恶意代码比较短。但可以通过引入外部的js文件,并由浏览器执行,来完成比较复杂的攻击策略
总结
当需要把某些数据渲染到HTML上,但是这些数据是由用户决定的,这时候就有可能受到XSS攻击
攻击者能够在用户的页面上运行恶意 JS ,就相当于取得了整个页面的浏览器上的控制权,攻击者通过XSS干的事情包括但不限于以下:
获取用户敏感信息。监听表单输入,获取cookie等
冒充用户发起操作请求。在恶意脚本中利用用户的登录状态进行货币、物品等转账,更改权限管理等
钓鱼。弹窗,或改造页面外观,引导用户输入其他网站的敏感信息
挖矿。占用CPU,消耗资源
发起DOS攻击。所有被XSS的用户对某个目标发起资源请求。
XSS 蠕虫。如果是社交平台的XSS,在恶意脚本中利用用户的登录状态进行关注、发状态、发私信等操作,发出的状态和私信可再带上攻击 URL,诱导更多人点击,不断放大攻击范围。
…
根据攻击的来源,XSS 攻击可分为存储型、反射型和 DOM 型三种
存储型 XSS 的攻击步骤:
这种攻击常见于带有用户保存数据的网站功能,如论坛发帖、商品评论、用户私信等。
反射型 XSS 的攻击步骤:
反射型 XSS 跟存储型 XSS 的区别是:存储型 XSS 的恶意代码存在数据库里,反射型 XSS 的恶意代码存在 URL 里。
反射型 XSS 漏洞常见于通过 URL 传递参数的功能,如网站搜索、跳转等。
由于需要用户主动打开恶意的 URL 才能生效,攻击者往往会结合多种手段诱导用户点击。
DOM 型 XSS 的攻击步骤:
eval
等操作,恶意代码被执行。DOM 型 XSS 跟前两种 XSS 的区别:DOM 型 XSS 攻击中,取出和执行恶意代码由浏览器端完成,属于前端 JavaScript 自身的安全漏洞,而其他两种 XSS 都属于服务端的安全漏洞。
预防DOM型 XSS 攻击
写原生JS时,一定不要把不可信的数据通过 innerHTML
、outerHTML
、document.write
渲染在页面上。尽量使用textContent
、setAttribute
等。如果使用Vue/React 技术栈,避免使用v-html
/dangerouslySetInnerHTML
。DOM的内联事件,a
标签的href
,JS中的eval
,setTimeout
,setInterval
等都会把字符串作为代码运行,一定不要把不可信的字符串拼接或传递给这些API
手动检测
jaVasCript:/*-/*`/*\`/*'/*"/**/(/* */oNcliCk=alert() )//%0D%0A%0d%0a//\x3csVg/\x3e
攻击者注入的内容通常称为payload,上面就是一个很好用的payload,它能够检测到存在于 HTML 属性、HTML 文字内容、HTML 注释、跳转链接、内联 JavaScript 字符串、内联 CSS 样式表等多种上下文中的 XSS 漏洞,也能检测 eval()
、setTimeout()
、setInterval()
、Function()
、innerHTML
、document.write()
等 DOM 型 XSS 漏洞,并且能绕过一些 XSS 过滤器
漏扫工具
除了手动检测之外,还可以使用自动扫描工具寻找 XSS 漏洞,例如AWVS 、Arachni、w3af 等
CSRF(Cross-site request forgery)跨站请求伪造:攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求。利用受害者在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户对被攻击的网站执行某项操作的目的
一个典型的CSRF攻击有着如下的流程:
CSRF大多来自第三方网站,直接禁止外域(或者不受信任的域名)对我们发起请求。通常做法是对请求头中的Referer
进行检测,这个内容前端 JS
是无法修改的
这种方法显而易见的好处就是简单方便。然而,Referer
的值是浏览器提供的,虽然HTTP 协议有明确的要求,但是浏览器的实现可能有差别,还可能有漏洞,比如 IE6 和 FF2 中就可能被篡改Referer
值
另外,有的浏览器中用户可以手动关闭Referer
的发送,这种情况下,用户的请求是正常的请求,但是请求中没有Referer
,而攻击者也可以伪造没有Referer
的请求。如果把没有Referer
的请求封掉就会存在误封
最后,如果攻击者的请求本身就是从本域发起的(比如在留言,评论处引入img
元素),这种依赖同源检测来防范 CSRF 的方式就会失效。
总结
针对CSRF攻击,同源检测非常方便,而且很大程度上可以起到防御的作用。但是会对没有Referer
的请求存在误封,无法防御用户使用存在Referer
篡改漏洞浏览器时被攻击的情况,以及对于本域发起的 CSRF 无法防范。
CSRF 攻击之所以能成功,是因为浏览器向一个域名发送请求时,会自动带上这个域名下的cookie。攻击者冒用了域名下的cookie,但是攻击者本身是没法知道cookie的具体数值
所以,对用户身份的验证不能只能验证请求的cookie,服务端规定在请求体或者请求头中,需要带上一个特殊字符串,服务端对这个特殊的字符串验证其合法性,这个字符串就叫 CSRF Token
CSRF Token的实现有以下几种方式:
服务端针对每个用户生成一个 token 并存储在Session中,浏览器请求页面时,在cookie
或者页面某处
插入此token,前端拿到token后,无论是ajax,还是表单提交都需要在请求头
或者请求体
或者请求参数
中携带此token,服务端接收请求时将请求中的 token 和Sesssion中的token比对,一致则通过。
服务端对每个用户生成一个 token,把token当作cookie设置在浏览器中,前端将此cookie取出后,每次发请求时添加到请求头
或者请求体
或者请求参数
中,服务端接收请求时将cookie中的token和请求头
或者请求体
或者请求参数
中的token比对,一致则通过。