点击上方蓝字·关注我们
由于传播、利用本公众号菜狗安全所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,公众号菜狗安全及作者不为此承担任何责任,一旦造成后果请自行承担!如有侵权烦请告知,会立即删除并致歉。
最近因为二期公开课原因开始复习PHP代码审计,搞了几套源码由简到难审审,水水文章
环境搭建
代码审计
路由分析
鉴权分析
任意文件上传RCE
存储型XSS
最后
环境搭建
项目地址:https://gitee.com/wcms/WCMS
我这里采用小皮面板搭建,源码下载到本地后,小皮面板配置信息
确认,然后访问/install.php文件跟着流程搭建即可
这里我没找到项目密码,然后加密方法我懒得去找了,提供个解决方案
注册个新账户,然后在数据库中把groupid的值改成1
然后就可以正常登录了
代码审计
路由分析
查看入口文件index.php,前面都是配置信息
关注app实例这一块,跟到App.php
路由解析的方法,这里先判断controllers目录下是否存在对应访问文件,然后判断Admin目录下的是否存在访问文件
对应方法,然后结合功能点访问的数据包,就能大概知道对应功能点代码如何构造路由触发了
鉴权分析
看下网站后台权限校验逻辑
对应文件:app/admin/AdminController.php
可以看到主要是校验COOKIE中的openid字段,有几个校验
1、判断是否存在openid字段,不存在返回到登录接口
2、通过openid获取用户信息判断status字段是否为大于0
3、判断groupid字段的值是否为1
那么这里我们要关注的点就是openid能否伪造,抓个登入数据包看下openid的生成逻辑
跟进login方法
这里通过isLogin方法操作我们传入的mobile_phone和password,跟进方法
这里就是通过我们传入的数据带入数据库查询,然后返回数据,我们回到前面openid生成的那块代码
$encryptSer=new EncryptService();
$code = "wcms#" . $rs['data']['uid'] . "#wcms";
$openid=$encryptSer->jiami($code);
setcookie("openid", $openid, time() +86400, "/");
return array('status'=>true,'data'=>array('openid'=>$openid),true);
}
这里除了uid还有个data,这个是获取的用户数据,uid还能尝试遍历,data没法获取,那么这里没办法伪造openid
任意文件上传RCE
全局搜索upload类似关键词
找到个upload方法,看下里面是咋处理的
public function upload ($type)
{
// 调用thumb方法处理上传的文件,并获取处理后的文件信息
$file = $this->thumb($_FILES['upload'], 'image');
// 根据$type参数决定返回值的格式
if($type) {
// 如果$type为真,返回JSON格式的文件信息
echo json_encode($file);
return;
}
// 获取CKEditor的回调函数编号
$callback = $_REQUEST["CKEditorFuncNum"];
// 构建并输出用于CKEditor的JavaScript调用,以在编辑器中显示上传的文件信息
echo "<script type='text/javascript'>window.parent.CKEDITOR.tools.callFunction($callback,'" .
$file['message'] . "','');</script>";
}
跟进thumb方法
public function thumb ($files, $dir = "thumb")
{
$imagetrans = new Image();
return $imagetrans->upload($files, $dir,false);
}
这里dir是有默认值的,继续跟进upload方法
前面都是正常接受文件内容的代码,我们的重点在文件后缀是否可控,文件内容是否有检测
// 如果没有错误发生(错误代码为'0'),则执行文件上传逻辑
if ($error == '0') {
// 提取文件类型,从文件名中获取从第一个点之后的部分
$fileType = substr($name, strpos($name, ".") + 1);
// 获取一个随机的前缀,用于生成唯一的文件名
$prefix = $this->getRandPrefix();
// 生成新的文件名,结合日期、随机前缀和文件类型,以确保唯一性和按日期排序
$newName = date("YmdHi") . $prefix . "." . $fileType;
// 拼接保存路径和新文件名,得到完整的文件路径
$filepath = $savePath . $newName;
// 将临时上传的文件移动到指定的路径,完成文件上传
move_uploaded_file($tmp_name, $filepath);
}
这里通过substr获取上传的文件后缀,然后拼接随机前缀生成新的文件名,最后通过move_uploaded_file方法上传文件,那么这里是存在任意文件上传的,因为文件后缀我们可控,也没文件内容检测
漏洞验证
在编辑器的图片上传功能点
拼接访问
成功执行代码
存储型XSS
XSS优先寻找前台能写的功能点
漏洞在账户注册
抓包,修改用户名为XSS_poc,因为用户名会在后台显示
这里看到有检测,感觉回显信息全局搜索定位到代码或者根据路由定位也行
这里有个filter(过滤)方法跟进下
这里使用正则表达式 #[*./?-%!]+#i
来过滤以下字符:*
, .
, /
, ?
, -
, %
, !
那么我们的poc就得不包含这些字符
绕过POC:<img src=x onerror=alert(1)>
模拟管理员在后台用户功能点触发js代码
最后
二期公开课《PHP代码审计速成》在四月初开课,后续直播通知和课程详情都会在交流群中发布,有需要的师傅可以加我VX,备注:交流群,我拉你进群
原文始发于微信公众号(菜狗安全):PHP代审之WCMS11
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论