赛后想写一些比赛时的心得 , 但是找到的 Docker 环境都无法完美运行 , 或多或少有一些问题 , 这里就不写解题过程了 , 记录一下自己的想法吧~
checkIn
签到题难度不大 , 考得是一个文件上传漏洞 , 题目界面大概是这样的
上传一个文件 , 页面会返回对应信息 , 该题在对上传的文件进行了限制
现在问题是如何绕过这些限制 , 一个一个来看
- 文件后缀名的限制
一般来说 , PHP解析器默认解析后缀为 : phtml , pht , php , php3 , php4 , php5 的文件 , 但这些后缀名中都包含
ph
这个字符组合 , 因此想直接上传可被解析的PHP文件是不可行的!同理 , 本题对
ph
这个组合进行检测 , 因此常见的Web中间件解析漏洞也是不可行的 ------ 无论是 Apache 还是 FastCGI 解析漏洞 , 它们至少需要文件名或后缀中出现php
这个字符组合 .当遇到这类情况时 , 一个思路是尝试上传一些配置文件来修改 php 或者 Web中间件 的配置 , 这个点下面会谈到
-
文件内容的限制
文件内容中不能出现
<?
这个字符组合 , 因此常用的<?php ... ?>
文件格式无法使用 , 但是像<script language="php"> ... </script>
这类写法可以绕过<?
的内容限制还有一种思路是对文件内容进行加密或者编码( 比如 base64 编码 ) , 但是这类方法需要在解析器解析文件内容前解密或解码文件内容 , 因此需要其它的攻击方式配合
-
exif_imagetype() 函数检测
exif_imagetype() 函数用于判断一个图像文件的类型 , 官方文档是这么解释的 :
exif_imagetype() 读取一个图像的第一个字节并检查其签名 本函数可用来避免调用其它 exif 函数用到了不支持的文件类型上或和 $_SERVER['HTTP_ACCEPT'] 结合使用来检查浏览器是否可以显示某个指定的图像
重点就是
exif_imagetype()
函数会检测文件头来检查文件类型 .图片文件通常有称作幻数的头字节 , 如下所示 :
JPG : FF D8 FF E0 00 10 4A 46 49 46 GIF : 47 49 46 38 39 61 PNG : 89 50 4E 47
因此绕过该检测的方法很简单 , 给上传文件加上相应的幻数头字节就可以 , php引擎会将
<?
之前的内容当作html文本 , 不解释而直接跳过 .一般来说会选用 GIF 文件的幻数头字节来绕过检测函数 , 因为转换为文本后都是可打印字符
GIF 文件的幻数头文件文本为 : GIF89a
所以现在分析一下思路
由于无法直接上传可被 php 解释器直接解析的 ph*
文件 , 所以这里通过上传敏感的配置文件来修改服务器的配置 , 常用的有两个配置文件 : .htaccess
和 .user.ini
.htaccess
.htaccess 是一个存放与 Apache 服务器配置相关的一个纯文本文件 , 它提供了在主配置文件中定义用户自定义指令的支持( 比如 URL重定向 , 自定义错误页面 , 访问权限控制 ... ) , 类似于 Apache 的站点配置文件( httpd.conf / apache2.conf ) , 但不同的地方在于 :
.htaacess
仅作用于当前目录 , 并且在用户访问时才加载.htaccess
最常用于设置URL重定向功能 ,.htaacess
支持需要手动开启一个例子 : 对于本题 , 可以通过上传 .htaccess 使 Apache 服务器使用 php 解析器来解析 PNG 文件
浏览器访问
test.png
文件但测试时发现无法使用 .htaccess 这个文件. 因此需要用到下面这个配置文件
-
.user.ini
官方文档是这么解释 user.ini 文件的
自 PHP5.3.0 起 , PHP支持基于每个目录的 .htaccess 风格的 INI 文件 . 此类文件仅被 CGI/FastCGI SAPI 处理 . 此功能使得 PECL 的 htscanner 扩展作废 . 如果使用 Apache , 则用 .htaccess 文件有同样效果 .
php.ini 是 php 的核心配置文件 , 在 php 启动时被读取 . 而除了主 php.ini 文件之外 , PHP还会在每个目录下扫描 INI 文件 , 从被执行的php文件所在的目录一直上升到Web根目录( 也就是
$_SERVER['DOCUMENT_ROOT']
指定的目录 ) , 如果被执行的php文件在Web根目录外 , 则只扫描文件所在的目录 .而与 php.ini 不同的 ,
.user.ini
是一个可以被动态加载的ini文件 , 也就是说修改了.user.ini
文件后 , 不需要重启Web中间件 , 只需要等待user_ini.cache_ttl
设置的时间到期后 , 就可被重新加载 , 并且 ,php.ini
和.user.ini
中可设置的选项也不同( 可以理解为" 权限 "不同 ) ..user.ini 可设置的选项中有这两个项比较有意思
- auto_append_file : 指定一个文件 , 自动包含在要执行的文件末尾 , 类似与在可执行文件末尾调用了 require() 函数
-
auto_prepend_file : 指定一个文件 , 自动包含在要执行的文件开头 , 类似与在可执行文件开头调用了 require() 函数
这就类似于文件包含漏洞了 , 要知道PHP文件包含是不需要考虑文件的后缀名的 . 被包含文件中的php代码会被执行 , 非php代码会被输出 .
综上所述 , 可以上传两个文件 , 一个为 .user.ini
, 里面的内容如下
另一个为 test.jpg , 该文件中包含php代码 , 这些代码将会被自动包含到目录下每个文件开头
现在 index.php 中会自动包含这一句 php 代码 . 可以用它来执行系统命令( 比如 system("cat /flag")
)
找到的 docker 环境中上传的目录进不去 , 就不演示了~
这道题的整体思路就是这样的 : 通过 .user.ini
创建 php 后门 , 还有一些小细节 , 总体来说还是比较简单的~