一、XSS分类
XSS全称:跨站脚本(Cross Site Scripting) ,为了不和层叠样式表(Cascading Style Sheets)的缩写CSS混合,所以改名为XSS;攻击者会向web页面(input表单、URL、留言版等位置)插入恶意JavaScript代码,导致管理员/用户访问时触发,从而达到攻击者的目的。
xss攻击可分为三类:1.反射性XSS; 2.存储型XSS; 3.DOM型XSS。其特点和区别如下:
反射型XSS(非持久型)
- 非持久性:攻击载荷(payload)不会存储在目标服务器上,而是通过URL参数、表单字段或HTTP头等方式传送到受害者的浏览器并执行。
- 特定性:被攻击对象是特定的,通常需要通过诱导受害者点击一个包含恶意脚本的链接来触发攻击。
- 即时性:攻击效果通常是一次性的,即一旦受害者点击了恶意链接,脚本就会执行,但攻击不会持续存在。
存储型XSS(持久型)
-
持久性:攻击脚本被永久地存放在目标服务器的数据库或文件中,只要受害者访问了含有该恶意脚本的页面,攻击就会持续发生。
-
隐蔽性:由于攻击脚本存储在服务器上,因此具有很高的隐蔽性,难以被轻易发现。
-
危害面广:由于攻击脚本的持久性,它可能影响到所有访问该页面的用户,甚至可能导致用户机器成为DDoS攻击的肉鸡,或被盗取敏感私密信息。
DOM型XSS
-
客户端执行:DOM型XSS完全在客户端执行,不涉及服务器端的任何改变。攻击者通过修改页面的DOM结构来触发执行恶意脚本。
-
动态内容:攻击通常与网页的动态生成内容有关,如JavaScript生成的内容。
-
隐蔽性:由于攻击发生在客户端,服务器端的日志可能不会记录任何异常,这使得检测和追踪变得更加困难。
区别
反射型XSS | 存储型XSS | DOM型XSS | |
---|---|---|---|
存储位置 | 不存储在服务器上,通过URL等传输 | 存储在服务器数据库或文件中 | 不涉及服务器端存储,完全在客户端执行 |
攻击对象 | 特定用户,需要受害者点击恶意链接 | 访问页面的所有用户 | 访问页面的用户,但与DOM操作相关 |
持久性 | 非持久性,一次性攻击 | 持久性,长期影响 | 不涉及服务器端存储,但攻击效果可能持续(如果页面持续被访问) |
隐蔽性 | 较低,攻击载荷在URL中可见 | 较高,攻击脚本存储在服务器上 | 较高,服务器端日志可能无记录 |
防御难度 | 中等,需防止恶意链接传播 | 较高,需检查所有用户输入并进行转义处理 | 中等至高,需关注客户端DOM操作的安全性 |
二、XSS的fuzz字典
fuzz字典下载地址
https://github.com/TheKingOfDuck/fuzzDicts
fuzzDicts: Web Pentesting Fuzz 字典,一个就够了。
三、挑战XSS靶场打靶
(要求通过5关以上,通关越多,加分越多。地址:https://xss.tesla-space.com/)
level 1 直接注入
查看源码可知,让浏览器蹦出弹窗即可进入下一关。
可直接注入:
/level1.php?name=<script>alert(1)</script>
level 2 闭合绕过
简单注入,查看源码:
发现我们的语句被过滤,可使用使用"> <"闭合。payload:
"><script>alert(1)</script>
实现了html实体转化:
level 3 利用鼠标属性
正常注入,查看源码:
发现>
、<
都被过滤掉了,但是没有将预定义字符转义,那么我们也可以构造一个事件进行绕过,这里需要用双引号进行属性闭合。
payload:
' οnclick='alert(1)
然后输入框的就会被添加 onclick 属性,我们点击一下输入框,即可过关。
level 4 加过滤
和第三关相似,但在第三关的基础上添加了对尖括号的过滤。
payload:
" οnclick="alert(1)
level 5 再加过滤
注入正常的JavaScript代码,查看页面源代码
发现语句被破坏。尝试发现 <script 和 <on 均被过滤,可以用a标签的 href 属性来构造。
href属性的意思是 当标签<a>被点击的时候,就会触发执行转跳,上面是转跳到一个网站,我们还可以触发执行一段js代码
payload
"><a href=javascript:alert(1)>test</a>
# javascript:alert(1) 使用了java伪协议,就是把javascript: 后面的代码当JavaScript来执行
level 6 大小写
过滤的更多,但是大小写可以绕过。
"><a hRef=javascript:alert(1)>test</a>
level 7 双写绕过
输入关键字试试。
" OnFocus <sCriPt> <a hReF=javascript:alert()>
发现输入的href, script都被过滤了,大小写也全部转为了小写。但过滤不严谨,我们可以双写绕过。
比如on,我们可以写成oonn,当中间on被删掉的时候,就变成了on。
比如script,可以写成scscriptipt,当script被删掉的时候,就变成了script
"><a hrhrefef=javascscriptript:alert(1)>test</a>
四、总结浏览器解析机制
html的解析器类似于一个状态机,会获取字符并按照转换规则转换到另一种状态,在解析的过程中,遇到了 < 就会进入标签开始的状态,然后就到了标签名状态,再是前属性名,最后进入数据状态。
在xss中我们很多页面都把 < > 等符号进行了html实体化的操作,这样就可以防护xss。因为当解析器遇到 & 的时候,它知道这是数据状态的字符引用,所以会消耗一个字符引用,把 html 实体编码,变成对应的字符。但是这时候在解析这个字符时,不会转换到标签的开始状态的,所以用户输入的数据只能解析成数据了。在html解析中只有遇到 < 才会进入标签开始的状态,所以 这里 html 实体编码变成 < 之后, html 解析器不会再从头去读 html解析器,会继续往后进行解析,这样,没有标签开始的状态,当中的恶意代码是不会被html 解析的,也就是不会执行当中的代码。