0x00 基本信息

基本信息

简介

多用于团队协作,在2021年的时候呗爆出过一个前台的文件上传漏洞

之前写过利用,除了公开的方式还可以有其他的方法ShowDoc心情记录,这里对老版本看下存在什么问题,以及最新版本更新的挺大的了,默认使用的是sqlite,但是在老版本和新版本中都是可以支持mysql的,在中间的版本直接把不支持mysql驱动写在了代码里

1666086836070

文件hash

必选项

  • 2.10.8: 1fd19a2dbd52abbbddeebc5244e6774c

文件存储

必选项

  • 2.10.8:https://pan.baidu.com/s/1H0ZhjB_U0KEJlsdf02s7TA
  • 2.9.0

cms指纹

可选项,后期必选

  • header="showdoc"

源码相关

从哪下载,可选项

  • https://github.com/star7th/showdoc

cms名字

必选项,实际名字或者化名

  • showdoc

关联平台

类似第三方支付平台

0x01 代码信息

对比存在上传和不存在上传版本的代码

主要就是验证白名单后缀的参数名字写错了

1666087482123

thinkphp3.2.3的参数是exts,而allowExts好像是3.0左右的,要比3.2的版本低

除此之外,在老版本中还存在一个其他的问题

SSRF

同样在page控制器中,存在一个ajaxHttpApi方法

参数都可控

1666087641107

复现一下,可以通过报错获取文件路径

1666087975152

1
2
3
http://127.0.0.1:84/server/index.php?s=home/page/ajaxHttpApi

url=file://E:/phpstudy/directory/phpstudy_pro/WWW/www.showdoc.com/server/index.php&method=post

1666088084347

0x02 代码审计

老版本不多看了,看下最新版本,最新版本增加了不少新代码

数据库防护

既然是基于sqlite,看看对于数据库文件的防护措施,首先数据库文件的名称为showdoc.db.php

但是我们知道,就算是重命名成了php文件,不符合php格式的照样会被原样输出,比如图片马

在这里的防护措施也很简单,就是最先建立一个<?php的数据表,这样访问php文件就会直接error

1666162701570

鉴权流程

很多功能的访问都是需要登陆的,鉴权的方法如下

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
public function checkLogin($redirect = true){
if ($this->is_local_debug > 0 ) {
$login_user = D("User")->where("username = 'showdoc' ")->find();
session("login_user" , $login_user);
}

if ( ! session("login_user")) {
$cookie_token = I("user_token") ? I("user_token") : cookie('cookie_token');
if ($cookie_token) {
$ret = D("UserToken")->getToken($cookie_token);
if ($ret && $ret['token_expire'] > time() ) {
D("UserToken")->setLastTime($cookie_token);
$login_user = D("User")->where("uid = $ret[uid]")->find();
unset($ret['password']);
session("login_user" , $login_user);
return $login_user ;
}
}
if ($redirect) {
$this->sendError(10102);
exit();
}
}else{
return session("login_user") ;
}
}

这里当session中获取不到参数时,会从token中取,而cookie获取的参数是完全可控的

接下来看看getToken方法

这里重写了where方法,并通过escapeString函数对传参进行转义

1666163097420

所以从注入来说没什么可以操作的点,主义的点是checkLogin方法存在一个参数redirect,当传入的值为false时,虽然没有登陆,但不会跳转退出

参数接受

在tp3中是不支持接受json传参的,同样在showdoc的老版本中也并未引入

但是在新的版本中,php代码不在需要去解析html的模板文件,全部修改成了api接口,那在不改变框架的情况下,showdoc在base控制器中添加了如下代码

1666164029345

这就相当于在thinkphp3中引入了弱类型的问题

这个后面分析一下tp3中关于此种调用,会产生的问题

用户操作

因为大部分操作都是需要登陆之后的,所以看看对于用户存在哪些未授权的操作

注册用户

新版本默认情况下是开启了注册用户的,老版本没有这个限制注册的功能

1666164249601

虽然还有一些其他的注册方式,但都受到这个参数的限制

第一点

当开启了ldap的时候api/adminsetting/checkLdapLogin方法会注册一个admin/123456的账户

1666164597433

第二点

默认的账户名就是showdoc,当账户存在更改时

  • api/update/updateSqlite

会重新加入一个showdoc/123456的账户

1666164813132

第三点

重置密码的,不过需要在命令行模式,所以没啥用

  • api/common/repasswd
1
2
3
4
5
6
7
8
9
10
11
12
public function repasswd(){
if (preg_match("/cli/i", php_sapi_name()) ) {
if(D("User")->where("username = 'showdoc' ")->find()){
D("User")->where("username = 'showdoc' ")->save(array("groupid"=> 1,'password'=>"a89da13684490eb9ec9e613f91d24d00" )) ;
}else{
D("User")->add(array('username'=>"showdoc" ,"groupid"=>1,'password'=>"a89da13684490eb9ec9e613f91d24d00" , 'reg_time'=>time()));
}
echo "ok \n" ;
}else{
echo "please run in command line";
}
}

方法访问

thinkphp3中不支持访问非字母开头的公共方法

1666165167327

漏洞

反序列化1

这里也可以任意文件生成,但是无法写入内容,也没有覆盖的功能,只是空文件,利用方式待定

1666166000049

只有生成的功能,伪协议也用不到

1666166263509

但是pahr反序列化是可以的

反序列化2

还有一处phar反序列化

  • api/import/importFromReadingMDFile

检查登陆的方法在if条件内

1666169167225

其实这两处反序列化是不需要权限的,但是上传文件需要,windows下倒是可以直接碰撞tmp文件

linux下比较难,至于thinkphp内部的写文件或者日志的地方,后面写

复现

最新版本

这两处漏洞复现一处,这里正好利用到了之前的一个点

新版本中添加了许多第三方库,可以直接通过guzz完成

生成一个利用链

1666170378001

成功触发

1666170415990

较低版本

原来的利用链加上

  • home/item/delete

可以组合成一个完整的文件包含利用链

1666171764871

文件上传漏洞

当然这个也需要一个登陆的用户,这应该是最新版更新出来的,在2.9.0版本也不存在此问题

之前的版本的上传问题是因为,验证参数出现错误

现在的上传控制器是

  • api/attachment

这里面有个_download方法,参数倒是可控就是没法访问,原因上面已经说明,像这种进行代码迁移,比如thinkphp3升级到5,就会出现漏洞,典型的代码是weiphp

1666172026824

直接看下上传相关的代码

1666172555642

在2.9.0版本中还是黑名单,然后是针对之前的文件上传进行了修复

在最新版本中改用了白名单,具体可以看看

1666172625257

白名单其实是没有问题的,只不过验证早了

在upload类中并未设置exts参数进一步验证,导致可以绕过

1666172698921

1666172745469

复现

1
2
3
4
5
6
7
8
9
<html>
<body>
<form action="http://192.168.1.198:84/server/index.php?s=api/attachment/attachmentUpload" method="post" enctype="multipart/form-data">
<input type="file" name="file" />
<input type="submit" value="上传文件" />
</form>
</body>
</html>

注意尖括号位置

1666173224065

名字是uniqid函数生成的基于微妙的时间戳,爆破一下就ok

0x03 end