xxs 攻击英文全称是 Croess SiteScripting ,意思就是跨站脚本攻击。是一种网站应用程序的安全漏洞攻击。是脚本代码注入的一种。其核心的攻击原理就是注入有攻击行为的脚本代码,通过浏览器的执行从而完成攻击行为。
他的攻击方法主要分为 3 类,分别是 反射型 XSS,存储型 XSS和基于的 DOM 的 XSS 。
反射型 xss 又称,非永久性 XSS 。它一般出现在服务器没有经过正确编码而直接使用客户端提供的数据的情况下出现。
而其中最为常见和熟悉的就是网站的 URL 地址中的数据,协议头或者表单数据。如下图:
攻击原理就是用户点击执行有恶意脚本的 URL 地址,然后登陆了某个网站,然后服务器返回带恶意脚本代码在浏览器中执行,从而完成攻击行为。
而一个完整的攻击流程是这样的:
A 和 B 表示的是用户和网站正常通信,从 C 开始就是 XSS 攻击的整个流程。
首先:
以上就是 反射型XSS 的整体攻击环节。
存储型 XSS 又称永久性XSS,他的攻击方法是把恶意脚本注入在服务器中,之后在别人的访问时,浏览器会执行注入了恶意脚本的 HTML,从而实现了攻击行为。相比之下,放射型 XSS 的危险要比存储型 XSS 的危害要小一点。存储型 XSS 是存储在 DB 之中,而连接多少还可以发现一点问题,而存在数据库中的数据用户是没有办法感知的。
存储型 XSS 攻击原理如下:
黑客事先在 website 的 server 中存储一端恶意脚本,之后用户点击访问获取数据,浏览器在解析文件的时候执行了恶意的脚本,向黑客发送敏感数据。
存储型 XSS 的攻击整体流程是:
C 表示的是正常访问 website 的情况。
首先:
基于 DOM 的 XSS 的攻击场景和反射性 XSS 是一样的,但是唯一不同的就是,基于 DOM 的 XSS,不是发生在服务器端,而是直接发生在了浏览器那里。
他们之间的区别就是如果是通过 HTTP 请求数据而导致的就是属于反射型 XSS,如果是存储在服务器上面的 就是属于存储型 XSS。如果是 DOM 的数据结构发生了变化,那么就是属于基于DOM 的XSS。
注入的方式分别是通用修改 DOM 节点内容,通过修改 DOM 节点属性,通过修改 JavaScript 修改和通过富文本修改。
举个例子:在 HTML 中有一段注入恶意代码,比如在 url 中 注入一段恶意脚本。
// 正常--
<script>
const url = "...xx.com?id=1";
const id = "1";
</script>
<div>
<p>{id}</p>
// 转换为
<p>1</p>
</div>
// 异常--
<script>
const url = "...xx.com?id=<script>console.log(document.cookie);
const id = "<script>console.log(document.cookie)</script>";
</script>
<div>
<p>{id}</p>
// 转换为
<p><script>console.log(document.cookie)</script></p>
</div>
在获取一段 URL 的参数时,将 URL 参数写进 DOM 的时候,如果这个是一段恶意脚本,那么他就会自动执行,相当于这个 HTML 多了一段恶意脚本。
// 正常--
<script>const image_url = "..images.ac.qq.com/....."</script>
<div>
<img src="{image_url}">
</div>
// 异常--
<script>
const image_url = " onerror="console.log(document.cookie)"
</script>
<div>
<img src="" onerror="console.log(document.cookie)"">
</div>
上面一段代码可以看到,如果 image_url 这个标签是一个普通的 url 地址,那是没有问题。
但是,如果是如果是一段有问题的 url ,那么就会出现下面的情况,这个 img 标签就会执行 onerror里面的函数。他的原理就是提前把 img 的 src 属性闭合,之后再补上一个 onerror 的属性,在这个属性里面注入恶意脚本。
同样的,还是从 URL 中获取参数 id,只不过这次不是渲染到 DOM , 而是写入 JavaScript 代码中。
// 正常
const url = "...xx.com?id=1";
const id = "1";
// 异常
const url = "...xx.com?id=1"console.log(document.cookie)"";
const id = "1"console.log(document.cookie)"";
<div><p style="font-size='16px;'">test</p><script>console.log(document.cookie)</script></div>
这一段富文本就包含了一段恶意脚本代码,而这一段代码是会保存在数据库的,凡是读取了这一段代码的都可能被注入攻击。
对于一些标签的 < 和 > 进行转移,是他们在 HTML 中不会以一个 script 标签形式执行。
对于 DOM 节点影响比较大的就是单引号和双引号, 因为他们会关闭属性的值。所以也是对单引号和双引号进行字符转义。
对于避免造成 javascript 注入的情况,一般会对从 url 上取到的数据进行 encode ,这样就可以避免双引号提前封闭。
只是这里也要注意一下 ,这里一般会使用 encode 的方式格式化参数会更好一些,不然也要考虑类似 \" 这样的双引号转义符,是不是会和 下一个 " 又相互抵消。 当然,解决的方法还是给 \ 做转义。
在富文本中,可以其实可以使用配置黑白名单的方法,配置禁止某些标签出现或者是只允许某些标签出现。
但更多时候建议使用的还是白名单,因为配置黑名单实在是太麻烦了而且一旦漏了,问题也就大了。网上已经有一些库可以使用,但是这些库是别人写的,可能有些地方不是自己想要的。所以,如果想完全定制那么就是使用白名单配置,如果只是一个小需求,快速开发影响也不大,那就可以考虑引用个库。
前面说的一些防御方法是有效果,但是始终还是远远不够。所以,现在防御XSS 有一个更好的方法就是使用 CSP 规则。
CSP 即 content security policy 内容安全策略,是一个 HTTP header ,用于指定哪些内容可以执行。
http.set(`content-security-policy`, `default-src 'self'`);
上面这个意思就是允许当前域下的任意请求。
至于详细配置,可以参考 ,https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CSP 这个说明。
csp 规则一般会在服务器配置,当然前端页面也是可以配置,但是更多的是以服务器为准,在日常开发中也经常会遇到引用了第三方的东西,这个时候 csp 规则不通过,都需要向服务器端的同学要求加个规则。
以上就是 XSS 攻击和防御的整体流程。
第十篇文章了,继续坚持。。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。