目录
一、反射型、存储型、DOM型XSS特点和区别
0. XSS是什么?
人们本想将跨站脚本攻击(Cross Site Scripting)缩写为CSS,但这会与层叠样式表(Cascading Style Sheets,CSS)的缩写混淆。因此,将跨站脚本攻击缩写为XSS。这就是XSS名字的由来。
XSS攻击是一种经常出现在web应用中的计算机安全漏洞,它允许恶意web用户将代码植入到提供给其他用户的使用界面中,通过代码所执行的不同行为,将Cookie或者其他信息发送给攻击者,攻击者可通过这些信息实施破坏或窃取有效信息为己用。
反射型、存储型和DOM型 XSS 是三种常见的跨站脚本攻击类型,它们的特点和区别如下:
1. 反射型 XSS (Reflected XSS)
通过发送带有恶意脚本代码参数的url,当url地址被打开时,特有的恶意代码参数被html解析、执行。
特点:
-
隐蔽性差。恶意代码存放在url中,没有适当的过滤或转义。只有用户在点击恶意链接的时候才会执行恶意代码,可以直观的看到访问了怎样的站点。
-
非持久化。这种攻击通常是一次性的,即攻击代码不会被存储在服务器上。
2. 存储型 XSS (Stored XSS)
存储型 XSS 也称为持久型 XSS,它发生在应用程序将用户输入的数据存储在服务器端的数据库或其他存储介质中,然后在后续的请求中将其输出到页面中而没有适当的过滤或转义。
恶意语句会进入到目标服务器中,包括但不限于数据库里面,存写进去的方式,比如网站的留言板,个人信息,文章发布等地方,如果这些地方未对传入的数据细致的过滤,就会有储型XSS的产生。
特点:
- 持久性较长,危害性较大。
3. DOM 型 XSS (DOM-based XSS)
DOM 型 XSS 是一种基于客户端的攻击,攻击者通过修改文档对象模型(DOM)来注入和执行恶意代码。
特点:
-
这种攻击不依赖服务器端的响应,而是在客户端 JavaScript 处理数据的过程中发生的。
-
攻击通常发生在客户端的 JavaScript 代码中未正确处理用户输入或未对动态内容进行适当的安全处理。
4. 三者之间的区别
-
反射型 XSS 是一次性的,通过 URL 或表单数据直接反射到响应中。
-
存储型 XSS 是持久的,恶意代码存储在服务器上,并且可能影响多个用户。
-
DOM 型 XSS 是纯客户端的,依赖于客户端 JavaScript 处理,服务器看不到这些攻击代码。
二、XSS的fuzz字典
一个好用的xss fuzz字典:
easyXssPayload/easyXssPayload.txt at master · TheKingOfDuck/easyXssPayload · GitHub
TheKingOfDuck/fuzzDicts: Web Pentesting Fuzz 字典,一个就够了。 (github.com)
这个项目总结了多个Fuzz字典,其中包括参数字典、用户字典、密码字典等,大家可按需下载。
三、XSS挑战靶场过关
3.0 常用的xss语句
<script>alert(1)</script>
<img src=ganyu οnerrοr=alert(1)>
<svg οnlοad=alert(1)>
<a herf=javascript:alert(1)>
<iframe src="javascript:alert(1)"></iframe>
3.1 Level 1
按提示点击图片后,F12查看网站源码,可以发现get传参给name的值“test”插入到了html(h2标签)里,还回显了payload的长度。
其实这里都可以看到第二关的触发条件:在script内,如果alert函数被调用执行,则会弹出提示框,并window.location.href 重定向到level2。
那么直接在url的name参数进行xss注入。构造payload:
<script>alert(1)</script>
成功弹窗,并跳转Level2!
当然传其他的东西也能过关,可以参考XSS常见的触发标签
3.2 Level 2
先插一个payload试试,没成功,查看源码:
可以看到我们插入的payload被嵌套到value属性中,所以我们需要闭合input标签。构造payload:
"><script>alert(1)</script>
成功过关!这关其实是htmlspecialchars($str) 将字符串中的特殊字符转换为了HTML实体,我们只需要闭合掉双引号构造payload即可。
3.3 Level 3
先插再说,插入<script>alert(1)</script>,查看源码:
因为htmlspecialchars() 默认是只编码双引号的,单引号无论如何都不转义。可以看到,相对于上一关,这里是单引号闭合。我们可以构造一个事件,使得事件发生时,则执行JavaScript。可以联想到鼠标点击事件onclinck
。构造payload:
' onclick='alert(1)
添加payload回车后,输入框的就会被添加 onclick属性。点击一下输入框,即可弹窗过关:
3.4 Level 4
查看源码:
可以看到这关是双引号闭合,所以继续利用onfocus事件,构建payload:
" onclick="alert(1)
而后点击输入框即可过关:
3.5 Level 5
先提交查看源码:
试试构造payload为【" οnfοcus=javascript:alert() "】。
发现鼠标事件被加了下划线。那么可用a href标签法,同时还需要闭合input标签。构造payload:
"><a href=javascript:alert(1)>
点击“>"触发a标签href属性。成功弹窗,过关!
3.6 Level 6
插入level5的payload试试:
发现把href属性给过滤了,但没过滤大小写,可通过大小写进行绕过。构造payload:
"><a HrEf=javascript:alert(1)>
3.7 Level 7
先传关键字试试:" OnFocus <sCriPt> <a hReF=javascript:alert()>
查看源码发现,进行了小写转化,并将检测出来的on,script,href给删掉了,我们可以利用双拼写来绕过。构造payload:
"><scrscriptipt>alert(1)</scrscriptipt>
3.8 Level 8
分析发现,我们在输入框输入的内容会被带入到友情链接href
属性中,想到是不是可以直接输入javascript:alert(1)
,然后再点击友情链接。但当输入后发现javascript被过滤了。于是使用HTML实体编码(即Unicode编码)绕过。
将【javascript:alert(1)】通过在线Unicode编码解码进行实体编码,构造payload:
javascript:alert(1)
将其插入href里面:
插入完成后,点击”友情链接“,成功弹窗通关!
3.9 Level 9
思路跟上一关一样,先进行编码绕过。发现之前的绕过方式,但是看到一个友情链接,写上一个正确的http网址可以看到输出在了href属性中,看后台代码发现其实就是http协议校验,于是想到可以巧用js代码中的注释符号 // 。
又发现进行转义了,那就结合编码跟js语言的注释符//配合使用:
javascript:alert("jaden")//http://www.baidu.com
插入href后点击”友情链接“:
3.10 Level 10
没发现输入框,于是查看源代码,看到有hidden把输入框给隐藏了。
把type属性的hidden为text,则会出现输入框。
根据三个input框的name值进行传值发现,t_sort传的值以作为value属性的值渲染到页面上。所以针对name属性为t_sort的input标签进行注入,可以闭合属性,构造新的属性,同时把type="hidden"属性替换。构造payload如下 :
?keyword=1&t_sort=" onclick="alert(1)
四、《漏洞利用之XSS注入》解释
例1:
<a href="%6a%61%76%61%73%63%72%69%70%74:%61%6c%65%72%74%28%31%29"></a>
结果:不执行
解释:首先,浏览器会对HTML进行解析,但在该示例中,href
属性内没有HTML编码的内容,因此直接将内容交给URL模块处理。由于URL模块无法识别被编码的javascript:
协议类型,解码失败,脚本未被执行。
例2:
<a href="javascript%3aalert(3)"></a>
结果:不执行
解释:在这个示例中,javascript:
协议被URL编码为%3a
(即:
字符),当浏览器解析href
属性时,会首先将内容交给URL模块处理。然而,由于javascript:
协议的冒号(:
)部分被编码,URL模块无法正确识别这个协议类型,解码失败,导致脚本无法被执行。这种情况下,与前面的例1相同,浏览器无法正确理解并执行编码后的内容。
例3:
<textarea><script>alert(6)</script></textarea>
结果:不执行
解释:<textarea>
是一个RCDATA元素,这意味着它可以容纳文本和字符引用,但不会解析其中的HTML标签。浏览器在解析<textarea>
标签时,只会将其中的内容视为纯文本,而不会创建新的DOM元素或执行其中的JavaScript代码。因此,虽然在<textarea>
标签内部包含了一个<script>
标签,但这个<script>
标签仅被当作文本处理,JavaScript代码不会被执行。
例4:
<script>\u0061\u006c\u0065\u0072\u0074\u0028\u0031\u0031\u0029</script>
结果:不执行
解释: 在这个例子中,JavaScript代码中的字符通过Unicode转义序列进行了编码。这些序列解码后应该对应于alert(11)
函数调用。然而,由于11
被解析为字符串,而不是有效的数字,并且没有适当的引号将其封闭,因此导致JavaScript语法错误,脚本无法正确执行。
例5:
<script>alert('13\u0027')</script>
结果:不执行
解释:在这个示例中,'\u0027'
代表的是单引号字符。在JavaScript解析过程中,Unicode转义序列\u0027
会被解码为普通的单引号字符。然而,由于这个单引号与其他字符串引号冲突,导致字符串没有被正确关闭,进而引发语法错误,导致脚本无法执行。这种情况下,浏览器会将其视为无效的JavaScript代码。