Cross-Site Scripting(跨站脚本攻击)简称XSS,是一种代码注入攻击。为了和CSS区分,这里将其缩写的第一个字母改成了X,于是叫做XSS。恶意攻击者在web页面里插入恶意JavaScript代码,当浏览者浏览网页时就会触发恶意代码,从而导致用户数据的泄露如Cookie、SessionID等,及造成其他类型的攻击。
XSS的本质是:恶意代码未经过滤,与网站正常代码混在一起,浏览器无法分辨哪些脚本是可信的,导致恶意脚本被执行。从源头上讲,就是代码和数据被攻击混淆,导致浏览器将攻击者输入的数据解释为代码。
对于下面的代码
">
<button>搜索button>
<div>
您搜索的关键词是:<%= getParameter("keyword") %>
div>
当构造链接:
http://xxx/search?keyword=">
浏览器请求该链接时,服务端会解析出参数keyword,得到">
,拼接后,得到:
<input type="text" value=""><script>alert('XSS');script>">
<button>搜索button>
<div>
您搜索的关键词是:"><script>alert('XSS');script>
div>
因为参数中的数据和页面代码产生了混淆,浏览将用户参数中的,解析为代码执行。
修复这个问题可以对用户输入参数进行转义。
使用函数escapeHTML()
">
<button>搜索button>
<div>
您搜索的关键词是:<%= escapeHTML(getParameter("keyword")) %>
div>
escapeHTML()
的转义规则为:
字符 | 转义后的字符 |
---|---|
& |
& |
< |
< |
> |
> |
" |
" |
' |
' |
/ |
/ |
经过转义,浏览器就可以很好的区分用户提交的数据和页面中的代码。
<input type="text" value=""><script>alert('XSS');</script>">
<button>搜索button>
<div>
您搜索的关键词是:"><script>alert('XSS');</script>
div>
- 用户输入的为数据,目的是以文本显示出来
- 攻击者利用输入精心构造的片段,导致代码和数据混淆,使得浏览器将用户输入解析为代码
- 通过HTML转移可以防止XSS攻击
有时仅仅做HTML转义也是不够的。如:如果将JSON内联在HTML中
<script>
var initData = <%= data.toJSON() %>
script>
这时就不能使用escapeHTML()
,因为会破坏JSON格式。
但此时并不安全
U+2028
或 U+2029
这两个字符时,不能作为 JavaScript 的字面量使用,否则会抛出语法错误。
时,当前的 script 标签将会被闭合,后面的字符串内容浏览器会按照 HTML 进行解析;通过增加下一个
标签等方法就可以完成注入。所以我们要丢此种情景单独进行转义。
字符 | 转义后的字符 |
---|---|
U+2028 | \u2028 |
U+2029 | \u2029 |
< | \u003c |
根据不同的场景需要采用不同的转义规则
避免自己写转义库,可能出现考虑不到的地方,尽量使用成熟、通用的转义库
有时就算是做了所有的转义,但是还是可能存在XSS,如对于下面代码:
">跳转...a>
构造链接:
http://xxx/?redirect_to=javascript:alert('XSS')
此时,服务端的响应为:
<a href="javascript:alert('XSS')">跳转...a>
在点击a
标签时,实现了XSS。
因在在于用户输入的并不是我们预期的数据。这里可以采取白名单策略,过滤非期望输入。
对用户输入数据做要求限制,过滤非期望的输入
做黑名单要考虑完全,如果考虑不周,可能会被绕过。如,上面的例子,如果仅仅过滤
JavaScript
,那么利用大小写就可以绕过。
XSS攻击可以分为三类,反射性、存储型和DOM型。
类型 | 存储区 | 插入点 |
---|---|---|
存储型 XSS | 后端数据库 | HTML |
反射型 XSS | URL | HTML |
DOM 型 XSS | 后端数据库/前端存储/URL | 前端 JavaScript |
存储区:恶意代码存放位置
插入点:由谁取得恶意代码,并插入网页
攻击步骤:
攻击常见于通过 URL 传递参数的功能,如网站搜索、跳转等。
POST请求也可以触发反射型XSS,但触发条件苛刻,较少见。
攻击步骤:
攻击常见于带有用户保存数据的网站功能,如论坛发帖、商品评论、用户私信等。
反射型 XSS 跟存储型 XSS 的区别是:存储型 XSS 的恶意代码存在数据库里,反射型 XSS 的恶意代码存在 URL 里。
攻击步骤:
DOM 型 XSS 跟前两种 XSS 的区别:DOM 型 XSS 攻击中,取出和执行恶意代码由浏览器端完成,属于前端 JavaScript 自身的安全漏洞,而其他两种 XSS 都属于服务端的安全漏洞。
如果用户在评论去输入
"评论“
<script>alert("XSS")script>
如果没有任何防御措施,最终会解析为:
HTML属性/参数
如上面说到的
当用户输入的地址为:
就会构成XSS。
JavaScript代码
如果用户输入为JavaScript中的变量,则可以被精心构造,导致字符串提前关闭,实现注入。
它能够检测到存在于 HTML 属性、HTML 文字内容、HTML 注释、跳转链接、内联 JavaScript 字符串、内联 CSS 样式表等多种上下文中的 XSS 漏洞,也能检测
eval()
、setTimeout()
、setInterval()
、Function()
、innerHTML
、document.write()
等 DOM 型 XSS 漏洞,并且能绕过一些 XSS 过滤器。只要在网站的各输入框中提交这个字符串,或者把它拼接到 URL 参数上,就可以进行检测。
检测工具:
引用