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
2
3
4
5
const params = new URLSearchParams(location.search)
const name = params.get('a')
console.log(name)
document.write(name)
<script>alert(114514)</script>

黑客可能会通过注入恶意script脚本,或引入外部木马,实现读取用户cookie或其他用户信息

防范措施

  • Web页面渲染的所有内容或者渲染的数据都必须来自于服务端
  • 尽量不要从URL、document.referrer``document.forms等这种 DOM API中获取数据直接渲染
  • 尽量不要使用evalnew Function()document.write()document.writeln()window.setInterval()window.setTimeout()innerHTMLdocument.creteElement()等可执行字符串的方法
  • 如果做不到以上几点,也必须对涉及DOM渲染的方法传入的字符串参数做escape转义
  • 前端渲染的时候对任何的字段都需要做escape转义编码

存储型XSS

存储型/HTML注入型/持久性XSS攻击最常发生在由社区内容驱动的网站或Web邮件网站,不需要特制的链接来执行

攻击脚本将被永久地存放在目标服务器端(数据库,内存,文件系统等),下次请求目标页面时不用再提交XSS代码

黑客仅需要提交XSS漏洞利用代码到一个网站上其他用户可能访问的地方,这些地方可能是博客评论、用户评论、留言板、聊天室、HTML、电子邮件、wikis和其他许多地方

一旦用户访问到受感染的页面,就会自动执行漏洞;因为这些页面是开放的,而且往往是用户信任的页面,所以是影响最严重的

存储型XSS更具有隐蔽性,带来的危害也更大,除非服务器能完全阻止注入,否则任何人都很有可能受到攻击

特点

  • 持久性,植入在数据库中
  • 危害面广,甚至可以让用户机器变成DDoS攻击的肉鸡
  • 盗取用户敏感私密信息

案例

在评论区输入一段script代码点击发送时,如果前端和后端都没有进行过滤操作,这段代码就会被注入到数据库;当有其他人读取评论时,这段代码就会被拉取到他的页面

1
2
3
4
5
6
7
8
9
10
11
12
13
var a = document.getElementById('a')
// a.value = "<script>alert(1)</script>"
// a.value = '<img src="1" onerror="alert(1)">'
ajax({
url: 'http://localhost:3000/xss',
type: 'post',
data: {
a: a.value
},
success: function(data) {
console.log(data)
}
})

防范措施

  • 后端在入库前应该选择不相信任何前端数据,将所有的字段统一进行转义处理
  • 后端在输出给前端数据统一进行转义处理
  • 前端在渲染页面DOM的时候应该选择不相信任何后端数据,任何字段都需要做转义处理

DOM型XSS

DOM型/客户端XSS攻击基于Web应用程序中的JavaScript脚本语言与HTML的交互性质(即DOM文档对象模型操作)实现

攻击者会通过Web应用程序中的某个页面向用户提供构造好的特殊URL,当用户访问该URL时,浏览器会执行其中的JavaScript代码,攻击者利用该机制就可以注入恶意代码到当前页面、篡改现有页面内容、盗取用户个人信息

与其他XSS攻击类型不同的是,DOM型XSS不会触发HTTP请求或响应过程,它的攻击载荷不会被传递到服务端,而是直接在客户端执行,这使它更加难以检测和防范

案例

黑客会尝试在页面上的所有input框中进行XSS注入

1
2
3
4
5
6
7
// dom xss注入
document.addEventListener('keydown', (e)=> {
if(e.keyCode == 13) {
let value = document.getElementById('a').value.value
document.body.innerHTML += value
}
})

如果像上述代码一样,不安全的使用了那些危险属性和方法,就可能造成危险

防范措施

为了防止DOM型XSS攻击,可以对输入的数据进行过滤和转义处理、限制用户的输入行为、避免使用危险的JavaScript属性或方法,例如locationinnerHTMLdocument.write、Vue的v-htmleval

基于字符集的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
2
3
4
5
6
7
8
9
document.addEventListener('keydown', (e)=> {
if(e.keyCode == 13) {
let value = document.getElementById('a').value
// 转义,把<和>替换成HTML字符实体
value = value.replace(/</g, '&lt;').replace(/>/g, '&gt;')
document.body.innerHTML += value
}
})
// 或者直接使用npm的xss库,免除手搓烦恼

这样就不会被注入脚本了

前后端都要进行过滤,且后端的过滤更为重要

输出转义

在向Web页面中输出用户数据时,对其内容进行适当的编码和转义处理

CSP

全称Content Security Policy,通过设置响应报文头中的CSP策略,限制页面中可执行的脚本来源、样式表、图像、字体等,以此减少恶意代码执行的可能性

配置CSP规则:在服务端生成CSP规则,以HTTP响应头的方式发送给浏览器,例如

1
2
3
4
// 前端通过meta标签设置
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' cdn.example.com; style-src 'self' fonts.googleapis.com;">
// 后端通过请求头设置
Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.example.com; style-src 'self' http://fonts.googleapis.com;

这些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注入等工具,以便进行研究学习