一、XSS漏洞原理
XSS指跨站脚本攻击,主要基于javascript语言完成恶意的攻击行为,因为javascript可以非常灵活的操作html、css和浏览器。XSS利用网页开发时留下的漏洞,巧妙的将恶意代码注入到网页中,因为浏览器不会判断代码是否恶意,只要代码符合语法规则,浏览器就会解析这段XSS代码,以达到攻击的效果。
微博、留言板、聊天室等收集用户输入的地方,都有遭受XSS的风险。
前提条件:
1.需要向Web页面注入精心构造的恶意代码
2.对用户的输入没有做过滤,恶意代码能够被浏览器成功的执行
XSS危害:
1.盗取各种用户账号
2.窃取用户Cookie资料,冒充用户身份进入网站
3.劫持用户会话,执行任意操作
4.刷流量,执行弹窗广告
5.传播蠕虫病毒
6.攻击者能在一定限度内记录用户的键盘输入
二、XSS分类
1.反射型XSS
反射型XSS是一种非持久型XSS,是最容易出现的一种XSS漏洞。用户在请求某条URL地址的时候,会携带一部分数据。当客户端进行访问某条链接时,攻击者可以将恶意代码植入到URL,如果服务端未对URL携带的参数做判断或者过滤处理,直接返回响应界面,那么XSS攻击代码就会一起被传输到用户的浏览器,从而触发反射型XSS。
流量走向:浏览器——>后端——>浏览器
2.存储型XSS
存储型XSS是持久型XSS,它是危害最大的一种。该类型的XSS漏洞是由于恶意攻击代码被持久化保存在服务器上,然后显示到HTML页面之中。攻击者精心构造XSS代码,保存到数据库中,当其他用户再次访问这个页面,就会触发并执行恶意的XSS代码,从而达到攻击者想要的目的。
流量走向:浏览器——>后端——>数据库——>后端——>浏览器
3.DOM型XSS
DOM型XSS与之前两种在原理上有本质区别,它的攻击代码并不需要服务器解析响应,触发XSS靠的是浏览器端的DOM解析。客户端上的JavaScript脚本可以直接访问浏览器的DOM并修改页面的内容。在客户端直接输出DOM内容的时候极易触发DOM型XSS漏洞。
流量走向:URL——>浏览器
4.三种XSS的区别
被攻击对象的不同
反射型XSS的被攻击对象一般是攻击者去寻找的,而存储型XSS是广撒网的方式或者指定的方式,就是攻击者将存储型XSS放在一些有XSS漏洞的网站上,只要有用户访问这个链接就会中招,而攻击者也可以寻找被攻击对象,比如说上面的例子,所以我们可以看出,存储型XSS的危害性更大,范围更广,可以不需要寻找被攻击对象,只要存储型XSS在服务器上就能实施攻击。
DOM型XSS的被攻击对象其实和反射型XSS被攻击对象差不多,就是给攻击对象放送URL。
解析位置不同
反射型XSS的脚本被解析的地方是浏览器,而存储型XSS的脚本被解析的地方是服务器,DOM型XSS也是浏览器,所以DOM型又叫DOM反射型XSS。但是反射型XSS需要联网,而DOM型不需要!
存储时间不同
反射型XSS是既有即用,没有持久性,而存储型XSS是存储在服务器上,只要服务器不挂机或者是被干掉,就一直会有,DOM型XSS和反射型差不多,但是用人就扯淡了,那反射型只要不改变源代码不就是一直存在吗?不是的,反射型XSS是必须得特定的URL才能使得被攻击对象中招,如果是单单官方网页,就没有了咯,存储型就不同,只要服务器里面有存储型XSS,不论是不是官网,被攻击对象都会被攻击。
允许输入点的不同
一般情况下,反射型XSS在搜索框啊,或者是页面跳转啊这些地方,而存储型XSS一般是留言,或者用户存储的地方,而DOM呢?是在DOM位置上,不取决于输入环境上。
三、Fuzz字典
Fuzz字典下载
https://github.com/fuzzdb-project/fuzzdb
https://github.com/TheKingOfDuck/fuzzDicts
https://github.com/TuuuNya/fuzz_dict
https://github.com/jas502n/fuzz-wooyun-org
Fuzz字典生成工具
配置
需要python2环境
工具地址:https://github.com/c0ny1/upload-fuzz-dic-builder
四、XSS挑战靶场
第一关
修改地址栏中的name=
第二关
输入js代码不可行
查看源代码,发现提交的参数被存储在value属性中
闭合input值,再插入js代码
第三关
输入第二关代码,发现不可行
查看源代码,发现此处被编码
将双引号修改为单引号,发现可以闭合了但还是被编码
于是输入'οnclick='alert(1)语句
第四关
先输入"<script>alert(1)</script><"
查看源代码,发现<>被替换为空格
输入"οnclick="alert(1)语句
第五关
先输入"><script>alert(1)</script><"测试
查看源代码,发现<script>被修改为<scr_ipt>
输入" onclick = alert(1)"发现onclick也被修改为o_nclick
可以不使用<script>,使用标签链接里的javascript:伪协议执行js代码,点击插入的链接出现弹窗
第六关
依次尝试"><script>alert(1)</script><" 发现<script>变为<scr_ipt>
" onclick = alert(1)" onclick变为o_nclick
"> <a href="javascript:alert(1)”><" href变为hr_ef
但是因为HTML语言是不区分大小写,所以可以进行大小写转换
"> <a HrEF="javascript:alert(1)"><"
第七关
依次尝试"><script>alert(1)</script><" 发现script被替换为空格或删除
" onclick = alert(1)" on被替换为空格或删除
"> <a href="javascript:alert(1)”><" href和javascript中的script被替换为空格或删除
且更换大小写也不行
但可以通过复写进行绕过,将script改为sscriptcript
"><sscriptcript>alert(1)</sscriptcript>
第八关
输入 "><script>alert((1)</script>"测试
查看源代码,发现 < > "符号被编码且大小写都不可行
利用编码网站,对javascript:alert(1)进行编码
五、浏览器解析机制
①
<a href="%6a%61%76%61%73%63%72%69%70%74:%61%6c%65%72%74%28%31%29">aaa</a>
分析:a标签中的href属性放的是url,然后现在里面全是url编码,URL模块解码出来就是javascript:alert(1),因为是url解码后才能看到javascript所以最后没识别到这个协议,即alert没被执行
结果:执行失败
②
<a href="javascript:%61%6c%65%72%74%28%32%29">
分析:先通过HTML解码得到javascript:%61%6c%65%72%74%28%32%29,再丢给URL模块,URL模块识别到Javascript协议,把:后边的内容解码后丢给js的模块去处理
结果:执行成功
③
<a href="javascript%3aalert(3)"></a>
分析:和①类似,URL识别到完整的javascript:后才能识别出这个协议
结果:执行失败
④
<div><img src=x onerror=alert(4)></div>
分析:&.#60(打了个.防止csdn给我解码了)是< ,&.#62是> HTML实体编码把这俩转化成尖括号后token就被消耗掉了所以并不会进入到标签开始状态,自然<img>里面的内容也失效了
结果:执行失败
⑤
<textarea><script>alert(5)</script></textarea>
分析:这个看起来和④差不多,但其实<textarea>与<title>都是RCDATA元素,即在这俩标签里面,不可能有别的标签存在,所以最后也会把<>变成实体编码
结果:执行失败
⑥
<textarea><script>alert(6)</script></textarea>
分析:这里与⑤做对照,就算<>不用html实体编码,最后也不会识别到<script>标签
结果:执行失败
⑦
<button onclick="confirm('7');">Button</button>
分析:html实体解码后得到'7'然后有js的函数confirm就会丢给js模块去处理
结果:执行成功
⑧
<button onclick="confirm('8\u0027);">Button</button>
分析:confirm函数里面用了unicode编码,没别的编码了,所以会解析过后会丢给js模块去处理,但是unicode只能用来表示字符串和标识符,所以最后右边的'没有解析成功
结果:执行失败
⑨
<button onclick="confirm('8\u0027);">Button</button>
分析:html实体解析完后<script>中间的内容是alert(1)乍一看应该能执行,但是<script>是原始文本元素,只能放文本内容,在这里的话里面的东西html不会解析,会直接以文本格式丢给js模块去处理,js不认识html实体编码
结果:执行失败
⑩
<script>\u0061\u006c\u0065\u0072\u0074(10);</script>
分析:<script>原始文本元素,丢给js模块去处理,解析出来的alert函数是个标识符,直接就执行了
结果:执行成功
⑪
<script>\u0061\u006c\u0065\u0072\u0074\u0028\u0031\u0031\u0029</script>
分析:类似于⑧,虽然看起来能解析出个alert(10)但是()不在标识符范围内,js解析执行失败
结果:执行失败
⑫
<script>\u0061\u006c\u0065\u0072\u0074(\u0031\u0032)</script>
分析:与⑪做比较,js模块解析出来alert(12)看起来没什么问题,但是这里12是两个unicode编码,意思就是字符串,字符串是必须要''才能执行的
结果:执行失败
⑬
<script>alert('14\u000a')</script>
分析:\u000a解码后就是换行,解码出来直接执行
结果:执行成功
⑭
<a href="javascript:%5c%75%30%30%36%31%5c%75%30%30%36%63%5c%75%30%30%36%35%5c%75%30%30%37%32%5c%75%30%30%37%34(15)"></a>
分析:先进行html解码得到<a href="javascript:%5c%75%30%30%36%31%5c%75%30%30%36%63%5c%75%30%30%36%35 %5c%75%30%30%37%32%5c%75%30%30%37%34(15)"></a>
再进行URL解码得到
javascript:\u0061\u006c\u0065\u0072\u0074(15)
因为被URL模块识别到js协议了,所以丢给js模块解码
javascript:alert(15)
结果:执行成功