
XSS跨站之原理及攻击手法
XSS的产生
XSS原理
跨站脚本攻击是指恶意攻击者往Web页面里插入恶意Script代码,当用户浏览该页之时,嵌入其中Web里面的Script代码会被执行,从而达到恶意攻击用户的目的。
当这些HTML标签引入了一段JavaScript脚本时,这些脚本程序就将会在用户浏览器中执行。所以,当这些特殊字符不能被动态页面检查或检查出现失误时,就将会产生XSS漏洞。
总结后为三点。
①攻击者对含有漏洞的服务器发起XSS攻击(注入JS代码)。
②诱使受害者打开受到攻击的服务器URL。
③受害者在Web浏览器中打开URL,恶意脚本执行。
XSS危害
- 盗取各类用户帐号,如机器登录帐号、用户网银帐号、各类管理员帐号
- 控制企业数据,包括读取、篡改、添加、删除企业敏感数据的能力
- 盗窃企业重要的具有商业价值的资料
- 非法转账
- 强制发送电子邮件
- 网站挂马
- 控制受害者机器向其它网站发起攻击
XSS出现场景
文章发表、评论、留言、注册资料的地方、修改资料的地方等
XSS漏洞分类及各自原理
反射型XSS
攻击者事先制作好攻击链接, 需要欺骗用户自己去点击链接才能触发XSS代码(服务器中没有这样的页面和内容),一般容易出现在搜索页面。
提交 x=xiaodi => x.php => 回包
反射型 XSS漏洞常见于通过 URL 传递参数的功能,如网站搜索、跳转等。
反射型XSS只是简单的把用户输入的数据“反射”给浏览器,也就是说需要诱使用户“点击”一个恶意链接,才能攻击成功。漏洞产生的原因是攻击者注入的数据反映在响应中。非持久型XSS攻击要求用户访问一个被攻击者篡改后的链接,用户访问该链接时,被植入的攻击脚本被用户游览器执行,从而达到攻击目的。
反射型 XSS 的攻击步骤
已知存在XSS漏洞
1. 攻击者构造出包含恶意代码的 URL,通过各种办法发送给终端用户(钓鱼)。
如:构造url为:http://192.168.1.101/submit.php?input_value=“><img src=1 onerror=alert(/xss/)/>
2. 用户打开带有恶意代码的 URL 时,网站服务端将恶意代码从 URL 中取出,拼接在 HTML 中返回给浏览器。
用户访问上述URL触发XSS漏洞,GET方式提交了上述代码,后端处理之后返回前端
3. 用户浏览器接收到响应后解析执行,混在其中的恶意代码也被执行。
存储型XSS
代码是存储在服务器中的,如在个人信息或发表文章等地方,加入代码,如果没有过滤或过滤不严,那么这些代码将储存到服务器中,每当有用户访问该页面的时候都会触发代码执行,这种XSS非常危险,容易造成蠕虫,大量盗窃cookie(虽然还有种DOM型XSS,但是也还是包括在存储型XSS内)。
提交 x=xiaodi => x.php => 写到数据库某个表 => x.php =>回显
存储型 XSS攻击常见于带有用户保存数据的网站功能,如论坛发帖、商品评论、用户私信等。
储存型XSS会把用户输入的数据“储存”在服务器端。这种XSS具有很强的稳定性。持久的XSS危害性大,容易造成蠕虫,因为每当用户打开页面,查看内容时脚本将自动执行。持久型XSS最大的危害在于可能在一个系统中的用户间互相感染,以致整个系统的用户沦陷。能够造成这种危害的脚本我们称之为XSS蠕虫。
存储型 XSS 的攻击步骤
已知存在XSS漏洞
1. 攻击者将恶意代码提交到目标网站的数据库中。
如:留言板提交XSS攻击脚本,并存储到数据库中
2. 用户打开目标网站时,网站服务端将恶意代码从数据库取出,拼接在 HTML 中返回给浏览器。
3. 用户浏览器接收到响应后解析执行,混在其中的恶意代码也被执行。
DOM型XSS
基于文档对象模型(Document Objeet Model,DOM)的一种漏洞。DOM是一个与平台、编程语言无关的接口,它允许程序或脚本动态地访问和更新文档内容、结构和样式,处理后的结果能够成为显示页面的一部分。DOM中有很多对象,其中一些是用户可以操纵的,如URI ,location,refelTer等。客户端的脚本程序可以通过DOM动态地检查和修改页面内容,它不依赖于提交数据到服务器端,而从客户端获得DOM中的数据在本地执行,如果DOM中的数据没有经过严格确认,就会产生DOM XSS漏洞。
提交 x=xiaodi => 本地浏览器静态前端代码 =>x.php
DOM 型 XSS 跟前两种 XSS 的区别:DOM 型 XSS 攻击中,取出和执行恶意代码由浏览器端完成,属于前端 JavaScript 自身的安全漏洞,而其他两种 XSS 都属于服务端的安全漏洞。
DOM通常代表在html、xhtml和xml中的对象,使用DOM可以允许程序和脚本动态的访问和更新文档的内容、结构和样式。它不需要服务器解析响应的直接参与,触发XSS靠的是浏览器端的DOM解析,所以防范DOM型XSS完全就是前端的责任,必须注意!!!。
DOM 型 XSS 的攻击步骤
已知存在XSS漏洞
1. 攻击者构造出特殊的 URL,其中包含恶意代码。
2. 用户打开带有恶意代码的 URL。
3. 用户浏览器接收到响应后解析执行,前端 JavaScript 取出 URL 中的恶意代码并执行。
XSS常规攻击方法
在线XSS平台
各类在线XSS平台,为避免后门,建议自己搭建XSS平台
工具
如Kali下的BeEF-Xss漏洞利用框架
Cookie和Session
cookie实际上是一小段的文本信息。浏览器发送请求到服务器,如果服务器需要记录该用户的状态(比如:用户访问网页的次数,登录状态等),就使用response向客户端浏览器颁发一个cookie。客户端浏览器会把cookie保存起来。当浏览器再次请求该网站时,浏览器就会把请求地址和cookie一同给服务器。服务器检查该cookie,从而判断用户的状态。服务器还可以根据需要修改cookie的内容。
session也是类似的记录用户状态的机制。不同的是cookie保存在客户端浏览器中,而session保存在服务器上。session比cookie安全,别人可以分析存放在本地的cookie并进行cookie欺骗。cookie能保存的数据量比session小;
XSS跨站之代码及HttpOnly绕过
HttpOnly
什么是HttpOnly
如果在Cookie中设置了HttpOnly属性,那么通过js脚本将无法读取到cookie信息,这样能有效的防止XSS攻击
注意:HttpOnly只是阻止js脚本传递Cookie信息,并不能防止XSS漏洞
HttpOnly的绕过
表单劫持
需要注意的是,如果要利用表单劫持,那么XSS漏洞必须出现在登录框所在页面,也即XSS的表单劫持代码必须插入到登录框所在的页面(XSS代码提前写入此页面等待触发),若登录框所在页面不存在跨站漏洞,就无法得到账号密码信息。
直接读取
如果管理员账号密码保存在浏览器,则登录时以及登录后触发了XSS语句(勾选获取浏览器记住的明文密码),都会把账号密码信息发送到XSS后台。
XSS-labs关卡代码过滤绕过测试
Level-2——普通闭合
目的语句:
1 | <input name=keyword value=""><script>alert(1)</script>"> |
提交payload
1 | "><script>alert(1)</script> |
Level-3——过滤尖括号——onclick事件属性
原始input标签
1 | <input name=keyword value='111111'> |
目的input标签(注意value属性的前半个单引号和后半个单引号的闭合)
1 | <input name=keyword value='11111' onclick='alert(1)'> |
我们提交的XSS语句就成为:
1 | 11111' onclick='alert(1) |
因而可以绕过对于提交内容中的尖括号的过滤
Level-5——过滤<script和 on字符——超链接
既要闭合input标签内部,又要使得链接标签写入前端写法如下
原始input标签
1 | <input name=keyword value="3333 "> |
闭合inoput并构造添加一个超链接标签(注意前后双引号闭合)
1 | <input name=keyword value="3333"><a href="javascript:alert(1);">链接文本</a><""> |
则需要提交到搜索框中的部分为
1 | 3333"><a href="javascript:alert(1);">链接文本</a><" |
提交后XSS执行成功
Level-6——<script、on、src、href关键字都会被过滤——大小写绕过过滤
str_replace() 函数以其他字符替换字符串中的一些字符(区分大小写)。
由于区分大小写,这时我们尝试将提交XSS语句中涉及过滤关键字的部分大小写绕过(这里只是单纯过滤关键字,没有使用正则表达式匹配,如果使用了正则匹配,则无法大小写绕过过滤),则XSS语句写成
1 | 3333"><a Href="javascript:alert(1);">链接文本</a><" |
提交后执行成功
Level-7——<script、on、src、href关键字都会被过滤且大小写无法绕过——关键字双写绕过
我们看到过滤代码只进行一次过滤,而非递归或循环过滤,因此我们将涉及的过滤关键字再写一遍插入到原关键字中,使得过滤时触发关键字被替换为空,过滤后又拼组成关键字并带到前端。则XSS语句为
1 | 3333"><a hrhrefef="javascscriptript:alert(1);">链接文本</a><" |
提交后执行成功
Level-8——关键字、大小写、双写无法绕过——Unicode编码绕过
基于以上的过滤手法,我们想到编码绕过思路
在超级加解密工具中选择编码方式为

对提交内容进行编码后在提交,javascript:alert(1);的编码结果如下:
1 | javascript:alert(1); |
提交后点击友情链接,成功触发XSS代码
Level-9——关键字、大小写、双写无法绕过+检查http://
绕过思路
- 编码绕过关键字过滤
- 添加
//http://,满足提交参数包含http://,js语句执行时//后的语句注释掉,以避免影响js语句执行
则XSS代码如下,即在上一关的javascript:alert(1);编码之后添加//http://
1 | javascript:alert(1);//http:// |
提交后添加友情链接,成功触发XSS语句
Level-10——关键字、大小写、双写无法绕过+表单type=“hidden”属性——
我们设法使得表单里的input标签出现onclick鼠标触发事件属性,并且由于需要鼠标点击,那么type属性也不能为hidden,当input标签中同时出现type=“hidden”和type=“text”两种属性时,会执行后者,因此可以添加type=“text”属性到input标签中去
原始input标签如下
1 | <input name="t_sort" value="888" type="hidden"> |
目的input标签如下
1 | <input name="t_sort" value="888" onclick="alert(1)" type="text" type="hidden"> |
则XSS语句如下(GET参数提交)
1 | ?keyword=2222&t_sort=888" onclick="alert(1)" type="text |
提交后点击输入框,成功触发XSS语句
Level-11——$_SERVER[‘HTTP_REFERER’]参数提交拼接
$_SERVER['HTTP_REFERER'];提交的这个参数才会输出到一个type="hidden"的input标签中,且参数值不能出现尖括号
绕过思路和上一关一样,但是提交参数的位置不是GET方式,而是$_SERVER['HTTP_REFERER'];,因此抓包后修改数据包,在HTTP头部中的Referer属性中提交XSS语句payload
原始input标签如下
1 | <input name="t_ref" value="" type="hidden"> |
目的input标签如下
1 | <input name="t_ref" value="" onclick="alert(1)" type="text" type="hidden"> |
则XSS语句如下(数据包中HTTP头部属性Referer中提交)
1 | " onclick="alert(1)" type="text |
抓包修改或添加Refer属性

点击输入框,成功触发XSS语句
Level-12——$_SERVER[‘HTTP_USER_AGENT’]参数提交拼接
设法修改数据包中的User-Agent信息,使之传递XSS语句即可
抓包后将上一关的payload添加到数据包的User-Agent处即
1 | User-Agent: " onclick="alert(1)" type="text |

提交后点击输入框,成功触发XSS语句
XSS跨站之WAF绕过及安全修复
常见WAF绕过思路
一个最经典的WAF绕过的测试思路就是,在提交处对关键字进行拆分,测试WAF匹配拦截的是什么字符。
比如在虚拟机搭建xss-labs平台并开启安全狗进行提交测试,当提交<…>即尖括号且括号内有字符a、j、o等内容时会被拦截
进行绕过WAF测试时,注意既要绕过WAF即避免匹配到关键字,又要使得我们提交的js语句标签闭合
标签语法替换
XSS的payload未必需要使用<script>alert(/xss/)<script>这类语句,还可以使用其他标签进行替换,如:onclick事件属性、超链接、图片链接等其他标签语法
特殊符号干扰
如在提交的payload中加入@#$%^&*等符号进行干扰
提交方式更改
比如后端代码使用$_REQUEST接收数据,WAF只对GET方式的参数数据进行匹配拦截,则完全可以使用POST方式提交参数来绕过WAF。
垃圾数据溢出
payload语句中添加垃圾数据,对WAF检测进行干扰
加密解密算法
比如上节提到的使用Unicode编码后再进行参数提交
结合其他漏洞绕过
在线XSSpayload的Fuzz生成
Fuzzing(模糊测试)是挖掘漏洞最常用的手段之一,不止是XSS,应该可以说Fuzzing可以用于大部分类型的漏洞挖掘。通俗可以把这种方式理解为不断尝试的过程。
XSS语句FUZZ平台:https://xssfuzzer.com/fuzzer.html
自动化XSS工具——XSStrike
略
XSS安全修复方案
开启HttpOnly
输入过滤:对前端提交来的参数进行过滤,比如不接收
<script>输出过滤:后端处理后,对输出到前端的内容进行过滤,比如不输出
<script>PHP、Java的XSS防护方案参考文章