RPO攻击原理介绍和利用
注意:本文分享给安全从业人员,网站开发人员和运维人员在日常工作中使用和防范恶意攻击,请勿恶意使用下面描述技术进行非法操作。
[TOC]
0x00 前言介绍
描述:说实在第一个看这个漏洞的时候是没挣明白的有点绕(大佬一眼应该就能观定),下面大致对PRO做一个介绍;
什么是RPO攻击?
RPO(Relative Path Overwrite
)相对路径覆盖,是一种新型攻击技术,最早由Gareth Heyes在其发表的文章中提出。主要是利用浏览器的一些特性和部分服务端的配置差异导致的漏洞,通过一些技巧,我们可以通过相对路径来引入其他的资源文件,以至于达成我们想要的目的。
就目前来看此攻击方法依赖于浏览器和网络服务器的反应,基于服务器的Web缓存技术和配置差异,以及服务器和客户端浏览器的解析差异,利用前端代码中加载的css/js的相对路径来加载其他文件,最终浏览器将服务器返回的不是css/js的文件当做css/js来解析,从而导致XSS,信息泄露
等漏洞产生。
网站是如何加载的?
- 根据程序员编写的代码从上到下进行执行
- HTML加载域CSS渲染JS脚本解析;
其中页面的加载和渲染都需要通过脚本执行
,并且在脚本执行过程中网站的加载暂时停止,等待脚本加载完成,特别是JavaScript和src引入JavaScript(会暂停直接进行解析并执行
,并且连续载入
两个JavaScript文件加载过程中会有一段时间的间隔,这段时间就是js代码执行的时间
)
0x01 RPO漏洞原理(principle)
原理:RPO漏洞相对路径覆盖并且源码中引用了相对路径css文件所导致的脆弱性漏洞,一般的可利用手段就是CSS攻击钓鱼和CSS-XSS 攻击。 本质:根据服务器解析与浏览器(客户端)解析URL之间的微小差异而产生的漏洞,
RPO漏洞攻击的条件:
- 可利用页面无DOCTYPE
- 标签中包含相对路径的CSS/js/swf文件
- 浏览器解析页面路径有误而导致css文件加载路径错误,从而引发的任意解析。
对于php而言它获得的请求是url解码后的%2F会被解码为/
, apache和nginx会按照目录的方式来返回我们请求的资源。
服务端和客户端之间产生了沟通差异,浏览器在寻找js资源的时候,并没有对%2f进行解码则导致将%2f+后续的字符串 认为是一个文件;
脆弱性的演示Demo: http://www.google.com/tools/toolbar/buttons/apis%2fhowto_guide.html
#注意这里也并没有<!Doctype HTML> 标记;
<html>
<head>
<title>Google Toolbar API - Guide to Making Custom Buttons</title>
<link href="../../styles.css" rel="stylesheet" type="text/css" /> <!--- Href 关键点 --->
访问上面的网站%2f = /
则服务器容器解析/apis/howto_guide.html
,而浏览器解析会将其看作是一个文件apis%2fhowto_guide.html
,其次CSS样式表的理解也是一个文件apis%2fhowto_guide.html
我们来还原一下正常的解析情况和采用%2f
后的解析情况
#1.使用 / 的网站地址
http://www.google.com/tools/toolbar/buttons/apis/howto_guide.html # 实际服务器中的html文件名词howto_guide.html
http://www.google.com/tools/toolbar/style.css #此时的css样式表包含地址 (实际存在的)
#2.使用 %2f 的网站地址
http://www.google.com/tools/toolbar/buttons/apis%2fhowto_guide.html #将apis%2fhowto_guide.html看作是一个文件,但是服务器却可以进行解析
http://www.google.com/tools/style.css #此时的css样式表包含地址(实际不存在)
结果导致style.css不存在,所以无法加载css样式表,现在浏览器认为我们的目录是/tools/toolbar/buttons/
而不是/tools/toolbar/buttons/apis
。
尝试创建个fake目录和..%2ftoolbar 网站地址如:http://www.google.com/tools/fake/..%2ftoolbar/buttons/apis%2fhowto_guide.html
服务器理解:http://www.google.com/tools/toolbar/buttons/apis%2fhowto_guide.html #因为fake和..%2ftoolbar目录不存在
浏览器理解:http://www.google.com/tools/fake/..%2ftoolbar/buttons/apis%2fhowto_guide.html
css样式表:http://www.google.com/tools/fake/style.css
添加了fake 和..%2ftoolbar
虚假目录,浏览器认为fake和..%2ftoolbar都是目录
,因为他们中间都有/*/,而%2f被理解成了文件。
- 经过实验证明,理论上我们可以css覆盖:
http://www.google.com/*/style.css
,但是我们再次往上层编码,发现这是不行的会出错。所以css覆盖止步于:http://www.google.com/tools/*/style.css
,我们需要在Tools目录下找寻可以被利用的点 - 找寻利用点
http://www.google.com/tools/toolbar/buttons/gallery?q=1
会进行二次跳转跳转到http://www.google.com/gadgets/directory?synd=toolbar&frontpage=1&q=1
验证利用点准备尝试植入CSS
http://www.google.com/tools/toolbar/buttons/gallery?q={}*{background:red}
#跳转
http://www.google.com/gadgets/directory?synd=toolbar&frontpage=1&q={}*{background:red} #css代码成功植入,虽然他不在style样式表中。
WeiyiGeek.
为什么只能使用接口而不能使用跳转链接进行攻击?
现在我们来利用它:
构造地址:http://www.google.com/tools/toolbar/buttons%2Fgallery%3Fq%3D%0a%7B%7D*%7Bbackground%3Ared%7D/..%2F的/apis/howto_guide.html
服务器理解:http://www.google.com/tools/toolbar/buttons//apis/howto_guide.html
浏览器理解:http://www.google.com/tools/toolbar/buttons%2Fgallery%3Fq%3D%0a%7B%7D*%7Bbackground%3Ared%7D/..%2F的/apis/howto_guide.html
/tools/toolbar/buttons%2fgallery%3fq%3d%250a%257B%257D*%257Bbackground%253Ared%257D/..%2f/apis/../../style.css #浏览器会认为目前在的目录是apis向上之后就到了下面的css样式表
css样式表:http://www.google.com/tools/toolbar/buttons/gallery?q=%0a{}*{background:red}/style.css #访问之后会跳转到下面URL,然后进行二次跳转
/gadgets/directory?synd=toolbar&frontpage=1&q=%0a{}*{background:red}/style.css #最终样式表
#原始的未污染的样式表
<link href="../../styles.css" rel="stylesheet" type="text/css" />
#转变(#就把{}*{background:red}包含了)
<link href="/gadgets/directory?synd=toolbar&frontpage=1&q=%0a{}*{background:red}/style.css" rel="stylesheet" type="text/css" />
WeiyiGeek.
WeiyiGeek.
0x02 漏洞利用案例
案例1.强网杯案例 描述: http://39.107.33.96:20000/index.php 调用了相对路径的js ,第一个是相对路径,第二个是绝对路径
WeiyiGeek.
- 我们创建一个包含js脚本的页面:
http://39.107.33.96:20000/index.php/view/article/3093
即alert(1)
;
WeiyiGeek.
构造xss利用点
#POC:http://39.107.33.96:20000/index.php/view/article/3093/..%2f..%2f..%2f/index.php
服务器端解析: http://39.107.33.96:20000/index.php #向上跳了三层,依旧返回index.php页面的内容,其中包含有js相对资源: static/js/jquery.min.js
浏览器端在渲染的时候无法url解码:http://39.107.33.96:20000/index.php/view/article/3093/..%2f..%2f..%2f
#所以 static/js/jquery.min.js 是接在目录 3093/后面,构成了
http://39.107.33.96:20000/index.php/view/article/3093/static/js/jquery.min.js
#然后在渲染的时候将该页面的内容作为js脚本来加载
http://39.107.33.96:20000/index.php/view/article/3093
WeiyiGeek.
- 最终效果:
WeiyiGeek.
0x03 漏洞修复
- 建议在对js或者swf以及css或者其他页面包含的时候,在页面中避免直接使用相对路径进行静态文件的加载,尽量不要出现如”../../../xxxx.js”相对路径的调用;
0x04 参考
- https://www.jianshu.com/p/5b174dcba362
- http://blog.nsfocus.net/rpo-attack/
- https://xz.aliyun.com/t/2220
- Golang实现Fibonacii的几种算法
- 【译】使用 dotnet watch 开发 ASP.NET Core 应用
- vmware安装ubuntu12.04嵌套安装xen server(实现嵌套虚拟化)
- Golang语言切片slice的线程协程安全问题
- ASP.NET Core 在 Azure 开启 HTTPS
- 算法基础:最大递减数问题(Golang实现)
- 亲身经历的痛--database/sql: Stmt的使用以及坑
- Ubuntu上通过nginx部署Django笔记
- Go学习笔记:golang交叉编译
- Python魔术方法-Magic Method
- python类中super()和__init__()的区别
- Python正则表达式:最短匹配
- 转--Go时间格式化和类型互换操作
- Python标准库(1) — itertools模块
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- ThinkPHP框架结合Ajax实现用户名校验功能示例
- Laravel框架Eloquent ORM新增数据、自定义时间戳及批量赋值用法详解
- PHP使用HTML5 FileApi实现Ajax上传文件功能示例
- python3.7调试的实例方法
- Laravel框架控制器,视图及模型操作图文详解
- PHP实现带进度条的Ajax文件上传功能示例
- 基于selenium及python实现下拉选项定位select
- PHP rmdir()函数的用法总结
- thinkphp5修改view到根目录实例方法
- openCV提取图像中的矩形区域
- PHP二维索引数组的遍历实例分析【2种方式】
- Selenium及python实现滚动操作多种方法
- PHP使用JPGRAPH制作圆柱图的方法详解
- PHP 实现超简单的SESSION与COOKIE登录验证功能示例
- PHP 图像处理与SESSION制作超简单验证码的方法示例