天天看点

upload-labs通关简述以及文件上传小结

本文通过upload-labs学习文件上传漏洞,最后有一个文件上传的小结。首先看一下$_FILES[]的内容

array(1) {
  ["myfile"]=>
  array(5) {
    ["name"]=>
    string(7) "hhh.php"
    ["type"]=>
    string(24) "application/octet-stream"
    ["tmp_name"]=>
    string(22) "C:\Windows\php6109.tmp"
    ["error"]=>
    int(0)
    ["size"]=>
    int(156)
  }
}
           

这些信息也是服务器检测的依据来源。靶场入口

paas-1

前端javascript检测,直接禁用JavaScript或者burpsuit抓包改名字就行了。

pass-2

Content-Type检测

Content-Type :image/gif imag/jpg

Content-Type :application/octet-stream

pass-3

过滤.asp,.aspx,.php,.jsp文件后缀,用php3,php4,phtml等替换。

但phpstudy因为配置原因无法解析php3等文件后缀。

pass-4

过滤的很多文件后缀,但可以上传.htaccess文件,修改解析,然后上传.jpg。

pass-5

大小写绕过(前提是配置文件开启)

pass-6

文件名加空格绕过

pass-7

文件名后面加.绕过(eg:hhh.php.),利用的是windows特性在保存时会自动把点去掉。

pass-8

通过::$DATA绕过

pass-9

利用windows文件命名特性

test.php… ------> test.php

test.php ------> test.php(前一个test.php后有空格)

test.php. … ------> test.php

构造一个.和空格组合的文件名(test.php. .)绕过

pass-10

双写绕过。

pass-11

控制上传路径,在上传路径后通过%00截断,绕过白名单

%00截断条件:

php版本小于5.3.4

php.ini中magic_quotes_gpc为OFF状态。

move_uploaded_file函数的底层实现类似于C语言,遇到0x00就会截断。

pass-12

因为save_path也在上传文件的那个表单里,因此就不会对其解码,那么要通过%00截断,就只有在包的二进制里面修改才有用。

upload-labs通关简述以及文件上传小结

pass-13

通过copy paint.jpg /b+shell.txt /a webshell.jpg 来构造一个图片马,然后再结合文件包含漏洞利用图片马.

pass-14

通过getimagesize()会返回图像的尺寸大小及类型等信息.

array(6) {
  [0]=>
  int(48)
  [1]=>
  int(48)
  [2]=>
  int(3)
  [3]=>
  string(22) "width="48" height="48""
  ["bits"]=>
  int(8)
  ["mime"]=>
  string(9) "image/png"
}
           
  • 索引 0 给出的是图像宽度的像素值
  • 索引 1 给出的是图像高度的像素值
  • 索引 2 给出的是图像的类型,返回的是数字,其中1 = GIF,2 = JPG,3 = PNG,4 = SWF,5 = PSD,6 = BMP,7 = TIFF(intel byte order),8 = TIFF(motorola byte order),9 = JPC,10 = JP2,11 = JPX,12 = JB2,13 = SWC,14 = IFF,15 = WBMP,16 = XBM
  • 索引 3 给出的是一个宽度和高度的字符串,可以直接用于 HTML 的 标签
  • 索引 bits 给出的是图像的每种颜色的位数,二进制格式
  • 索引 channels 给出的是图像的通道值,RGB 图像默认是 3
  • 索引 mime 给出的是图像的 MIME 信息,此信息可以用来在 HTTP Content-type 头信息中发送正确的信息,如: header(“Content-type: image/jpeg”);

这一关主要就是通过getimagesize检测的图片的类型,还是和上一关类似,上传一个图片马就可以了。

pass-15

通过exif_imagetype()读取图像第一个字节并检查签名。返回结果和getimagesize的索引2类似,但它更快。

还是和上面一样上传一个图片马就行了,但要打开php_exif扩展。

pass-16

经过了二次渲染,原来加在后面的图片马被删掉了,所以这个要对比前后文件差异,然后把代码插在未被修改的地方就行了。

参考:二次渲染绕过

pass-17

代码审计可以看出是白名单过滤,但它是先把文件移动到文件夹下,然后判断如果文件后缀不对再删除文件。于是就会有一小段时间是存在那个文件夹的,所有就可以通过条件竞争来绕过。同时模拟很多人上传文件和访问,只要有一次访问成功就可以创建后门。

参考:条件竞争

pass-18

通过代码审计可以看出它最后是先上传的文件,然后改的名字,于是也可以通过条件竞争上传webshell。

pass-19

代码审计先查看pathinfo()函数返回文件后缀,当文件名以点(.)结尾时,返回为空。于是可以通过这一点绕过黑名单检测。还能看出最后上传的文件名我们可控,于是设置文件名为test.php即可上传。除此之外还可以通过大小写绕过黑名单检测。还可以用<CVE-2015-2348 move_uploaded_file() 00截断>

pass-20

从代码审计可以看出首先经过了一个Content-Type检测,然后把保存的文件名进行白名单过滤,最后上传。

白名单过滤主要就是想办法绕过in_array( e x t , ext, ext,allow_suffix),而对于in_array(string,array,[strict])的绕过,再两个参数的情况下是弱比较。但在这题里面似乎利用不了,因为$file初始值是上传的文件名或者你输入的保存的文件名,然后经过了exlode函数分割变成了数组,最后通过end得到数组最后一个。

但问题就在于这个$file的初始值是我们完全可控的,然后在explode函数前它做了一个is_array()检测,所以我们可以自己直接给她POST传入一个数组就绕过了白名单检测。

然后看到了保存的文件名是通过$file数组获取的,reset()返回数组的第一个元素,count()返回数组元素的个数,这个是关键点它返回的是设置过的数组元素个数。

<?php
$a = array();
var_dump($a[4]);                    //NULL
echo "<br>".count($a)."<br>";       //0
$a[0]='123';
$a[4]="hhh";
echo count($a)."<br>";              //2
$a[4]=null;
echo count($a)."<br>";              //2
var_dump($a[4]);                    //NULL
?>
           

于是就可以传入一个数组save_path[0]=“demo.php”,save_path[2]=“jpg”;这样$file[count($file)-1]就为空,就绕过了最后文件保存的文件名后缀了。

upload-labs通关简述以及文件上传小结

总结

前端检测

直接禁用javascript或者抓包就OK了。

文件类型检测(Content-Type)

也可以直接抓包修改Content-Type字段。

文件名检测(File_Name)

黑名单:

  • 大小写绕过(strtolower())
  • 罕见后缀(eg:phtml,php5等)
  • 文件后缀加空格绕过(trim())
  • 末尾加点(deldot()/strrstr())
  • 末尾空格和后缀组合(deldot(),trim())
  • 特殊符号::$DATA(windows系统下)
  • 双写绕过
  • 上传.htaccess文件(前提是配置文件有AllowOverride All)

白名单:

  • %00截断(条件:1、PHP版本<5.3.4。2、magic_quotes_gpc关闭)。注意上传时修改的位置。
  • 在上传路径或者文件名可控的条件下分析其拼接过程,通过上传特定参数绕过白名单。

文件内容检测

  • 读取文件头部判断文件类型,那么我们就可以用01editor修改文件头部,常见文件头部
  • 文件内容敏感字符检测,可以通过一些其他方法替代

二次渲染

通过上传的图片马然后再访问对比前后的区别确定是否存在二次渲染,然后找出未改变的地方插入一句话木马。