1. 反射型、存储型、DOM型XSS特点和区别
1.1 反射型(非持久型跨站)
反射型跨站脚本漏洞,最普遍的类型。用户访问服务器-跨站链接-返回跨站代码。
这种攻击往往具有一次性。攻击者通过邮件等形式将包含XSS代码的链接发送给正常用户,当用户点击时,服务器接受该用户的请求并进行处理,然后把带有XSS的代码发送给用户。用户浏览器解析执行代码,触发XSS漏洞。
- 产生层面:前端
- 漏洞特征:一次性的、前端执行、不会储存在后端数据库
- 危害等级:中
反射型XSS攻击原理
1.2 存储型(持久型跨站)
最直接的危害类型,跨站代码存储在服务器(数据库)。
- 产生层面:后端
- 漏洞特征:持久1.3性的、前端执行、储存在后端数据库
- 危害等级:高
攻击脚本存储在目标服务器的数据库中,具有更强的隐蔽性。攻击者在论坛、博客、留言板中,发帖的过程中嵌入XSS攻击代码,帖子被目标服务器存储在数据库中。当用户进行正常访问时,触发XSS代码。例如下图:
1.3 DOM跨站(DOM XSS)
DOM(document object model文档对象模型),客户端脚本处理逻辑导致的安全问题。
DOM是一个与平台、编程语言无关的接口,它允许程序或脚本动态地访问和更新文档内容、结构和样式,处理后的结果能够成为显示页面的一部分。DOM中有很多对象,其中一些是用户可以操纵的,如URI ,location,refelTer等。客户端的脚本程序可以通过DOM动态地检查和修改页面内容,它不依赖于提交数据到服务器端,而从客户端获得DOM中的数据在本地执行,如果DOM中的数据没有经过严格确认,就会产生DOM XSS漏洞。
- 产生层面:前端、特殊的反射型XSS
- 漏洞特征:一次性的、前端执行、不会储存在后端数据库、程序执行不依赖于服务器端的数据;web server不参与,仅仅涉及到浏览器的XSS。
- 危害等级:中
1.4 三种XSS的区别
1.4.1 被攻击对象的不同
反射型XSS的被攻击对象一般是攻击者去寻找的,就比如说:一个攻击者想盗取A的QQ号,那么攻击者就可以将一个含有反射型XSS的URL链接给A,此时我们可以看出,需要将特定的URL,注意是特定的URL给A,当A点击进入链接时,就受到XSS攻击,所以这种攻击范围不是特别的广。
而存储型XSS是广撒网的方式或者指定的方式,就是攻击者将存储型XSS放在一些有XSS漏洞的网站上,只要有用户访问这个链接就会中招,而攻击者也可以寻找被攻击对象,比如说上面的例子,所以我们可以看出,存储型XSS的危害性更大,范围更广,可以不需要寻找被攻击对象,只要存储型XSS在服务器上就能实施攻击。
DOM型XSS的被攻击对象其实和反射型XSS被攻击对象差不多,就是给攻击对象放送URL。
1.4.2 解析位置不同个人感觉是反射型与存储型区别的本质)
反射型XSS的脚本被解析的地方是浏览器,而存储型XSS的脚本被解析的地方是服务器,DOM型XSS也是浏览器,所以DOM型又叫DOM反射型XSS。但是反射型XSS需要联网,而DOM型不需要。
1.4.3 存储时间不同
反射型XSS是既有即用,没有持久性,而存储型XSS是存储在服务器上,只要服务器不挂机或者是被干掉,就一直会有,DOM型XSS和反射型差不多,但是用人就扯淡了,那反射型只要不改变源代码不就是一直存在吗?不是的,反射型XSS是必须得特定的URL才能使得被攻击对象中招,如果是单单官方网页,就没有了咯,存储型就不同,只要服务器里面有存储型XSS,不论是不是官网,被攻击对象都会被攻击。
1.4.4 允许输入点的不同(这是DOM型与其他两种的区别)
一般情况下,反射型XSS在搜索框啊,或者是页面跳转啊这些地方,而存储型XSS一般是留言,或者用户存储的地方,而DOM是在DOM位置上,不取决于输入环境上。
2. XSS 的fuzz字典
2.1 fuzz字典生成工具
工具地址:https://github.com/c0ny1/upload-fuzz-dic-builder
环境要求:需要python2环境
使用方法:
- $ python upload-fuzz-dic-builder.py -h
- usage: upload-fuzz-dic-builder [-h] [-n] [-a] [-l] [-m] [--os] [-d] [-o]
- optional arguments:
- -h, --help show this help message and exit
- -n , --upload-filename
- Upload file name
- -a , --allow-suffix Allowable upload suffix
- -l , --language Uploaded script language
- -m , --middleware Middleware used in Web System
- --os Target operating system type
- -d, --double-suffix Is it possible to generate double suffix?
- -o , --output Output file
2.1.1 Example1
生成适合全语言,全部中间件,全部操作系统的fuzz字典
- python upload-fuzz-dic-builder.py
2.1.2 Example2
生成适合后端语言为asp
的fuzz字典
- python upload-fuzz-dic-builder.py -l asp
2.1.3 Example3
上传文件名为:test
,可以上传后缀为jpg
,后端语言为php
,中间件为apache
,操作系统为Windows
,输出字典名为upload_filename.txt
的fuzz字典
- python upload-fuzz-dic-builder.py -n test -a jpg -l php -m apache --os win -o upload_file.txt
2.1.4 Attention
- 生成时给的上传点相关信息越详细,生成的字典越精确!
- 在使用burp的Intruder模块进行fuzz时将Payload面板中
Payload Encoding
一栏的URL-encode these characters
选项设置为未选中状态。
2.2 Fuzzing字典(不定期更新)
地址:GitHub - TheKingOfDuck/fuzzDicts: Web Pentesting Fuzz 字典,一个就够了。
内容包括:参数Fuzz字典 Xss Fuzz字典 用户名字典 密码字典 目录字典 sql-fuzz字典 ssrf-fuzz字典 XXE字典 ctf字典 Api字典 路由器后台字典 文件后缀Fuzz js文件字典 子域名字典
Xss Fuzz字典地址:easyXssPayload/easyXssPayload.txt at master · TheKingOfDuck/easyXssPayload · GitHub
3. XSS挑战靶场打靶(https://xss.tesla-space.com/)
3.1 level1
1. 观察题目,发现用户名在url
处被提交,且输出用户名的长度为4
2. 查看源码,发现get传参name的值test插入了html里头,还回显了payload的长度4。
3. 直接修改name参数:
- <script>alert(1)</script>
3.2 level2
1. 观察页面提示,与level1的不同之处在于有了搜索框。尝试使用与上一关相同的参数。
2. 查看源码,发现特殊符号被html实体转义了,但是value的值没有被实体转义。
3. 右键检查搜索框的代码,发现只需要把value的< > 和 "闭合掉即可。
4. 在搜索框中输入:
- "> <script>alert(1)</script> <"
3.3 level3
1. 先在输入框输入test测试一下,发现,上面keyword的值变成test,payload的值也变成4。
2. 查看一下网页源码,发现value的值被单引号闭合。
3. 相对于上一关,这里是单引号闭合,试一下看看
- '> <script>alert()</script> <'
查看代码,发现符号也被实体化了。
4. 还可以利用其他方法进行xss注入,这里可以利用onfocus事件绕过
简单介绍一下onfocus事件:
onfocus事件在元素获得焦点时触发,最常与 <input>、<select> 和 <a> 标签一起使用,以下图的html标签<input>为例,<input>标签是有输入框的,简单来说,onfocus事件就是当输入框被点击的时候,就会触发myFunction()函数,然后我们再配合javascript伪协议来执行javascript代码
所以我们可以利用这个事件来绕过<>号的过滤已达到执行js的目的,构造payload
- ' οnfοcus=javascript:alert(1) '
再次点击输入框,触发onfocus事件即可。
3.4 level4
1. 还是老样子,在输入框输入test测试一下,发现上面keyword的值变成test,payload的值变成4。
2. 查看网页源码,发现value从单引号变成双引号闭合了。
3. 还是<input>标签,所以还能继续利用onfocus事件,构建payload
- " οnfοcus=javascript:alert() "
4. 和上一关一样,再次点击输入框,触发onfocus事件即可。
3.5 level5
1. 还是老样子,在输入框输入test测试一下,发现上面keyword的值变成test,payload的值变成4。
2. 查看网页源码,发现value还是双引号闭合。
3. 尝试一下上一关的做法,发现没反应。
再次查看网页源码,发现on被替换成了o_n,被加了下划线。
4. 查看服务器端源码
- 发现将get方式传递到服务器端的keyword参数的值进行全小写的转换,然后赋值给str变量。
- 通过str_replace()函数来破坏变量值中的敏感字符的语义。
- 通过htmlspecialchars()函数处理之后显示到网页上。
- 直接将进行敏感字符处理之后的变量值插入到<input>标签的value属性值中。
因此我们需要换一个标签来执行js代码,这里用a href标签法。
href属性的意思是 当标签<a>被点击的时候,就会触发执行转跳,上面是转跳到一个网站,我们还可以触发执行一段js代码。
5. 还需要闭合前面和后面的< > " 标签,从而构建payload
- "> <a href=javascript:alert()>xxx</a> <"
6. 点击"xxx"链接即可出现弹窗。