文件上传安全

发布于:2025-03-12 ⋅ 阅读:(34) ⋅ 点赞:(0)

uplabs靶场

Pass1--前端验证

        此关有后缀白名单验证,但是验证方法在前端处理,解题方法关闭浏览器Javascript。该设置在右上角...中------>Cookie 和网站权限--------->JavaScript中关闭。

考虑用 Burp Suite抓包修改后缀即可成功。

Pass2-content-type

        本关检测数据包头部里的content-tupe字段是否在白名单里,把抓到的包里的该字段改为白名单里的 image/jpeg即可。

Pass3---黑名单

        黑名单不允许上传这四种后缀的文件,那上传其他后缀的即可。这种方法生成的文件是随机名称文件,该如何访问呢?

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

 Pass4---黑名单

        此关黑名单过滤了更多的后缀,但是漏掉了.htaccess文件,这个文件会在Apache或者nginx的网站目录下自动生成,功能是里面存有的指令可以作用于该目录和子目录下的所有文件。

php
<FilesMatch "test.jpg">
  SetHandler application/x-httpd-php
</FilesMatch>  //将该目录以及子目录下的test.jpg当作php文件执行

编写该文件上传后再上传带有恶意代码的test.jpg文件

访问有问题,看起来文件没有生效。

 重启Nginx没有用,文件都上传成功。

检查.htaccess文件内容:

 检查test.jpg文件,看起来也没有问题。

 直接改为test.php访问测试,访问成功,应该是.htaccess没有生效。

 nginx默认没有包含该文件进来,找到配置文件,添加:

但是这里nginx重启动会失败,在Linux环境下才可以生效。就不浪费时间布置环境。

Pass5 ..与user.ini

        测试..绕过,去掉一个.后剩余名称为tese.php.,在Windows下自动删除.,以达到绕过黑名单的目的。实际效果无效,原因未知。

尝试第二个方法,创建.user.ini文件:

auto_prepend_file string

 上传.user.ini文件:

 访问test.jpg文件测试:

无法正常解析,与.htaccess文件相同,无法生效,应该是集成环境的问题。 

Pass6---大小写绕过

        抓包修改后缀为大小写混合绕过黑名单限制。

Pass7----空格绕过

        这一关缺少了前后去空格操作,抓包在后面添加空格以绕过黑名单。

Pass8.绕过

        缺少过滤后缀.的函数,抓包+.绕过黑名单。

Pass9---::$DATA特殊字符绕过

        在Windows下,::$DATA特殊字符和.相似,会自动去除,但是可以绕过php代码黑名单。

 Pass10---..绕过

        修改后缀  .+空格+.绕过黑名单。

Pass11----双写绕过

        双写后缀过滤后成为正确的后缀。

 Pass12---%00截断(get)

        php代码底层为c语言,在C语言中字符串的截断符为/0,使用这个机制,让代码后面的部分被截断无法生效。

这里应该是截断失败了,看文件名字是通过随机数+时间生成的,为什么截断没有生效?

 为什么会有上传出错,来分析一下代码。

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

这个函数返回值为否,要么上传的临时文件不存在,要么路径错误,显然刚刚上传成功了,应该是文件不存在导致的。

试着修改php.ini文件magic_quotes_gpc属性测试:

仍然不太行,可能是版本太高。下载一个低版本试试,网上下了5.2.9版本的测试:

 

Pass13----%00截断(post)

        post传参的情况下,想要使用%00截断程序,需要修改16进制下的数据包。

Pass14-----图片码

        将图片与恶意代码结合到一起,绕过黑名单限制。

C:\Windows\System32>cd C:\Users\huang\Desktop

C:\Users\huang\Desktop>copy 1.png /b + test.php /a web.php
1.png
test.php
已复制         1 个文件。

C:\Users\huang\Desktop>

确保制作的图片能够正常打开,要想测试文件包含漏洞,需要PHP配置中allow_url_include选项打开远程包含。测试访问:

这里表示在制作的图片里,php代码损坏了,无法正常解析,换几张图再次尝试。

 重新制作上传测试:

又失败了,看来运气不太眷顾。再换一张测试:

成功了,运气比老师好点,哈哈哈哈哈。

Pass15-----图片码2

        15关没区别,把成功的图片再次上传测试:

Pass16---图片码3

        仍然测试:

 Pass17----二次渲染

        17关讲的是在上传过程中使用了函数打乱了图片编码,在不破坏图片主体的情况下,恶意代码就被破坏掉了,解决思路是有没有一块区域是在该过程中不会被打乱的,使用010 Editor打开一张原图片和处理后的图片,对比区域。具体操作如下:

打开010 Editor------>选择Tools------>compare file------>选择高亮显示相同部分:

很轻易就找到了相同部分,把恶意代码放到该区域就不会被破坏。

改完之后测试能不能打开图片,可以看到虽然不一样了,但是仍然可以打开图片:

上传测试:

 很遗憾,图片改废了,因此换一个合适的方法。有php脚本代码可以直接生成完好的图片码。

Pass18----条件竞争

        此关存在的代码逻辑问题,先上传判断文件是否合法,不合法即删除图片,合法重命名,在审查是否合法的过程中,有短暂的时间可以去访问上传的恶意代码。

先制作一个恶意代码文件:

<?php file_put_contents(dirname(__DIR__) . '/web.php', '<?php phpinfo();?>');

抓包发送到intruder模块:

 然后再抓恶意代码文件同样多次访问,两者一起跑,发现有成功的数据包:

成功生成恶意代码文件:

Pass19----解析漏洞+条件竞争

         这关涉及到了acaphe的解析漏洞,意思是当解析时,在文件后放acaphe解析不了的后缀,程序就会自动往前解析,例如7Z,bz2等。此方法用来绕过白名单限制。

当使用Nginx,没有解析漏洞时,有没有其他方法来绕过白名单限制,有的,在第三关有方法,叫做.user.ini文件,让程序解析jpg文件为php文件。然后利用条件竞争漏洞,在没有改名之前访问恶意文件。

但是集成环境的原因.user.ini文件并不生效,测试acaphe后缀解析漏洞发现,没有看到解析7z文件,但是文件名被改掉了。

查看上传成功的文件:

 这是成功上传会变为upload+time.7z,可是访问无法成功:发了10000多个都不成功,可能是包有问题。

检查恶意文件代码无误:

 可能是acaphe版本太高,切换低版本尝试可能会成功。

Pass20----大小写绕过

        绕过黑名单限制使用大小写混合,会检测你保存的文件名,保存的后缀要过黑名单检验:

if(!in_array($file_ext,$deny_ext)) {
            $temp_file = $_FILES['upload_file']['tmp_name'];
            $img_path = UPLOAD_PATH . '/' .$file_name;
            if (move_uploaded_file($temp_file, $img_path)) { 
                $is_upload = true;
            }else{
                $msg = '上传出错!';
            }
        }else{
            $msg = '禁止保存为该类型文件!';
        }

利用Windows不识别点,PHP程序会的特点,加上点过黑名单,使保存weiphp文件:

Pass21----数组绕过

     最关键的地方在于数组的分割规则: 

  if (!is_array($file)) {
            $file = explode('.', strtolower($file));
        }

用.将数组分割开,类型检测是白名单只有jpg,png,gif,考虑绕过白名单,肯定要让检测的文件类型就是白名单的。代码里检测的是数组的最后一个字段。

 $ext = end($file);

然后拼接后缀时:

  $file_name = reset($file) . '.' . $file[count($file) - 1];
            $temp_file = $_FILES['upload_file']['tmp_name'];
            $img_path = UPLOAD_PATH . '/' .$file_name;

拼接的是用array[0]+array[len(array)-2],如果我们构造一个数组,最后一个为白名单的类型,然后array[len(array)-2]不给值,在拼接时只把array[0]内容有,可以通过嘛: