# 第二阶段:安全审查报告 ## 审查概述 | 项目 | 详情 | |------|------| | 审查日期 | 2026年5月19日 | | 审查范围 | SQL注入、XSS、CSRF、认证授权、文件上传、支付安全、会话管理 | | 发现问题数 | **47个** | | 严重风险 | 12个 | | 高风险 | 15个 | | 中风险 | 14个 | | 低风险 | 6个 | --- ## 1. SQL 注入风险 ### 🔴 严重风险 #### 1.1 用户输入直接拼接 SQL **文件**:`mcpsapi/controller/ChannelRebind.php:74` ```php $cusername = $this->input('cusername','','trim'); $whereRaw .= ' origin_cusername="'.$cusername.'" or cusername="'.$cusername.'" '; ``` **风险**:用户输入 `$cusername` 直接拼接到 SQL 语句,可直接进行 SQL 注入攻击 **相同问题位置**: - `guildapi/controller/ChannelRebind.php:74` - `admin/controller/MemberRebind.php:97` #### 1.2 JOIN 条件直接拼接用户输入 **文件**:`api/controller/v2/Gift.php:206` ```php ->join('cy_libaoinfo a', 'll.infoid=a.id and ll.user_id="' . $this->input['userid'] . '"') ``` **相同问题**:`api/controller/v1/Gift.php:108` #### 1.3 Db::query 使用变量插值 **文件**:`common/logic/Complex.php:166` ```php $query = Db::query("SELECT SUM(total_amount*divide_point) as total FROM cy_polychannel_game_frozen WHERE `channel_id`={$channel_id} AND `status`=1"); ``` ### 🟡 中风险(约 50+ 处) 多个文件使用 `whereRaw` 配合变量插值但未参数绑定: - `api/controller/v2/User.php:918` - `api/controller/v2/Gift.php:41` - `service/WelfareService.php` 多处 - `admin/controller/Welfare*.php` 多处 - `guildapi/controller/*.php` 多处 - `mcpsapi/controller/*.php` 多处 ### 修复建议 ```php // ❌ 错误写法 $whereRaw .= ' origin_cusername="'.$cusername.'"'; // ✅ 正确写法 $whereRaw .= ' origin_cusername=?'; $bindParams[] = $cusername; ``` --- ## 2. 认证与授权 ### 🔴 严重风险 #### 2.1 GuildAPI GET 请求免密登录 **文件**:`guildapi/controller/Login.php:98-103` ```php }else{ $username = trim(input('get.username')); $adminInfo = Db::name('nw_channel_admin')->where(['username' => $username])->find(); return $this->getdoLogin($adminInfo); // 直接登录,无密码验证! } ``` **风险**:通过 GET 请求仅传 `username` 即可直接登录,无需密码 #### 2.2 权限检查逻辑缺陷 — 未注册规则默认放行 **文件**:`common/logic/Auth.php:46-48` ```php if ($findAuthRuleCount == 0) { //return false; return true; // ← 关键缺陷:未配置的路由默认放行 } ``` **风险**:任何未配置到菜单的控制器/操作都无需权限即可访问 #### 2.3 密码使用 MD5 哈希 **文件**:`common.php:681-684` ```php function mg_password($pw) { return md5(Env::get('ADMIN_PASS_PRE') . $pw); } ``` **风险**:MD5 已不安全,易被彩虹表攻击 ### 🔴 高风险 #### 2.4 密码修改存在越权风险(IDOR) **文件**:`admin/controller/Login.php:206-253` ```php $id = input('post.id','','intval'); // id 从客户端获取 $adminModel->where(['id'=>$id])->update(['password'=>mg_password($new_password)]); ``` **风险**:未校验是否为当前登录用户,可修改其他管理员密码 #### 2.5 硬编码超级管理员 ID **文件**:`common/logic/Auth.php:33` ```php if ($userId == 1) { return true; } // ID=1 直接跳过权限检查 ``` **相同位置**:`admin/controller/Rbac.php:33`, `admin/controller/User.php:40` #### 2.6 API 调试模式可绕过加密和签名 **文件**:`api/controller/Api.php:65-110` ```php if (!$decryptStr || $api_debug == true) { $this->input = input(); // 直接使用明文参数,绕过 AES 和签名验证 } ``` **风险**:通过请求头 `qmapidebug: true` 可绕过所有安全验证 ### 🟡 中风险 #### 2.7 Admin 登录无暴力破解防护 **文件**:`admin/controller/Login.php:110-121` - 无登录失败次数限制 - 无 IP 限流 - 无账号锁定机制 #### 2.8 API 签名使用 MD5 + AES-ECB **文件**:`api/controller/Api.php:154,204` ```php $mysgin = md5($arg); // MD5 签名强度不足 $str = openssl_encrypt($data, 'AES-128-ECB', $key); // ECB 模式不安全 ``` --- ## 3. XSS 防护 ### 🔴 严重风险 #### 3.1 Admin 模板大量反射型 XSS **位置**:`admin/view/` 下 **652+ 处** 以下模板直接输出未转义的用户输入: ```html ``` **完整漏洞列表**: | 文件 | 行号 | 变量 | |------|------|------| | `admin/view/pay/list.html` | 134,189,195,201,208 | orderid, username, roleid, rolename, servername | | `admin/view/pay/index.html` | 158,164 | orderid, username | | `admin/view/member/login_list.html` | 73,80 | username, imeil | | `admin/view/member/bind_list.html` | 55,63 | username, mobile | | `admin/view/member/index.html` | 163,170 | m_nickname, m_username | | `admin/view/game_package/add.html` | 165 | game_id | | `admin/view/welfare_grant/index.html` | 81 | username | ### 🟡 中风险 #### 3.2 全局输入过滤为空 **文件**:`config.php:50` ```php 'default_filter' => '' // 全局过滤为空 ``` **仅 home/mobile 模块有过滤**: ```php 'default_filter' => 'trim,htmlspecialchars,addslashes,strip_tags' ``` **admin/api/guildapi/mcpsapi 模块均无输入过滤** #### 3.3 removeXss() 定义但未使用 **文件**:`common.php:109-122` — 定义了 HTMLPurifier 过滤函数,但从未被调用 --- ## 4. CSRF 防护 ### 🔴 严重风险 #### 4.1 完全没有 CSRF 防护 | 检查项 | 状态 | |--------|------| | CSRF Token 生成/验证 | ❌ 未实现 | | 表单 `__token` 隐藏字段 | ❌ 未使用 | | ThinkPHP 内置 CSRF 中间件 | ❌ 未启用 | | 任何表单中的 CSRF 隐藏字段 | ❌ 完全没有 | **影响范围**:所有 admin 后台表单均存在跨站请求伪造风险 --- ## 5. 文件上传安全 ### 🔴 严重风险 #### 5.1 绕过框架直接使用 move_uploaded_file **文件**:`admin/controller/GamePackage.php:341` ```php $result = move_uploaded_file($_FILES['data']['tmp_name'], iconv('UTF-8', 'GBK', $filename)); ``` **风险**: - 仅检查后缀名是否为 `['ipa','apk']` - 无 MIME 类型校验 - 无文件内容校验(magic bytes) - 目录权限 `0777`(第335行) **相同问题**:`admin/controller/GameUpload.php:46` #### 5.2 Base64 图片上传类型校验可绕过 **文件**:`home/controller/Member.php:1320-1352` ```php if (preg_match('/^(data:\s*image\/(\w+);base64,)/', $base64_image_content, $result)){ $type = $result[2]; // 仅校验 base64 头部声明,不校验实际内容 ``` **风险**: - 可伪造头部上传恶意文件 - 文件写入到 `RUNTIME_PATH` 目录 ### 🟡 中风险 #### 5.3 上传目录无执行限制 - `public/.htaccess` 文件为空 - 上传目录没有 `.htaccess` 禁止 PHP 执行 - 如果上传了 `.php` 文件可直接执行 #### 5.4 后缀名校验逻辑缺陷 **文件**:`admin/controller/GamePackage.php:313-316` - 未考虑大小写(如 `.APK`) - 未考虑双扩展名(如 `.apk.php`) --- ## 6. 支付安全 ### 🔴 严重风险 #### 6.1 硬编码支付密钥 **文件**:`service/PayService.php:575` ```php $params['sign'] = $wxPay->MakeSign($params, '66052a198653943dbc6c8032f1a40a9c'); ``` **相同问题**: - `common/factory/pay/SywPay.php:107,203` - `common/logic/PayCallback.php:182` #### 6.2 SSL 证书验证禁用(全局 51 处) ```php curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); ``` **位置**: - `common.php:373-374,884-885` - `service/PayService.php:880-881,914-915` - `common/library/WeixinPay.php:85-88` #### 6.3 金额精度问题 **文件**:`common.php:1475-1489` ```php function formatFenToYuan($fen, $long = 2) { return number_format($fen / 100, $long, '.', ''); // 浮点数除法可能丢失精度 } ``` ### 🟡 中风险 #### 6.4 缺少重放攻击防护 - 回调接口无 nonce/timestamp 验证 - 无请求频率限制 #### 6.5 订单状态竞态条件 **文件**:`api/controller/v1/PayNotify.php:950-951` ```php $payInfo = $payModel->where(['orderid' => $orderid])->find(); if ($payInfo['status'] == 1 && $payInfo['real_amount'] == $real_amount) { return true; // 先查询再更新,存在并发风险 } ``` #### 6.6 签名算法安全性低 - 多处使用 MD5 签名 - `PayNotify.php:367` - `md5($str . md5($key))` --- ## 7. 其他安全问题 ### 🟡 中风险 #### 7.1 Cookie 安全配置缺失 **文件**:`config.php:286-290` ```php 'secure' => false, // 允许 HTTP 明文传输 'httponly' => '', // JS 可读取 Cookie ``` #### 7.2 CORS 配置过于宽松 **文件**:`public/index.php:14`, `guildapi/controller/Guild.php:70` ```php header('Access-Control-Allow-Origin: *'); // 允许任意来源 ``` #### 7.3 安全响应头完全缺失 未设置以下安全头: - `Content-Security-Policy` - `X-Frame-Options` - `X-XSS-Protection` - `X-Content-Type-Options` - `Strict-Transport-Security` #### 7.4 默认开启调试模式 **文件**:`config.php:24` ```php 'app_debug' => Env::get('app_debug', true) // 默认开启 ``` --- ## 8. 问题汇总 ### 按风险等级分类 #### 🔴 严重风险(需立即修复) | 序号 | 问题 | 位置 | |------|------|------| | 1 | SQL 注入 - 用户输入直接拼接 | `mcpsapi/controller/ChannelRebind.php:74` | | 2 | SQL 注入 - JOIN 条件拼接 | `api/controller/v2/Gift.php:206` | | 3 | GuildAPI GET 免密登录 | `guildapi/controller/Login.php:98-103` | | 4 | 权限未注册规则默认放行 | `common/logic/Auth.php:46-48` | | 5 | 密码使用 MD5 哈希 | `common.php:681-684` | | 6 | Admin 模板 652+ 处 XSS | `admin/view/` 多处 | | 7 | 完全没有 CSRF 防护 | 全局 | | 8 | 文件上传绕过框架 | `admin/controller/GamePackage.php:341` | | 9 | 硬编码支付密钥 | `service/PayService.php:575` | | 10 | SSL 证书验证禁用(51处) | `common.php` 等 | | 11 | API 调试模式绕过验证 | `api/controller/Api.php:65-110` | | 12 | Base64 上传校验可绕过 | `home/controller/Member.php:1320` | #### 🔴 高风险 | 序号 | 问题 | 位置 | |------|------|------| | 1 | 密码修改 IDOR 越权 | `admin/controller/Login.php:206` | | 2 | 硬编码超管 ID | `common/logic/Auth.php:33` | | 3 | SQL 注入 - Db::query 变量插值 | `common/logic/Complex.php:166` | | 4 | 上传目录 0777 权限 | `admin/controller/GamePackage.php:335` | | 5 | 金额精度问题 | `common.php:1475-1489` | #### 🟡 中风险 | 序号 | 问题 | 数量 | |------|------|------| | 1 | whereRaw 未参数绑定 | 约 50+ 处 | | 2 | 登录无暴力破解防护 | 1 处 | | 3 | API 签名 MD5+ECB | 多处 | | 4 | 缺少重放攻击防护 | 全局 | | 5 | 订单竞态条件 | 1 处 | | 6 | Cookie 配置不安全 | 全局 | | 7 | CORS 过于宽松 | 2 处 | | 8 | 安全响应头缺失 | 全局 | | 9 | 全局输入过滤为空 | 1 处 | | 10 | 上传目录无执行限制 | 全局 | --- ## 9. 修复优先级 ### 第一优先级(立即修复 - 安全漏洞) 1. 修复 SQL 注入高风险点(参数绑定) 2. 删除 GuildAPI GET 免密登录 3. 修复权限检查逻辑(`return false`) 4. 修复 Admin 模板 XSS(转义输出) 5. 添加 CSRF Token 6. 修复文件上传安全问题 ### 第二优先级(尽快修复) 1. 密码哈希升级为 bcrypt/argon2 2. 限制 CORS 来源 3. 启用 SSL 证书验证 4. 添加安全响应头 5. 密钥从环境变量读取 6. 禁用生产环境调试模式 ### 第三优先级(计划修复) 1. 升级签名算法(HMAC-SHA256) 2. 添加登录暴力破解防护 3. 添加重放攻击防护 4. 金额处理改用 bcmath 5. 完善日志脱敏 --- ## 10. 参考代码 ### SQL 注入修复示例 ```php // ❌ 错误 $whereRaw .= ' origin_cusername="'.$cusername.'"'; Db::query("SELECT * WHERE id={$id}"); // ✅ 正确 $whereRaw .= ' origin_cusername=?'; $bindParams[] = $cusername; Db::query("SELECT * WHERE id=?", [$id]); ``` ### XSS 修复示例 ```html ``` ### 密码哈希修复示例 ```php // ❌ 错误 return md5($prefix . $password); // ✅ 正确 return password_hash($password, PASSWORD_DEFAULT); // 验证 return password_verify($input, $hashedPassword); ``` ### CSRF Token 示例 ```html
{csrf_field()}
``` --- *审查报告生成时间:2026年5月19日*