通过session写文件
漏洞点位于:/think/session/Store.php
public function setId($id = null): void { $this->id = is_string($id) && strlen($id) === 32 ? $id : md5(microtime(true) . session_create_id()); }
|
针对sessionid的校验不严
![](/img/loading.gif)
之后初始化session
![](/img/loading.gif)
保存session的过程: think/session/Store.php
public function save(): void { $this->clearFlashData();
$sessionId = $this->getId();
if (!empty($this->data)) { $data = $this->serialize($this->data);
$this->handler->write($sessionId, $data); } else { $this->handler->delete($sessionId); }
$this->init = false; }
|
进入到 write
函数写入
最后存储到文件中
![](/img/loading.gif)
这样,如果我能控制session的数组中的某个值,就能直接写入shell
成功写入:
![](/img/loading.gif)
6.0 POP链分析
入口
![](/img/loading.gif)
进入 save
函数
![](/img/loading.gif)
继续步入
![](/img/loading.gif)
进入到 cleanContents
函数,直接返回原值(没有过滤因为不是多维数组)
public function cleanContents(array $contents) { $cachedProperties = array_flip([ 'path', 'dirname', 'basename', 'extension', 'filename', 'size', 'mimetype', 'visibility', 'timestamp', 'type', ]);
foreach ($contents as $path => $object) { if (is_array($object)) { $contents[$path] = array_intersect_key($object, $cachedProperties); } }
return $contents; }
|
返回
![](/img/loading.gif)
跟进 set
函数,这里的 $this->store
已经被覆盖为 File 类
![](/img/loading.gif)
![](/img/loading.gif)
最后有两个利用方式:
protected function serialize($data): string { if (is_numeric($data)) { return (string) $data; }
$serialize = $this->options['serialize'][0] ?? "\Opis\Closure\serialize";
return $serialize($data); }
|
利用伪协议任意文件写入
![](/img/loading.gif)