upload-labs 文件上传通关加源码分析

文件上传专项练习

靶场:谜团靶机平台
或者直接在github上下载
https://github.com/c0ny1/upload-labs

简介

文件上传是Web网页中常见的功能之一,通常情况下恶意的文件上传,会形成漏洞

大致逻辑是:用户通过上传点上传了恶意文件,通过服务器的校验后保存到指定的位置。
当用户访问已经上传成功的文件时,上传的Web脚本会被Web容器进行解析,从而对网站造成危害。
upload-labs是一个使用php语言编写的,专门收集渗透测试和CTF中遇到的各种上传漏洞的靶场。目前一共21关,每一关都包含着不同上传方式。所以使用这个靶场进行演练
图片.png

Pass-01 JS绕过

##源码分析
通过验证发现是前端JS验证。而前端验证,几乎没有什么防护作用
图片.png
再根据代码,进行绕过

方法一 禁用js

浏览器直接禁用JS,先按F12,然后按F1,找到禁用JS
图片.png
直接上传php木马
上传成功
图片.png

方法二 后缀名绕过

先把一句话木马改为,.jpg|.png|.gif其中一个后缀,上传,抓包
图片.png
修改后缀名为php
图片.png
上传成功
图片.png

方法三 修改前端代码

直接修改前端代码,上传
图片.png
上传成功
图片.png

Pass-02 文件类型绕过

源码分析

图片.png
分析代码,发现只是检查了content-type类型
大致就是识别上传文件的类型 并查看是否是image/jpge、image/png、image/gif其中的一个,否则不允许上传

扩充:

MIME类型检测简介:
MIME(Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型。是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方式。

绕过复现

直接抓取数据包,
图片.png

抓包修改content-type为图片类型:image/jpeg、image/png、image/gif 其中一个
图片.png
上传成功
图片.png

Pass-03 黑名单绕过

源码分析

图片.png
可以看出只是做了个简单的后缀名黑名单,识别上传文件的类型 查看是否是’.asp’,’.aspx’,’.php’,’.jsp’中的一个,若果是其中的一个,则不允许上传。

不允许上传.asp,.aspx,.php,.jsp后缀文件,但是可以上传其他任意后缀。比如说:.phtml .phps .php5 .pht,但如果上传的是.php5这种类型文件的话,如果想要被当成php执行的话,需要有个前提条件,即Apache的httpd.conf有如下配置代码(靶场应该是配置好的,如果是本地复现,需要配置)

AddType application/x-httpd-php .php .phtml .phps .php5 .pht

方法一 截断绕过

上传php文件,抓包
修改后缀名,进行截断,直接绕过
图片.png

方法二 其他可解析后缀

扩展:

PHTML(有时叫做PHP)网页是一种包含PHP(一种和JavaScript或 Microsoft VBScript类似的语言)脚本的网页和ASP一样,PHP脚本镶嵌在网页的HTML代码之中。在页面被发送给请求的用户之前,网页服务器调用PHP解释程序来解释和执行PHP脚本。含有PHP脚本的网页通常都以“.php”、“.php3”或“.phtml”作为后缀。和ASP一样,PHP可以被认为是一种“动态网页”

所以由于服务端采用黑名单的过滤方式, 这里可以使用php3或phtml等的后缀上传
上传php文件,抓包
修改后缀名,phtml,php3,php4, php5, pht后缀名,也是可以当做php脚本解析的(这里我演示其中一个
图片.png

Pass-04 htacess文件绕过

源码分析

图片.png
这个比03增加了黑名单量。但是,中间件为Apache的情况下,黑名单未校验htaccess文件,导致可上传htaccess文件,绕过黑名单检测。

扩展:

htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置。通过htaccess文件,可以帮我们实现:网页301重定向、自定义404错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能。上传.htaccess文件,来绕过黑名单。首先尝试上传.phtml,发现上传成功,再响应包中找到上传路径。

前提条件
1.mod_rewrite模块开启。
2.AllowOverride All

代码6到10行,是对文件后缀的一些处理,包括删除结尾的点,删除空格,全都转换成小写等。但可以购置后缀,比如构造.php. .中间是一个空格(后面的第八关和第十关是同样的思路),

方法一 上传htaccess文件

由于.htaccess还是没有过滤,可以重写文件解析规则绕过,上传一个.htaccess,文件内容如下,意思是设置当前目录所有文件都使用PHP解析,那么无论上传任何文件,只要文件内容符合PHP语言代码规范,就会被当作PHP执行。不符合则报错。
文本内容如下:

AddType application/x-httpd-php .png
或者
<FilesMatch "文件名">
SetHandler application/x-httpd-php
</FilesMatch>

抓包,填写文件(这个文件名可以只是baixi,后面只要是baixi的文件名都会以php形式解析)
图片.png
再上传一个baixi.jpg文件,上传成功后,会以php文件运行
图片.png

方法二 构造后缀

上传php文件,抓包
修改,后缀为.php. .
图片.png

Pass-05 解析漏洞

只是黑名单里添加了.htaccess,可以使用构造后缀的方式了(04中的方法二)
查看提示
图片.png
所以有一下方法

方法一 解析漏洞

由于服务器的中间件是apache2, 尝试解析漏洞:
apache2解析漏洞 (存在于Apache1.x和Apache2.x)
将从右向左开始解析后缀, 直到遇到一个apache认识的后缀类型,就会以该类型进行解析:
图片.png
然后访问, 发现解析成功了,

方法二 .user.ini绕过

根据提示redme.php。想到当PHP以CGI/FastCGI模式运行的情况下,黑名单未校验后缀为.ini的文件,导致可上传.user.ini文件,绕过黑名单检测。
.user.ini

在php执行的过程中,除了主 php.ini 之外,PHP 还会在每个目录下扫描 INI 文件,从被执行的 PHP 文件所在目录开始一直上升到 web 根目录($_SERVER[‘DOCUMENT_ROOT’] 所指定的)。如果被执行的 PHP 文件在 web 根目录之外,则只扫描该目录。 .user.ini 中可以定义除了PHP_INI_SYSTEM以外的模式的选项,故可以使用 .user.ini 加上非php后缀的文件构造一个shell,比如 auto_prepend_file=01.gif

具体请参考: https://segmentfault.com/a/1190000011552335?utm_source=tag-newest

利用.user.ini文件条件:

  • 服务器脚本语言为PHP
  • 服务器使用CGI/FastCGI模式
  • 上传目录下要有可执行的php文件

所以创建一个 .user.ini 文件, 内容如下:

auto_prepend_file=123.gif

将其上传到服务器,
图片.png
然后将包含webshell的脚本命名为 123.gif, 同样也上传服务器
图片.png
再访问readme.php的时候, 就会自动包含并解析123.gif文件

Pass-06 大小写绕过

源码分析

图片.png
看代码第5至10行,里面的过滤没有限制大小写,所以可以尝试大小写组合绕过。比如.pHP.PHP等。尝试上传
大小写绕过原理:

Windows系统下,对于文件名中的大小写不敏感。例如:test.php和TeSt.PHP是一样的。
Linux系统下,对于文件名中的大小写敏感。例如:test.php和 TesT.php就是不一样的。

绕过复现

图片.png

Pass-07 空格绕过

源码分析

图片.png
通过观察源码,发现没有对空格进行处理,所以此处可以利用windows系统的命名规则进行绕过。

Win下xx.jpg[空格] 或xx.jpg.这两类文件都是不允许存在的,若这样命名,windows会默认除去空格或点
windows文件名后缀不允许存在空格,如果存在,windows自动去除空格
此处会删除末尾的点,但是没有去掉末尾的空格,因此上传一个.php[空格]文件即可

图片.png

Pass-08 点绕过

源码分析

图片.png
从代码上看,可以发现相比于之前代码,却少了尾部去点。所以,利用windows文件命名规则绕过。这里去除了空格,并用strrchr函数查找指定小黑点最后一次出现,所以构造的后缀为.php. (点php点加空格),成功绕过,
图片.png

Pass-09 ::$DATA绕过

源码分析

图片.png
看代码第5行到第10行,源码中未过滤::$DATA,可以利用::$DATA来绕过过滤,

扩展:

在window的时候如果文件名+"::$DATA"会把::$DATA之后的数据当成文件流处理,不会检测后缀名,且保持::$DATA之前的文件名,他的目的就是不检查后缀名。例如:"test.php::$DATA"Windows会自动去掉末尾的::$DATA变成"test.php"。

简单讲就是当访问1.php::$DATA时,就是请求1.php本身的数据。
注:仅windows适用

绕过分析

现在抓取数据包验证。上传成功,如下图。
图片.png

Pass-10 点空格点绕过

源码分析

图片.png
这一关和第八关类似,就比第八关多了一行,多删除了一个点,所以还是采用构造后缀的方式,这次构造的后缀为xx.php. .(点php点空格点)正好绕过过滤。
也是利用了Windows的特性。也就是说,如果从第三关到第九关,如果目标服务器是windows系统的话,均可用点空格点绕过。
构造好后,上传成功
(具体方法看04的方法二)

Pass-11 双写绕过

源码分析

图片.png
第八行,这里使用了str_ireplace函数将匹配到的字符替换为空,所以可以使用双写绕过,删除字符后,剩余的又重新拼接为后缀,达到绕过的目的,
pphphp -> 过滤后为pphphp,前后又拼成了一个php。

绕过复现

图片.png

Pass-12 00截断

源码分析

图片.png
分析源码知道,这里是基于白名单过滤,只允许上传’jpg’,’png’,’gif’,
在第八行代码显示,在进行move_uploaded_file前。利用GET[‘save_path’]和随机时间函数进行拼接,拼接成文件存储路径。这里构造文件存储路径利用了_GET传入,导致服务器最终存储的文件名可控,所以可以利用%00截断,来达到上传木马的目的。

截断条件:
1、php版本小于5.3.4
2、php.ini的magic_quotes_gpc为OFF状态

绕过复现

图片.png

Pass13

源码分析

图片.png
同样是白名单,同样上传位置可控,只是由GET传输变为POST,还是可以利用%00截断。中间件Apache并不会自动解码一次,因此需要将%00解码一次。:
图片.png
选中%00 右键转码,或者手动
图片.png

Pass-14 图片马 unpack

第十四关是上传图片马,配合解析漏洞
图片.png

源码分析

图片.png
分析代码可以知道它只读前2字节,所以只需要将木马后缀改为图片格式,内容加个图片头部,然后在返回包中找到路径,然后写在file参数后,因为file参数include的原因都会直接执行。如下

方法一

添加图片前缀,例如gif 前缀 GIF89a
图片.png
传成功,配合文件包含漏洞解析图片格式的木马。

方法二 图片马

图片马的制作:

1.一句话木马代码:

2.用快捷键“win+R”打开cmd,先进入到先前准备好的两个文件的存放路径,然后敲命令行:copy demo.jpg/b + yjh.php tpm.jpg
图片.png

Pass-15 图片马 getimagesize()

源码分析

图片.png
这里使用getimagesize()函数来验证是否是图片,这里说一下getimagesize(),这个函数功能会对目标文件的16进制去进行一个读取,去读取头几个字符串是不是符合图片的要求的。getimagesize()返回结果中有文件大小和文件类型,如果用这个函数来获取类型,从而判断是否是图片的话,会存在问题。是可以被绕过的,因为图片头可以被伪造。这里伪造gif的图片头,来进行上传

与十三关解法相同。
用方法1即可。
图片.png
图片木马上传成功。

Pass-16 exif_imagetype()

源码分析

图片.png
这里使用exif_imagetype函数来检查是否是图片,这里说一下exif_imagetype(),它是读取一个图像的第一个字节并检查其签名。所以也是可以通过伪造图片头来进行绕过的。这里同样伪造gif的图片头,来进行上传,

与十三关解法相同。
用方法1即可。
图片.png

Pass-17 二次渲染绕过

关于二次渲染参考:https://xz.aliyun.com/t/2657 讲的很细

源码分析

图片.png
这一关比较综合,判断了后缀名、content-type,以及利用imagecreatefromgif判断是否为gif图片,最后再做了一次二次渲染。
可以看到,这里先是判断Content-Type,然后再用imagecreatefrom[gif|png|jpg]函数判断是否是图片格式,如果是图片的话再用image[gif|png|jpg]函数对其进行二次渲染。

我们可以上传一个正常的图片文件,观察其上传前和上传后图片的二进制流是否发生变化,比如我用copy命令生成了shell.jpg,用十六进制编辑器打开可以看到,文件末尾有我加入的php语句。将源文件和二次渲染过的文件进行比较,找出源文件中没有被修改的那段区域,在那段区域写入php代码即可。找到两者匹配的地方。在匹配处写入php代码即可

绕过姿势

(因为一些原因,这点没有复现,我只写写思路)
上传一个正常图片,抓取数据包,在图片末尾插入恶意代码,
然后,进行上传操作。上传成功,如下。将其上传,将服务器保存的即被二次渲染过的图片保存下来。
图片.png
将被二次渲染过的图片用十六进制编辑器打开,末尾前面加入的PHP代码也不见了
将上传的图片下载到本地查看
里发现在进行二次渲染的过程中,我们插入到图片的恶意代码被清理掉了,所以需要对比渲染前后,哪些地方没有变化,我们将恶意代码插入到那里,来绕过二次渲染。对比发现,这里渲染前后没有发生变化
所以,我将恶意代码插入到未变化的地方
重新上传,上传成功,再次下载到本地,发现恶意代码没有被清除,绕过了二次渲染。

pass-18 条件竞争

源码分析

图片.png
基本确定是白名单过滤,
过程是先将上传的临时文件移动到目标路径(upload下);
然后进行白名单判断, 是则以时间戳重命名目标文件; 否则就断开目标文件的软连接(可以理解为删除)。
这里就不适合用截断上传了, 可用竞争上传。
即进行若干次重复的上传脚本文件, 同时不断访问目标文件, 总有一次会趁系统来不及unlink文件而访问到上传的脚本文件, 称之为竞争上传。

绕过姿势

用burp开启两个intruder模块,一个用于重复上传,另一个用于重复访问。
1、先设置上传请求,记住此处的文件名,等下要用来拼接访问请求的url
图片.png
2、因为此处没有什么参数需要爆破,只是需要重复发起请求,所以payload设置为Null payloads,设置访问次数5000次,线程50个,可以利用burp一直发上传包,让php程序一直处于移动php文件到upload目录这个阶段。
图片.png
接下来设置访问请求
1、浏览器构造请求url:http://e3ae528c827246ea9d72b09a20d4b6dc.app.mituan.zone/upload/baixi.php进行访问,然后用burp抓包
2、burp抓包后发送至intruder模块,然后设置payload,这一步和上传请求设置差不多,都是Null payloads、5000次、50个线程,
图片.png
设置好两个模块后同时启动,观察结果,因为我们传入的php代码是phpinfo();,所以如果访问成功的话,会返回php的配置信息。
图片.png
哎,方法应该没错,但没出来,希望有大佬指点

pass-19 条件竞争

这里同样存在条件竞争问题,不过就是需要换成图片木马。其他和第十八关一样。
可以看到,这里先将上传的文件保存(move函数),再rename重命名一下。所以也存在条件竞争。
具体操作参考第十八关

pass-20 ./绕过

源码分析

图片.png
发现代码中move_uploaded_file会忽略掉文件末尾的/.所以可以构造save_path=1.php/.,这样file_ext值就为空,就能绕过黑名单,而move_uploaded_file函数忽略文件末尾的/.可以实现保存文件为.php

方法一 利用系统命名

Windows下命名为 door.php. , 系统会自动命名为 door.php ;
Linux下命名为 door.php/. , 系统会自动命名为 door.php ;

1.php%00.jpg
1.php/.
或者直接加一个.号也可以绕过
图片.png

方法二 大小写绕过

由于是黑名单过滤, 黑名单往往会不全, 所以可以用大小写绕过
图片.png

pass-21 数组/.绕过

源码分析

图片.png
逻辑:先检查MIME文件类型,通过后检查文件名,保存名称为空的就用上传的文件名。再判断文件名是否是array数组,不是的话就用explode()函数通过.号分割成数组。然后获取最后一个,也就是后缀名,进行白名单验证。不符合就报错,符合就拼接数组的第一个和最后一个作为文件名,保存

扩展:涉及到的函数的含义。

end()函数将 array的内部指针移动到最后一个单元并返回其值
reset()函数将 array 的内部指针倒回到第一个单元并返回第一个数组单元的值
count() 函数计算数组中的单元数目或对象中的属性个数,这里要注意,数组下标从0开始
然后这里用end函数将接收的后缀与白名单比较,如果符合,继续执行,然后数组第一位和$file[count($file) - 1]进行拼接,产生保存文件名file_name。
所以这里采用数组绕过,save_name[0]=pass21.php, save_name[2]=jpg,$ext=jpg过白名单,reset($file)=pass21.php
$file[1]=null,这样就成功上传pass21.php.(windows多个点不影响)
抓包测试。上传成功。

绕过姿势

图片.png
但是打靶场的时候回显的是500.500是(服务器内部错误)服务器遇到错误,无法完成请求。我也去看了很多篇文章,都是500。也有可能是靶场的原因,如果大佬知道希望告知

总结

21关做下来,已经包含了大部分文件上传类型。项目官方github上有一张总结图,总结的挺好的。也感谢网上的各位大佬的文章,给小白我一个思路与参考。
图片.png

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发