[GYCTF2020]EasyThinking
思路
经过测试发现有登录有搜索有回显

但是不知道搜索的是什么,尝试注入失败
username有长度为20限制


报错Thinkphp框架,版本6.0,用集成工具测试框架漏洞失败
看WP
解题
BUUCTF:[GYCTF2020]EasyThinking_buuctf [gyctf2020]easythinking-CSDN博客
网站存在源码泄露www.zip

结合上面的Thinkphp版本,去看6.x版本的漏洞,有Thinkphp的session文件名构造漏洞,刚好有源码,分析一下
vendor\topthink\framework\src\think\session\Store.php
/*
这是thinkphp中存储会话信息的代码
关键行在$this->handler->write($sessionId, $data);
其中$sessionId是$this->getId();得到的
我们看看这个write和getId的实现
*/
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;
}
/*
先看getId,我们可以看到,在id的判断中,
只要满足是字符串,并且长度为32,
就会认定为sessionid
*/
public function setId($id = null): void
{
$this->id = is_string($id) && strlen($id) === 32 ? $id : md5(microtime(true) . session_create_id());
}
public function getId(): string
{
return $this->id;
}
vendor\topthink\framework\src\think\session\driver\File.php
/*
接下来我们看write的实现
*/
public function write(string $sessID, string $sessData): bool
{
$filename = $this->getFileName($sessID, true);
$data = $sessData;
if ($this->config['data_compress'] && function_exists('gzcompress')) {
//数据压缩
$data = gzcompress($data, 3);
}
return $this->writeFile($filename, $data);
}
/*
可以看到,这是先得到$filename,在用writeFile写入的
我们先看$filename
*/
protected function getFileName(string $name, bool $auto = false): string
{
if ($this->config['prefix']) {
// 使用子目录
$name = $this->config['prefix'] . DIRECTORY_SEPARATOR . 'sess_' . $name;
} else {
$name = 'sess_' . $name;
}
$filename = $this->config['path'] . $name;
$dir = dirname($filename);
if ($auto && !is_dir($dir)) {
try {
mkdir($dir, 0755, true);
} catch (\Exception $e) {
// 创建失败
}
}
return $filename;
}
/*
关键行为$this->config['prefix'] . DIRECTORY_SEPARATOR . 'sess_' . $name
可以看到,只是加了路径前缀,而上面的name就是$sessID
session文件名为[path]/sess_[sessid]
再看writeFile,就是很简单的写入
*/
protected function writeFile($path, $content): bool
{
return (bool) file_put_contents($path, $content, LOCK_EX);
}
至此我们分析完毕,Thinkphp6.x的这个漏洞表现为,读取session值之后仅进行字符串和长度校验,然后拼接到sess_后面作为文件名,这就是说,我们可以构造sess值为0123456789012345678901234567.php来写入php文件,如果内容可控就可写马

从源码中也可以找到session的path
vendor\topthink\framework\src\think\session\driver\File.php
public function __construct(App $app, array $config = [])
{
$this->config = array_merge($this->config, $config);
if (empty($this->config['path'])) {
$this->config['path'] = $app->getRootPath() . 'runtime' . DIRECTORY_SEPARATOR . 'session' . DIRECTORY_SEPARATOR;
} elseif (substr($this->config['path'], -1) != DIRECTORY_SEPARATOR) {
$this->config['path'] .= DIRECTORY_SEPARATOR;
}
$this->init();
}
可以看到是runtime/session/sess_…
蚁剑连接

ret=127了,可能有disable_func,要用 bypass

注意
Thinkphp6.0的会话文件名构造漏洞