XSS跨站脚本攻击
XSS
XSS跨站脚本攻击,全称Cross-Site scripting
当目标网站目标用户浏览器渲染HTML文档的过程中出现了不被预期的脚本指令并执行时,XSS就发生了
作为一种HTML注入攻击,XSS攻击的核心思想就是在HTML页面中注入恶意代码
在XSS攻击中,一般有三个角色参与:攻击者、目标服务器、受害者的浏览器
由于有的服务器并没有对用户的输入进行安全方面的验证,攻击者就可以很容易地通过正常的输入手段,夹带进一些恶意的HTML脚本代码
当受害者的浏览器访问目标服务器上被注入恶意脚本的页面后,由于它对目标服务器的信任,这段恶意脚本的执行不会受到什么阻碍,而此时,攻击者的目的就已经达到了
XSS攻击一般分为三种
反射型XSS
反射型/非持久型XSS的注入代码从目标服务器通过错误信息、搜索结果等等方式“反射”而来
发出请求时,XSS代码会出现在URL中,作为输入提交到服务器端,服务器端解析后响应,XSS代码随响应内容一起传回给浏览器,最后浏览器解析执行XSS代码
这个过程像一次反射,所以被称为反射型XSS;这种攻击方式具有一次性,代码注入的是一个动态产生的页面而不是永久的页面,因此这种攻击方式只在点击链接的时候才产生作用,所以被称为非持久型XSS
特点
- 即时性,不经过服务器存储,直接通过HTTP的GET和POST请求就能完成一次攻击,拿到用户隐私数据
- 攻击者需要诱骗点击
- 反馈率低,所以较难发现和响应修复
- 盗取用户敏感保密信息
案例
要利用这个漏洞,攻击者必须以某种方式诱导用户访问一个精心设计的URL(恶意链接),例如一条恶意连接
1 | http://127.0.0.1:5500/index.html?a=<script>alert(1)</script> |
黑客可以返回这段XSS代码,从而把a参数的值注入页面
1 | const params = new URLSearchParams(location.search) |
黑客可能会通过注入恶意script脚本,或引入外部木马,实现读取用户cookie或其他用户信息
防范措施
- Web页面渲染的所有内容或者渲染的数据都必须来自于服务端
- 尽量不要从URL、
document.referrer``document.forms
等这种 DOM API中获取数据直接渲染 - 尽量不要使用
eval
、new Function()
、document.write()
、document.writeln()
、window.setInterval()
、window.setTimeout()
、innerHTML
、document.creteElement()
等可执行字符串的方法 - 如果做不到以上几点,也必须对涉及DOM渲染的方法传入的字符串参数做escape转义
- 前端渲染的时候对任何的字段都需要做escape转义编码
存储型XSS
存储型/HTML注入型/持久性XSS攻击最常发生在由社区内容驱动的网站或Web邮件网站,不需要特制的链接来执行
攻击脚本将被永久地存放在目标服务器端(数据库,内存,文件系统等),下次请求目标页面时不用再提交XSS代码
黑客仅需要提交XSS漏洞利用代码到一个网站上其他用户可能访问的地方,这些地方可能是博客评论、用户评论、留言板、聊天室、HTML、电子邮件、wikis和其他许多地方
一旦用户访问到受感染的页面,就会自动执行漏洞;因为这些页面是开放的,而且往往是用户信任的页面,所以是影响最严重的
存储型XSS更具有隐蔽性,带来的危害也更大,除非服务器能完全阻止注入,否则任何人都很有可能受到攻击
特点
- 持久性,植入在数据库中
- 危害面广,甚至可以让用户机器变成DDoS攻击的肉鸡
- 盗取用户敏感私密信息
案例
在评论区输入一段script代码点击发送时,如果前端和后端都没有进行过滤操作,这段代码就会被注入到数据库;当有其他人读取评论时,这段代码就会被拉取到他的页面
1 | var a = document.getElementById('a') |
防范措施
- 后端在入库前应该选择不相信任何前端数据,将所有的字段统一进行转义处理
- 后端在输出给前端数据统一进行转义处理
- 前端在渲染页面DOM的时候应该选择不相信任何后端数据,任何字段都需要做转义处理
DOM型XSS
DOM型/客户端XSS攻击基于Web应用程序中的JavaScript脚本语言与HTML的交互性质(即DOM文档对象模型操作)实现
攻击者会通过Web应用程序中的某个页面向用户提供构造好的特殊URL,当用户访问该URL时,浏览器会执行其中的JavaScript代码,攻击者利用该机制就可以注入恶意代码到当前页面、篡改现有页面内容、盗取用户个人信息
与其他XSS攻击类型不同的是,DOM型XSS不会触发HTTP请求或响应过程,它的攻击载荷不会被传递到服务端,而是直接在客户端执行,这使它更加难以检测和防范
案例
黑客会尝试在页面上的所有input框中进行XSS注入
1 | // dom xss注入 |
如果像上述代码一样,不安全的使用了那些危险属性和方法,就可能造成危险
防范措施
为了防止DOM型XSS攻击,可以对输入的数据进行过滤和转义处理、限制用户的输入行为、避免使用危险的JavaScript属性或方法,例如location
、innerHTML
、document.write
、Vue的v-html
、eval
基于字符集的XSS
即使现在很多的浏览器以及各种开源的库都专门针对了XSS进行转义处理,尽量默认抵御绝大多数都能XSS攻击,但是还是有很多方式可以绕过转义规则
”基于字符集的XSS攻击“就是绕过这些转义处理的一种攻击方式,比如有些Web页面字符集不固定,用户输入非期望字符集的字符,有时会绕过转义过滤规则
这种攻击方式的成因是,由于浏览器在meta没有指定charset时有自动识别编码的机制,所以这类攻击通常就是发生在没有指定或者没来得及指定meta标签的charset的情况下
防范措施:
- 指定
<meta charset="utf-8">
- XML中不仅要指定字符集为utf-8,而且标签要闭合
基于Flash的跨站XSS
AS脚本可以接受用户输入并操作cookie,攻击者可以配合其他XSS(持久型或者非持久型)方法将恶意swf文件嵌入页面中
因为AS有时需要和JS传参交互,攻击者就会通过恶意的XSS注入篡改参数,窃取并操作cookie
防范措施:
- 严格管理cookie的读写权限
- 对Flash能接受用户输入的参数进行过滤escape转义处理
未经验证的跳转XSS
有时,后端需要对一个传进来的待跳转的URL参数进行一个302跳转,其中可能带有一些用户的敏感(cookie)信息
如果服务器端做302跳转,跳转的地址来自用户的输入,攻击者可以输入一个恶意的跳转地址来执行脚本
防范措施:
- 对待跳转的URL参数做白名单或者某种规则过滤
- 后端注意对敏感信息的保护,例如对cookie使用来源验证
对抗XSS
预防XSS
输入过滤
在Web应用程序中对用户输入的数据进行过滤和校验,确保只接收合法的数据
例如上例,如果增加对输入进行转义的逻辑,过滤<和>
1 | document.addEventListener('keydown', (e)=> { |
这样就不会被注入脚本了
前后端都要进行过滤,且后端的过滤更为重要
输出转义
在向Web页面中输出用户数据时,对其内容进行适当的编码和转义处理
CSP
全称Content Security Policy,通过设置响应报文头中的CSP策略,限制页面中可执行的脚本来源、样式表、图像、字体等,以此减少恶意代码执行的可能性
配置CSP规则:在服务端生成CSP规则,以HTTP响应头的方式发送给浏览器,例如
1 | // 前端通过meta标签设置 |
这些CSP规则指定了:
- 默认(default-src)只能从当前源(‘self’)加载资源,例如HTML页面、图片、音频、视频等
- 脚本(script-src)只能从当前源(‘self’)和指定的CDN(cdn.example.com)加载JavaScript脚本
- 样式(style-src)只能从当前源(‘self’)和指定的CSS文件(fonts.googleapis.com)加载样式表
这些CSP规则能做到:
- 通过禁止外部脚本(例如第三方广告、恶意脚本等)执行,防止XSS攻击
- 通过禁止外部资源加载,防止敏感数据被窃取、篡改、泄露
- 通过禁止页面嵌入式IFrame,防止点击劫持以至于被钓鱼网站利用
XSS漏洞扫描工具
- wvs
- 椰树
- safe3
- Xelenium
- w3af – Kali
- vega – Kali
- burp
- Kali操作系统
- 主要给渗透工程师、安全审计、安全研究者、逆向工程师、黑客专门使用
- 会提供各种例如XSS、漏洞扫描、SQL注入等工具,以便进行研究学习