活力39284
在线时间13642 小时
阅读权限200
管理员
自由的灵魂
- 积分
- 107440
- 主题
- 5632
- 回帖
- 26662
- 注册时间
- 2003-4-10
- 最后登录
- 2026-10-2
|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
1、问题缘起
发现通过浏览器直接访问 https://www.dianbo.org/api/mail_queue_cli.php 时,脚本会以 Web 模式执行,抛出如下内容:
- #!/usr/bin/php 2026-10-02 14:35:13 Processing: [email]xxxxxx@qq.com[/email] (ID: 2792) ❌ Failed (retry 1/3): [email]xxxxxx@qq.com[/email]
复制代码
风险分析:
| 风险 | 说明 | | 信息泄露 | 暴露收件人邮箱、发送状态、队列 ID | | 恶意触发发送 | 每次访问都可能触发一封邮件发送 | | 消耗邮件配额 | 攻击者可反复访问,触发QQ邮箱限流 | | 日志污染 | 输出内容暴露内部逻辑 |
探讨中提出的关键约束:
- api/ 目录下还有 uc.php(UCenter 通信接口),不能整目录禁 PHP
- 必须精确拦截 CLI 脚本,不影响正常接口
2、解决方案
(1)简要技术分析:
采用双层防护:PHP 层通过 php_sapi_name() 检测运行模式,非 CLI 环境直接返回 403;Nginx 层通过精确匹配 location = 拦截特定 CLI 脚本,请求根本不到 PHP。
(2)修改文件列表:
| 操作 | 文件路径 | 加固方式 | | 修改 | /api/mail_queue_cli.php | PHP层 | | 修改 | /api/indexnow_cli.php | PHP层 | | 修改 | /www/server/panel/vhost/nginx/www.dianbo.org.conf | Nginx层 |
(3)关键代码段:
PHP 层加固(在两个 CLI 脚本顶部 <?php 之后插入):
- // ========== 安全加固:禁止 WEB 访问 ==========
- if (php_sapi_name() !== 'cli') {
- http_response_code(403);
- header('Content-Type: text/plain; charset=utf-8');
- exit('Forbidden: This script can only be run from CLI.');
- }
- // ========== 安全加固结束 ==========
复制代码
Nginx 层加固(在 server {} 块内插入):
- # ========== 禁止访问 CLI 脚本 ==========
- location = /api/mail_queue_cli.php {
- deny all;
- return 403;
- }
- location = /api/indexnow_cli.php {
- deny all;
- return 403;
- }
- # ========== 禁止访问结束 ==========
复制代码
3、最终实现效果
| 访问方式 | 加固前 | 加固后 | | Web 访问 mail_queue_cli.php | ❌ 执行并泄露信息 | ✅ 403 Forbidden | | Web 访问 indexnow_cli.php | ❌ 执行并泄露信息 | ✅ 403 Forbidden | | Web 访问 uc.php | ✅ 正常 | ✅ 正常(未受影响) | | CLI 执行 mail_queue_cli.php | ✅ 正常 | ✅ 正常 | | CLI 执行 indexnow_cli.php | ✅ 正常 | ✅ 正常 |
4、重要技术沉淀(需更新到固化摘要)
- 二十三、CLI 脚本安全加固(2026-10-02)
- 加固原则:api/ 目录下的 CLI 脚本禁止 Web 访问
- PHP 层:
- if (php_sapi_name() !== 'cli') {
- http_response_code(403);
- header('Content-Type: text/plain; charset=utf-8');
- exit('Forbidden: This script can only be run from CLI.');
- }
- Nginx 层:使用 location = 精确匹配,逐个拦截,不整目录禁 PHP
- 已加固脚本:mail_queue_cli.php、indexnow_cli.php
- 特殊说明:uc.php(UCenter 通信接口)不能拦截,保持 Web 访问正常
复制代码
踩坑点:
| 踩坑 | 正确做法 | | 整目录 location ~ ^/api/.*\.php$ { deny all; } | ❌ 会误伤 uc.php,导致 UCenter 通信失败 | | 只用 Nginx 层拦截 | 缺少 PHP 层兜底,若 Nginx 配置被改则失效 | | 只用 PHP 层拦截 | 请求仍到达 PHP-FPM,性能略有损耗 |
新增 CLI 脚本时的检查清单:
- 文件顶部是否加入 php_sapi_name() !== 'cli' 检测?
- Nginx 配置是否加入精确匹配拦截?
- 是否确认该脚本确实不需要 Web 访问?
5、进一步优化可能性
| 方向 | 说明 | 优先级 | | CLI 脚本统一前缀 | 所有 CLI 脚本使用 _cli.php 后缀,便于批量拦截 | 低 | | 拦截日志记录 | 记录 Web 访问 CLI 脚本的 IP,便于追溯 | 低 | | 定期扫描 | 检查 api/ 目录,确认没有遗漏的 CLI 脚本 | 中 |
|
|