文件上传功能是Web应用中最常见的安全风险点之一,攻击者可能利用漏洞上传恶意文件,导致服务器被入侵、数据泄露等严重后果。
// 使用finfo扩展验证真实文件类型
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $_FILES['file']['tmp_name']);
$allowed = ['image/jpeg', 'image/png'];
if(!in_array($mime, $allowed)) {
die('不允许的文件类型');
}
// 双重验证:扩展名+内容类型
$extension = pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION);
$allowedExtensions = ['jpg', 'png', 'gif'];
if(!in_array(strtolower($extension), $allowedExtensions)) {
die('不允许的文件扩展名');
}
// PHP配置和代码双重限制
// php.ini设置
; upload_max_filesize = 2M
; post_max_size = 2M
// 代码验证
if($_FILES['file']['size'] > 2000000) {
die('文件大小超过限制');
}
// 生成随机文件名并保留安全扩展名
$safeName = bin2hex(random_bytes(16)) . '.' . $extension;
$uploadPath = '/safe/directory/' . $safeName;
AddHandler cgi-script .php .pl .py .jsp .asp .sh .cgichmod 755 uploads/// 使用match表达式进行严格验证
$status = match($mime) {
'image/jpeg' => 'valid',
'image/png' => 'valid',
default => 'invalid'
};
if($status === 'invalid') {
throw new InvalidFileTypeException();
}
function safeUpload($file) {
// 验证上传错误
if($file['error'] !== UPLOAD_ERR_OK) {
throw new UploadException($file['error']);
}
// 验证文件类型
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $file['tmp_name']);
$allowedTypes = ['image/jpeg', 'image/png'];
if(!in_array($mime, $allowedTypes)) {
throw new InvalidFileTypeException();
}
// 验证扩展名
$ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
if(!in_array($ext, ['jpg', 'jpeg', 'png'])) {
throw new InvalidExtensionException();
}
// 生成安全文件名
$newName = bin2hex(random_bytes(8)) . '.' . $ext;
$dest = '/var/www/uploads/' . $newName;
// 移动文件
if(!move_uploaded_file($file['tmp_name'], $dest)) {
throw new UploadFailedException();
}
return $newName;
}