文件上传shell是在渗透测试过程中,获得服务器权限最快最直接的方法,只有存在上传漏洞,服务器就岌岌可危。
0x00 文件上传检验的方式
可分为服务端和客户端:
- JavaScript前端检验(检测文件扩展名)
- 服务端检验
- MIME类型检测(
content-type
内容) - 目录路径检测 (path参数相关的内容)
- 文件扩展名检测 (文件extension相关的内容)
- 文件内容检测 (检测内容是否合法或含有恶意代码)
- 文件头检测
- 文件加载检测
- MIME类型检测(
具体检测的内容如下,通常一个文件以HTTP 协议进行上传时,将以POST 请求发送至web 服务器
web 服务器接收到请求后并同意后,用户与web 服务器将建立连接,并传输data。
0x01 绕过各类检测方式
客户端检测
在网页上写一段JavaScript的检测代码,检测上传的文件是否是合法的后缀。
function checkFile() {
var file = document.getElementsByName('upload_file')[0].value;
if (file == null || file == "") {
alert("请选择要上传的文件!");
return false;
}
//定义允许上传的文件类型
var allow_ext = ".jpg|.png|.gif";
//提取上传文件的类型
var ext_name = file.substring(file.lastIndexOf("."));
//判断上传文件类型是否允许上传
if (allow_ext.indexOf(ext_name + "|") == -1) {
var errMsg = "该文件不允许上传,请上传" + allow_ext + "类型的文件,当前文件类型为:" + ext_name;
alert(errMsg);
return false;
}
}
绕过方式:可以通过burpsuite抓包,进行改filename,也可以通过禁用JS。
服务端检测
1、MIME类型检测绕过
服务器对content-type
的字段进行检测
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
if (($_FILES['upload_file']['type'] == 'image/jpeg') || ($_FILES['upload_file']['type'] == 'image/png') || ($_FILES['upload_file']['type'] == 'image/gif')) {
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = UPLOAD_PATH . '/' . $_FILES['upload_file']['name']
if (move_uploaded_file($temp_file, $img_path)) {
$is_upload = true;
} else {
$msg = '上传出错!';
}
} else {
$msg = '文件类型不正确,请重新上传!';
}
} else {
$msg = UPLOAD_PATH.'文件夹不存在,请手工创建!';
}
}
从上面的代码可以看出,服务器对上传的文件,content-type
为 image/jpeg,image/png,image/gif
才可以通过上传。
我们只需要抓取数据包,将content-type
改为其中一种即可。
可以看到当字段content-type: application/octet-stream
是上传失败的。改为image/jpg
:
可以看到已经上传成功了。
2、目录路径检测绕过
目录路径检测,一般就检测路径是否合法,但稍微特殊一点的都没有防御。漏洞成因是因为对目录路径的检测不够严谨而导致可以用0x00 截断进行攻击。
3、文件扩展名检测绕过
文件扩展名检测一般有黑名单和白名单,白名单比黑名单的安全性高,攻击的手法自然就少。
黑名单:
一般的backlist如下:
$deny_ext = array(".php",".php5",".php4",".php3",".php2","php1",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2","pHp1",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf");
绕过方式:
- 文件名大小写绕过(对于大小写不敏感的Windows)
Asp,pHp
等可以绕过黑名单 名单列表绕过
用黑名单里没有的名单进行攻击
特殊文件名绕过
比如发送的http 包里把文件名改成test.asp. 或test.asp_(下划线为空格),然后绕过验证后,会
被windows 系统自动去掉后面的点和空格,但要注意Unix/Linux 系统没有这个特性。test.asp. test.asp::$DATA //利用windows NTFS流 test.asp(空格) test.php:1.jpg
- 0x00 截断绕过
基于一个组合逻辑漏洞造成的,通常存在于构造上传文件路径的时候
test.php(0x00).jpg test.php%00.jpg 路径/upload/1.php(0x00),文件名1.jpg,结合/upload/1.php(0x00)/1.jpg
- .htaccess 文件攻击
无论是黑名单还是白名单再直接点就是直接攻击.htaccess 文件,配合名单列表绕过,上传一个自定义的.htaccess,就可以轻松绕过各种检测
配合解析漏洞和其他编辑器漏洞
这类漏洞直接配合上传一个代码注入过的非黑名单文件即可,再利用解析调用/漏洞
白名单:
白名单的攻击方式相对少一些。
$ext_arr = array('jpg','png','gif');
绕过方式:
- 0x00截断
- 配合解析漏洞和其他编辑器漏洞
4、文件内容检测绕过
文件内容检测分为文件头检测和文件加载检测,文件加载通过调用API重新渲染图片,将图片一些不必要的信息去掉,重新生成图片。
如果文件内容检测设置得比较严格,那么上传攻击将变得非常困难,也可以说它是在代码层检测的最后一道关卡,如果它被突破了,就算没有代码层的漏洞,也给后面利用应用层的解析漏洞带来了机会。
文件头检测:
主要是检测文件开头处的文件幻数。不同的图片文件都有不同文件头,如:
PNG: 文件头标识 (8 bytes) 89 50 4E 47 0D 0A 1A 0A
JPEG: 文件头标识 (2 bytes): 0xff, 0xd8 (SOI) (JPEG 文件标识)
GIF: 文件头标识 (6 bytes) 47 49 46 38 39(37) 61
PHP使用getimagesize
函数验证图片文件头,代码示例:
function isImage($filename){
$types = '.jpeg|.png|.gif';
if(file_exists($filename)){
$info = getimagesize($filename);
$ext = image_type_to_extension($info[2]);
if(stripos($types,$ext)){
return $ext;
}else{
return false;
}
}else{
return false;
}
}
文件相关信息的检测:
图像文件信息检测常用就是getimagesize()
函数,就是在幻数的基础上还加了一些文件信息
GIF89a
(...some binary data for image...)
<?php phpinfo(); ?>
(... skipping the rest of binary data ...)
文件加载检测:
最变态的检测,一般是调用API或函数去进行文件加载测试。常见的是图像渲染测试,还有二次渲染(更加变态)什么是二次渲染呢?二次渲染就是调用API,例如php的GD库,重新生成一张图片,在生成的过程中,把原本属于图像数据的部分抓了出来,再用自己的API 或函数进行重新渲染
- 对渲染/加载测试的攻击方式是代码注入绕过
- 对二次渲染攻击方式是攻击文件加载器自身
绕过方式:
- 渲染/加载测试的攻击方式是代码注入绕过
在不破坏文件本身的渲染情况下找一个空白区进行代码填充,一般会是图片的注释区,文件结构要完整。
二次渲染
参考:https://paper.seebug.org/387/#2-php-gdwebshell
https://github.com/RickGray/Bypass-PHP-GD-Process-To-RCE
http://www.secgeek.net/bookfresh-vulnerability/
0x02 上传攻击框架
1、轻量的检测绕过
- 绕过JavaScript对扩展名的检测
- 绕过服务端对MIME类型检测
2、路径/扩展名检测绕过
黑名单绕过
- 文件名大小写(主要windows)
- 名单列表绕过
- 特殊文件名绕过
- 0x00截断绕过
- .htaccess文件攻击
- php文件包含漏洞
- Apache解析漏洞
- IIS解析漏洞
- nginx解析漏洞
白名单绕过
- 0x00截断
- Apache解析漏洞
- IIS解析漏洞
- nginx解析漏洞
3、文件内容检测绕过
- 文件加载绕过
4、攻击mind图
5、攻击的流程
0x03 后记
一些平时大家当小技巧对待的东西,以后会成为主要攻击手段之一。