文件上传题
正常上传.png后回显文件路径
测试上传.php文件
检查源代码 发现有类型验证的逻辑
function uploadFile() {
const fileInput = document.getElementById('fileInput');
const file = fileInput.files[0];
if (!file) {
alert('请选择一个文件进行上传!');
return;
}
const allowedExtensions = ['png'];
const fileExtension = file.name.split('.').pop().toLowerCase();
if (!allowedExtensions.includes(fileExtension)) {
alert('只允许上传后缀名为png的文件!');
return;
}
const formData = new FormData();
formData.append('file', file);
fetch('upload.php', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(result => {
if (result.success) {
const uploadResult = document.getElementById('uploadResult');
const para = document.createElement('p');
para.textContent = ('地址:');
const link = document.createElement('a');
link.textContent = result.file_path;
link.href = result.file_path;
link.target = '_blank';
para.append(link);
uploadResult.appendChild(para);
alert('文件上传成功!');
} else {
alert('文件上传失败:' + result.message);
}
})
.catch(error => {
console.error('文件上传失败:', error);
});
}
前端类型验证,使用白名单过滤,用bp绕过
将后缀改为.php
上传失败,说明后台对后缀进行了验证
将content-type改为application/octet-stream
上传失败,说明后台对content-type也做了验证
思路1 绕过后缀
将常见的php1
php2
phtml
文件类型都试了一遍,都不行 说明是白名单验证
思路2 .htaccess覆盖
上传.htaccess文件
上传失败,换思路
将文件扩展名改为 png.abc(灵感来源于apache解析漏洞)
显示上传成功!!!
这就说明了,虽然他是白名单验证,但是对于文件名ant.png.abc
,他会将.png
识别为文件扩展名
将文件扩展名改为.png.php
上传成功!!!
所以后台获取文件扩展名的逻辑是 从左到后获取第一个扩展名,而apache解析文件的逻辑是从右到左获取第一个可用的扩展名,所以对于ant.png.php
,对于后台解析到png
,通过白名单,apache解析到php
使用蚁剑连接,连接成功
在根目录下获取flag
分析一下后台的源代码
<?php
$targetDir = 'uploads/';
$allowedExtensions = ['png'];
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['file'])) {
$file = $_FILES['file'];
$tmp_path = $_FILES['file']['tmp_name'];
if ($file['type'] !== 'image/png') { 就在这里过滤content-type
die(json_encode(['success' => false, 'message' => '文件类型不符合要求']));
}
if (filesize($tmp_path) > 512 * 1024) {
die(json_encode(['success' => false, 'message' => '文件太大']));
}
$fileName = $file['name'];
$fileNameParts = explode('.', $fileName); ant.png.php 被转换成数组 ['ant','png','php']
if (count($fileNameParts) >= 2) { 要修复这个漏洞只要把这里改成 ==
$secondSegment = $fileNameParts[1]; 取第二个元素为文件扩展名 这里是png
if ($secondSegment !== 'png') { 白名单过滤
die(json_encode(['success' => false, 'message' => '文件后缀不符合要求']));
}
} else {
die(json_encode(['success' => false, 'message' => '文件后缀不符合要求']));
}
$uploadFilePath = dirname(__FILE__) . '/' . $targetDir . basename($file['name']);
if (move_uploaded_file($tmp_path, $uploadFilePath)) {
die(json_encode(['success' => true, 'file_path' => $uploadFilePath]));
} else {
die(json_encode(['success' => false, 'message' => '文件上传失败']));
}
}
else{
highlight_file(__FILE__);
}
?>
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。