HITCON CTF 2018 - One Line PHP Challenge
每年HITCON CTF中,我都会准备至少一个PHP漏洞利用挑战,其源代码非常直接、简短且易于审查,但难以利用!我已将所有挑战放在这个GitHub仓库中,您可以查看,以下是一些列表:P
-
2017 Baby^H Master PHP 2017 (0/1541 解决)
- 使用Phar协议反序列化恶意对象
- 硬编码匿名函数名称 \x00lambda_%d
- 在Apache Pre-fork模式下破坏共享VARIABLE状态
-
2017 BabyFirst Revenge v2 (8/1541 解决)
- 在4字节内进行命令注入
-
2016 BabyTrick (24/1024 解决)
- 在反序列化中创建意外对象且不调用__wakeup()
- MySQL UTF-8排序规则 - SELECT ‘Ä’=‘a’ 为True
-
2015 Babyfirst (33/969 解决)
- PHP正则表达式中的多行匹配
- 无符号命令注入
-
2015 Use-After-FLEE (1/969 解决)
- 绕过disable_functions和open_basedir
- 编写PHP use-after-free漏洞利用
- 绕过全保护(DEP / ASLR / PIE / FULL RELRO)
- 在unserialize()中利用SplDoublyLinkedList的另一个Use After Free漏洞
今年,我设计了另一个挑战,它是我所有挑战中最短的一个 - 一行PHP挑战!(还有另一个PHP代码审查挑战叫做Baby Cake,您可能会感兴趣!)在比赛期间,只有3支队伍(共1816支)解决了它。这个挑战展示了PHP如何被“挤压”。初始想法来自@chtg57的PHP错误报告。由于PHP中默认启用了session.upload_progress,因此您可以控制PHP SESSION文件中的部分内容!基于这个特性,我设计了这个挑战!
挑战很简单,只有一行代码,并告诉您它在Ubuntu 18.04 + PHP7.2 + Apache的默认安装下运行。以下是完整的源代码:
|
|
利用会话上传进度
通过上传进度特性,尽管您可以控制SESSION文件中的部分内容,但仍需克服几个障碍!
包含悲剧
在现代PHP配置中,allow_url_include始终为Off,因此RFI(远程文件包含)是不可能的,并且由于新版Apache和PHP的加固,也无法包含LFI利用中的常见路径,如/proc/self/environs或/var/log/apache2/access.log。
也没有地方可以泄漏PHP上传临时文件名,因此LFI WITH PHPINFO() ASSISTANCE也是不可能的 :(
会话悲剧
PHP检查值session.auto_start或函数session_start()以了解是否需要处理当前请求的会话。不幸的是,session.auto_start的默认值为Off。然而,有趣的是,如果您在multipart POST数据中提供PHP_SESSION_UPLOAD_PROGRESS,PHP将为您启用会话 :P
|
|
清理悲剧
尽管互联网上的大多数教程建议您将session.upload_progress.cleanup设置为Off以进行调试,但PHP中session.upload_progress.cleanup的默认值仍为On。这意味着您的会话中的上传进度将尽快被清理!
这里我们使用竞争条件来捕获我们的数据! (另一个想法是上传一个大文件以保持进度)
前缀悲剧
好的,现在我们可以控制远程服务器上的某些数据,但最后一个悲剧是前缀。由于session.upload_progress.prefix的默认设置,我们的SESSION文件将以一个烦人的前缀upload_progress_开头!例如:
|
|
为了匹配@<?php,我们结合多个PHP流过滤器来绕过那个烦人的前缀。例如:
|
|
在PHP中,base64会忽略无效字符。因此,我们结合多个convert.base64-decode过滤器,对于有效载荷VVVSM0wyTkhhSGRKUjBKcVpGaEtjMGxIT1hsWlZ6VnVXbE0xTUdSNU9UTk1Na3BxVEc1Q2MyWklRbXhqYlhkblRGZEJOMUI2TkhaTWVUaDJUSGs0ZGt4NU9IWk1lVGgy,SESSION文件看起来像:
|
|
P.s. 我们添加ZZ作为填充以适应之前的垃圾
在第一次convert.base64-decode之后,有效载荷将看起来像:
|
|
第二次,PHP将解码hikYUU…为:
|
|
第三次convert.base64-decode,它变成我们的shell有效载荷:
|
|
好的,通过结合上述技术(会话上传进度 + 竞争条件 + PHP包装器),我们可以获取shell! 以下是最终的利用代码!
|
|