ShopXO v6.3.0 导致 服务器 Webshell 恶意文件安全事件排查与修复全记录

告警时间:2026-08-16 下午(GMT+8)
服务器环境:腾讯云轻量服务器 | OpenCloudOS | 宝塔面板 | Nginx + PHP 8.2.x + ThinkPHP 8.0.x + ShopXO v6.3.0(已应用本次安全修复)

说明:本文已脱敏,域名、公网 IP、服务器实例 ID 等均以占位符或泛化描述代替。


一、事件背景

收到腾讯云主机安全告警通知:

项目详情
告警时间2026-08-16 下午
文件路径/tmp/php9pDNFw
病毒名Php.Backdoor.Webshell.Rwhl
威胁等级严重
标签特征Webshell

本文完整记录了从发现告警到定位攻击源、分析攻击路径、完成修复加固的全过程。


二、排查过程

2.1 第一步:检查恶意文件

首先检查告警中的恶意文件是否仍然存在:

ls -la /tmp/php9pDNFw

结果:文件已不存在,可能已被主机安全自动隔离或删除,或被 PHP 进程自动清理。


2.2 第二步:确认服务器 Web 服务环境

检查服务器上运行的 Web 服务和 PHP 相关进程:

ps aux | grep -E 'nginx|apache|httpd|php-fpm|php' | grep -v grep
ss -tlnp | grep -E '80|443|8080|8443'
php -v

结果:

  • Nginx + PHP-FPM(宝塔面板环境)
  • Web 服务监听 80、443 端口
  • PHP 版本:8.2.x
  • PHP-FPM 通过 Unix Socket /tmp/php-cgi-82.sock 监听,仅允许 127.0.0.1 连接

2.3 第三步:确认站点配置与日志路径

查看 Nginx 配置和站点日志:

find /www/server/panel/vhost/nginx -name '*.conf'
ls -la /www/wwwlogs/

发现多个站点(域名均已脱敏):

  • 主站(ShopXO 电商系统)
  • 业务站 B
  • 业务站 C(会员站)
  • 业务站 D(FastAPI 服务)

2.4 第四步:搜索告警时段的 Web 日志

在所有站点日志中搜索告警时段前后的请求记录:

grep '16/Aug/2026:13:3[345]' /www/wwwlogs/*.log

发现攻击源:来自境外 IDC 的来源 IP(已脱敏)在 13:34 前后进行了大规模自动化漏洞扫描,发送了上百个请求,探测敏感文件、目录遍历、框架漏洞等。


2.5 第五步:分析攻击请求

攻击者的 POST 请求中有两个返回了 200 状态码:

时间请求状态码响应大小
13:34POST /index.php?option=com_jce&task=plugin.display&plugin=image&file=imgmanager200208字节
13:34POST /index.php?option=com_jce&view=editor&plugin=imgmanager&cmd=file_upload200208字节

这两个请求是 JCE(Joomla Content Editor)文件上传漏洞利用尝试,攻击者在 POST 请求体中包含了 multipart/form-data 上传数据。


2.6 第六步:主机安全日志分析

检查腾讯云主机安全(YunJing)日志,获取关键证据:

grep 'php9pDNFw\|phpJfqkRc\|/tmp/php' /usr/local/qcloud/YunJing/log/*.log

关键发现:

13:34  Malware  report  path:/tmp/php9pDNFw
13:34  Malware  open_fail  path:/tmp/phpJfqkRc
  • /tmp/php9pDNFw 在 13:34 被检测为恶意文件(文件已被 PHP 释放)
  • /tmp/phpJfqkRc 在 13:34 检测时 open_fail(文件已被 PHP 删除)
  • 两个临时文件的时间点与两个 POST 请求完美对应

2.7 第七步:攻击路径还原

综合所有证据,攻击路径如下:

攻击者(来源 IP 已脱敏)
    │
    ├── 13:34  POST /index.php?option=com_jce&task=plugin.display... (含 multipart 上传数据)
    │                │
    │                └── PHP-FPM 接收请求
    │                        │
    │                        └── PHP 在 /tmp 创建临时文件 php9pDNFw (Webshell)
    │                                │
    │                                └── YunJing 13:34 检测到恶意文件并告警
    │
    ├── 13:34  POST /index.php?option=com_jce&view=editor&cmd=file_upload (含 multipart 上传数据)
    │                │
    │                └── PHP-FPM 接收请求
    │                        │
    │                        └── PHP 在 /tmp 创建临时文件 phpJfqkRc
    │                                │
    │                                └── YunJing 13:34 检测时文件已被 PHP 自动删除
    │
    └── ShopXO (ThinkPHP) 路由未匹配 JCE 组件,返回默认首页 (208字节)
        └── 上传文件未被实际处理和保存,未造成持久化入侵

关键结论:

  1. 攻击者利用 JCE 文件上传漏洞扫描器,向 /index.php 发送了包含恶意 PHP 文件的 multipart 上传请求
  2. PHP 按标准机制将上传文件暂存到 /tmp 目录,生成临时文件 php9pDNFw 和 phpJfqkRc
  3. 由于 ShopXO 并非 Joomla,ThinkPHP 路由未匹配到 JCE 组件,返回了默认首页
  4. 上传的恶意文件未被实际处理和保存,PHP 脚本结束后自动删除了临时文件
  5. 未造成实际入侵,但暴露了安全隐患

2.8 第八步:安全隐患排查

检查 /tmp 残留文件

find /tmp -name 'php*' -type f

结果:无残留恶意文件 ✅

检查 Web 根目录

find /www/wwwroot -name '*.php' -mtime -1 | grep -v runtime

结果:无异常 PHP 文件 ✅

检查异常进程

ps aux | grep -E 'nc |ncat|socat|python -m|perl -e|bash -i' | grep -v grep

结果:无异常进程 ✅

检查 SSH 授权密钥

cat /root/.ssh/authorized_keys

结果:无异常授权密钥 ✅


2.9 第九步:发现 UEditor 未授权访问漏洞

在排查过程中,发现 ShopXO 的 UEditor 百度编辑器存在安全隐患:

代码审计:

  • app/admin/controller/Ueditor.php → 有 IsLogin() 认证 ✅
  • app/api/controller/Ueditor.php → 有 IsLogin() 认证 ✅
  • app/index/controller/Ueditor.php → 无登录认证 ❌

index 端(前台)的 Index() 方法直接调用 UeditorService::Run(input()),未授权用户可访问文件上传和 catchimage(远程图片抓取)功能。

虽然本次攻击未利用此漏洞,但这是一个严重的安全隐患,需要修复。


三、修复操作

3.1 封禁攻击来源 IP

# 封禁 Webshell 上传攻击来源 IP
iptables -I INPUT -s <来源IP-1> -j DROP

# 封禁 SSH 爆破来源 IP
iptables -I INPUT -s <来源IP-2> -j DROP
iptables -I INPUT -s <来源IP-3> -j DROP

# 保存规则,重启后持久化
iptables-save > /etc/sysconfig/iptables

验证:

iptables -L INPUT -n --line-numbers | head 10
来源(已脱敏)封禁原因
来源IP-1Webshell 上传攻击 + 大规模漏洞扫描
来源IP-2长期 SSH 爆破攻击
来源IP-3长期 SSH 爆破攻击

3.2 修复 UEditor 未授权访问漏洞

修改文件:站点根目录/app/index/controller/Ueditor.php

修改前:

public function Index()
{
    return ApiService::ApiDataReturn(UeditorService::Run(input()));
}

修改后:

public function Index()
{
    // 安全加固:禁止前台未授权访问 UEditor 上传功能(2026-08-16)
    // 如需恢复,注释掉下方 return 并取消注释原逻辑
    return ApiService::ApiDataReturn(['code' => -1, 'msg' => '禁止访问']);
    // return ApiService::ApiDataReturn(UeditorService::Run(input()));
}

修复效果:

  • Index() 方法直接返回禁止访问,不再调用 UeditorService::Run()
  • 攻击者无法再通过 index 端未授权访问 UEditor 上传和 catchimage 功能
  • ScanUpload() 方法不受影响,仍正常工作
  • 原始代码已注释保留,如日后需要恢复只需取消注释

四、安全加固建议

立即处理

序号加固项状态
1封禁攻击来源 IP✅ 已完成
2修复 UEditor 未授权访问✅ 已完成

短期加固

序号加固项说明
3配置 PHP 上传临时目录设置 upload_tmp_dir 为非 /tmp 目录,防止临时文件被直接访问
4加强 SSH 安全禁用 root 密码登录,仅允许密钥认证
5安装 fail2ban自动封禁暴力破解 IP
6确认系统二进制完整性使用 rpm -V 验证系统命令是否被篡改

长期加固

序号加固项说明
7升级 ShopXO关注官方安全更新,确认官方版本已包含本修复,及时升级到最新版本
8部署 WAF在 Nginx 层部署 Web 应用防火墙,拦截恶意扫描请求
9定期安全审计定期检查 Web 日志、系统日志和主机安全告警

五、总结

事件定性

本次安全事件为未成功的 Webshell 上传攻击。攻击者通过自动化漏洞扫描器,利用 JCE 文件上传漏洞尝试向服务器上传 PHP Webshell。由于服务器运行的是 ShopXO(基于 ThinkPHP)而非 Joomla,攻击载荷未匹配到有效路由,上传的恶意文件仅作为 PHP 临时文件存在于 /tmp 目录,未被实际执行或持久化保存。

经验教训

  1. PHP 临时文件机制:PHP 处理 multipart 上传时会在 /tmp 目录创建临时文件(命名格式 php + 6位随机字符),即使业务逻辑不处理上传文件,临时文件仍会被创建,可能被主机安全检测到
  2. 日志分析的重要性:Nginx 访问日志 + 主机安全日志的关联分析是定位攻击路径的关键
  3. 最小权限原则:前台用户不应有未授权的文件上传权限,所有上传接口都应有认证机制
  4. 主机安全的价值:腾讯云主机安全(YunJing)在本次事件中发挥了关键作用,及时检测并告警了恶意临时文件

排查方法论

告警通知 → 检查恶意文件 → 确认 Web 环境 → 搜索日志记录
    → 分析攻击请求 → 关联主机安全日志 → 还原攻击路径
    → 排查安全隐患 → 执行修复加固 → 验证修复效果

文档记录时间:2026-08-16 14:11

标签: none

添加新评论