RPO相对路径覆盖攻击

0x01 RPO简介

RPO(Relative Path Overwrite)相对路径覆盖,是一种利用相对URL路径覆盖目标文件的一种攻击手段。
该攻击方法利用浏览器和服务器对资源加载设置的差异,通过某些方法和技巧,在相对路径处,引入我们可控的js/css文件,甚至引入非js/css文件,并按照js/css的语法执行,从而实现攻击。

0x02 漏洞成因

2.1 pathinfo模式

在介绍漏洞成因之前先介绍一下pathinfo这种url解析模式。
对于访问一个以MVC模式搭建的网站,必然带有M、C、A三个参数即module、controller、action,这些参数需要还需要用&符号隔开,假若参数量很多,就显得特别的不友好啦。然而PathInfo模式功能就是将这一长串缩短简化,让这个路径变得更加友好的显示。
传统的访问路径是这样子的:

1
  http://www.example.com/index.php?m=module&c=controller&a=action&var1=vaule1&var2=vaule2.....

而在pathinfo的URL模式下路径:

1
  http://www.example.com/index.php/module/controller/action/var1/vaule1/var2/value2.....

2.2 服务端与客户端解码差异

在服务端中,编码后的url服务器可以正常识别,也就是说服务器在加载文件时会解码后找到具体文件返回返回客户端。但是在客户端识别url时是不会解码的,如果某些静态资源文件使用相对路径,就很容易遭受RPO相对路径覆盖攻击.
有点绕,那么用一个简单例子理解一下:

1
http://127.0.0.1/index.php/test/..%2f..%2findex.php

在服务端,%2f会被解码为/,apache和nginx会按照目录的方式来返回我们请求的资源。也就是访问 http://127.0.0.1/index.php/test/../../index.php 即返回 http://127.0.0.1/index.php 的内容。
而在客户端,浏览器并没有对%2f进行解码,在pathInfo模式下认为..%2f..%2findex.php为一个无效的数据而返回test的内容。

2.3 触发条件

触发这个漏洞有两个基本的前提:
①Apache 配置错误导致AllowEncodedSlashes这个选项开启(对Apache来说默认情况下 AllowEncodedSlashes 这个选项是关闭的),或者nginx服务器。
②存在相对路径的js或者css的引用

0x03 利用演示

  • 1.加载任意目录下静态资源文件
    搭建本地环境/test/index.html
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <html >
    <head>
    <meta charset="UTF-8">
    <title>Rpo Test</title>
    <script src="1.js">
    </script>
    </head>
    <body>
    <h1>Test.....<h1>
    </body>
    </html>

客户端加载的静态资源是/test目录下的1.js文件,内容为:

1
document.write('<p>t=This is test_111111</p>');

如果我们控制test下面css的目录下面的test_2.js的内容,写入/test/css/1.js内容如下:

1
document.write('<p>t=This is test_222222</p>');

那么当我们访问:http://test/index.html/css/..%2findex.html页面将会加载/test/css/1.js的输出内容,即实现了相对路径覆盖攻击, 我们成功覆盖掉了index.html中静态资源1.js的路径.

  • 2.将返回内容按静态文件解析
    现在有如下环境:
    我们可以提交内容,然后内容会显示到当前页面,而且使用相对路径加载静态文件style.css和script.js文件,这两个文件原本内容为空,此时我们访问:
    http://127.0.0.1:8888/RPO_HACK/user/2
    此处输入图片的描述
    这里表示使用2作为参数请求user接口,此时加载静态文件为:
    1
    2
    http://127.0.0.1:8888/RPO_HACK/user/style.css
    http://127.0.0.1:8888/RPO_HACK/user/script.js

然后我们提交一段css内容:{} * {color:red;}
当我们访问:http://127.0.0.1:8888/RPO_HACK/user/2/xxx时:
此处输入图片的描述
这里表示我们使用2/xxx作为参数访问user接口,返回的内容和使用参数2访问返回的内容相同。
但是浏览器客户端认为2是目录,然后加载的静态文件为:

1
2
http://127.0.0.1:8888/RPO_HACK/user/2/style.css
http://127.0.0.1:8888/RPO_HACK/user/2/script.js

所以此时加载静态文件返回的内容也是同使用参数2访问时返回内容相同,但是此时浏览器认为这里加载的是样式文件和脚本文件,从而将返回内容解析为css或者js,所以我们提交的css内容:{} * {color:red;} 成功解析为css,将页面渲染成红色。

返回正确
服务器接收到的是*/tools/toolbar/buttons/apis/howto_guide.html
浏览器接收到的是 */tools/toolbar/buttons/apis%2fhowto_guide.html
页面中导入的样式表 为 */tools /toolbar/buttons/../../ style.css
浏览器认为style.css的根目录是tools/toolbar/buttons,而不是tools/toolbar/button/apis
所以../../style.css跳到了更高一级的目录下
此处输入图片的描述

除了跳目录以外,还能制作假目录,例如,我们想在导入的样式路径为/tools/fake/styles.css, 可以构造如下url:http://www.google.com/tools/fake/..%2ftoolbar/buttons/apis%2fhowto_guide.html
服务器视角: /tools/fake/../toolbar/buttons/apis/ + howto_guide.
浏览器视角: tools/fake/..%2ftoolbar/buttons/ + apis%2fhowto_guide.html
导入的css样式: /tools/fake/..%2ftoolbar/buttons/../../ + style.css
这里我们添加了两个虚假的路径:fake/和..%2f, 以便他们能在服务器相互抵消,同时浏览器认为fake/是一个真实的目录,并且,..%2ftoobar是另外一个目录
作者在此基础上找到了一处可以利用的重定向页面,http://www.google.com/tools/toolbar/buttons/gallery会重定向到 http://www.google.com/gadgets/directory?synd=toolbar&frontpage=1
在这里参数q是作为搜索参数,并且反应在页面上,可以成功注入一个简单的payload:

1
2
![此处输入图片的描述][4]
可以看到,这里可以控制q,能使用如下payload导入样式。

http://www.google.com/tools/toolbar/buttons%2fgallery%3fq%3d%250a%257B%257D*%257Bbackground%253Ared%257D/..%2f/apis/howto_guide.html

1
2
![此处输入图片的描述][5]
当然到这里只是改变了页面样式,作者进一步利用,改变payload为 CSS XSS向量expression(alert(document.domain)),并启动IE8:

http://www.google.com/tools/toolbar/buttons%2fgallery%3fq%3d%250a%257B%257D*%257Bx%253Aexpression(alert(document.domain))%257D/..%2f/apis/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
![此处输入图片的描述][6]
## 0x04 利用场景
> * 加载任意目录下静态资源文件

如上演示,我们可以加载任意目录下的1.js去覆盖index.html中静态资源1.js的路径

> * 将任意文件内容按静态文件解析

在使用了pathurl模式的php开发框架以及pythonweb框架中,经常使用相对路径来加载静态资源文件。
比如一篇文章的链接为 index.php/view/article/666/view是index.php中的方法,article和666分别是传入的参数名和参数值.
如果我们在其后加上..2f..%2f/这样路径会如何,服务端正常解码后返回/index.php/view页面的内容,但客户端不会解码,所有采用相对路径的静态资源文件的父路径变成了index.php/view/article/666/,而在这个链接后面加上的..%2f..%2f会被当做参数来解析,最后返回的还是index.php/view/article/666/文章的内容.
这样我们就完成了将任意文件内容按静态文件来解析的漏洞利用了。
## 0x05 ctf题目
### 强网杯xss题:share your mind
题目提示xss bot使用了phantomjs
登录后add页面可添加文章,而report页面可提交链接。而且网站静态js文件采用相对路径来访问根路径:/index.php中有一个静态文件是用相对路径表示的
![此处输入图片的描述][7]


`

首先我们add一篇内容为: alert(1)的文章:
得到文章路径:http://39.107.33.96:20000/index.php/view/article/41801
我们在这个文章路径后面加上/..%2f..%2f..%2f, 然后在访问,发现页面会弹窗。也就是将我们添加的文章作为了js脚本运行。
此处输入图片的描述
这是因为服务端会正常解码,跳转3个目录到index.php,返回给我们对应的内容。
而客户端并不会解码%2f, 而是将..%2f..%2f..%2f 当成一个文件来看待了,客户端寻找js的路径为:http://39.107.33.96:20000/index.php/view/article/41801/static/js/jquery.min.js
pathinfo的模式下,static/js/jquery.min.js 会被当做参数,最后返回的还是该文章的页面,
即alert(1)的内容。
到此即可找到xss攻击点,可进一步构造js代码读取cookie.

0x06 防护方案

1.在页面中避免直接使用相对路径进行静态文件的加载,使用完整的url,或者所有的引用都加/。
2.在页面开头,声明 <!DOCTYPE html>.

0x07 参考链接

http://blog.nsfocus.net/rpo-attack/
https://blog.innerht.ml/rpo-gadgets/
https://xz.aliyun.com/t/2220

本文标题:RPO相对路径覆盖攻击

文章作者:boogle

发布时间:2018年05月02日 - 15:35

最后更新:2019年03月07日 - 11:37

原始链接:https://zhengbao.wang/RPO相对路径覆盖攻击/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

感觉写的不错,给买个棒棒糖呗