Java插件化漏洞扫描器Artillery:架构设计与一键Getshell实现

📅 2026/6/22 23:01:13
Java插件化漏洞扫描器Artillery:架构设计与一键Getshell实现
1. 项目概述与核心价值最近在整理自己的安全工具箱发现很多扫描器要么太重要么太老要么就是纯命令行对新手不太友好。特别是想快速验证一些常见中间件、框架的漏洞时往往需要翻好几个工具或者写一堆脚本效率很低。直到我动手把 Artillery 这个项目重新捡起来并深度定制了一番才算是找到了一个比较趁手的“瑞士军刀”。Artillery 本质上是一个用 Java 写的、支持插件化的漏洞扫描器它的图形界面GUI基于 JavaFX 开发目前已经集成了针对 Weblogic、Tomcat、Shiro、Spring 等主流组件的漏洞检测能力最关键的是它设计的目标很明确一键验证甚至一键 getshell。对于渗透测试人员、安全运维甚至是刚入门的安全爱好者来说这样一个工具的价值在于它极大地简化了从漏洞发现到验证的流程。你不需要再去记忆复杂的命令参数或者在不同的终端窗口之间切换。通过一个统一的图形界面选择目标点击扫描结果直观展示对于确认存在的漏洞往往一个按钮就能完成利用拿到 shell。这不仅仅是效率的提升更是降低了安全操作的门槛让验证工作变得更加标准化和可重复。当然工具是死的人是活的如何合规、合法地使用它是每个使用者必须坚守的底线。2. Artillery 的整体架构与设计思路2.1 为什么选择 Java 和插件化架构Artillery 选择 Java 作为开发语言在我看来首要考虑的是跨平台性和生态成熟度。Java “一次编写到处运行”的特性使得编译好的 Artillery JAR 包可以在 Windows、Linux、macOS 上无缝运行无需为每个平台单独编译这对于需要在不同环境中穿梭的安全人员来说非常友好。其次Java 拥有庞大而稳定的网络编程、多线程、反射等核心库非常适合实现扫描器所需的并发请求、协议处理、动态加载等功能。而插件化架构则是 Artillery 的灵魂所在也是它能保持生命力和扩展性的关键。传统的单体扫描器每增加一个漏洞检测模块POC都需要修改核心代码、重新编译、发布整个程序过程繁琐且容易引入错误。Artillery 的插件化设计将扫描引擎和漏洞检测逻辑彻底解耦。核心引擎只负责最通用的任务管理任务队列、调度并发线程、发送 HTTP/HTTPS 等基础网络请求、处理原始响应、提供日志和结果存储接口。它不关心具体要检测什么漏洞。漏洞检测插件POC 模块则被实现为独立的 JAR 文件或类文件。每个插件都遵循一个统一的接口规范。这个规范通常会定义几个核心方法例如check(String target)验证漏洞是否存在返回布尔值或漏洞详情。exploit(String target)利用漏洞执行命令或上传 webshell。getVulnInfo()返回漏洞的 CVE 编号、名称、风险等级等信息。当 Artillery 启动时它会扫描指定的插件目录利用 Java 的类加载机制如 URLClassLoader动态加载所有符合规范的插件类。用户在前端界面上看到的漏洞列表其实就是这些被成功加载的插件。当用户点击扫描时引擎会调用对应插件的check方法点击利用时则调用exploit方法。这种设计带来了巨大的优势热插拔新增漏洞检测能力时只需编写新的插件 JAR放入插件目录重启 Artillery 即可生效核心程序无需改动。社区贡献友好安全研究人员可以专注于编写漏洞验证代码而不必理解整个扫描器的复杂逻辑降低了贡献门槛。安全隔离即使某个插件存在 bug 或恶意代码理论上也更易于被限制在插件沙箱内虽然 Artillery 默认可能没有强沙箱但架构为这种增强提供了可能不会导致整个程序崩溃。2.2 JavaFX GUI 的优势与挑战图形界面选用 JavaFX 而非更古老的 Swing 或需要额外运行时的 Eclipse RCP 等是一个符合现代技术趋势的选择。JavaFX 提供了比 Swing 更丰富、更现代化的 UI 控件支持 CSS 样式美化动画效果也更流畅能够构建出体验更好的桌面应用。在 Artillery 中GUI 层主要承担几个职责项目管理创建、打开、保存扫描任务管理目标列表支持导入 IP/域名文件。扫描配置设置并发线程数、请求超时、代理如 Burp Suite、请求头等。状态监控实时显示扫描进度、当前正在检测的插件和目标。结果展示以表格、树形等清晰的形式展示漏洞结果并对高危漏洞进行突出显示。交互控制提供“一键验证”、“一键利用”的按钮并将利用结果如命令执行回显、Webshell 地址反馈给用户。然而JavaFX 的挑战在于其打包和分发。为了让用户无需复杂配置就能运行我们需要将 Artillery 及其所有依赖包括 JavaFX 运行时打包成一个可独立执行的“胖 JAR”Fat JAR或者使用jlink创建自定义的 JRE 镜像。目前社区常用的工具是Maven Shade Plugin或Gradle Shadow Plugin它们能将所有依赖库合并到一个 JAR 文件中。对于包含 JavaFX 的情况还需要特别注意模块化路径和原生库的处理否则很容易在非开发环境出现JavaFX runtime components are missing的错误。实操心得在打包 Artillery 这类 JavaFX 应用时我强烈推荐使用javapackager或后续版本中的jpackage工具。它可以生成真正意义上的原生安装包如 Windows 的.exe/.msi macOS 的.dmg/.pkg Linux 的.deb/.rpm。用户安装后就像使用一个普通软件一样完全感知不到 Java 环境的存在体验提升巨大。虽然配置过程稍显复杂但一劳永逸。3. 核心 POC 插件解析与实现要点Artillery 的威力完全体现在其集成的 POC 插件上。我们以它目前支持的 Weblogic、Tomcat、Shiro、Spring 为例拆解一下这些插件的典型实现逻辑和注意事项。3.1 Weblogic 反序列化漏洞插件Weblogic 的反序列化漏洞如 CVE-2017-10271, CVE-2019-2725 等是它的“重灾区”。这类插件的核心逻辑是向特定的 URI如/wls-wsat/CoordinatorPortType发送一个精心构造的、包含恶意序列化对象的 SOAP/XML 请求。实现要点漏洞指纹识别在攻击前插件通常会先发送一个普通请求根据返回的 Server 头、错误页面特征等确认目标是否为 Weblogic 以及大致版本避免盲目攻击。Payload 生成利用公开的漏洞利用工具如 ysoserial生成对应的序列化 Payload。这里需要在插件中集成或调用 ysoserial 的功能。一种做法是将 ysoserial 的源码作为库编译进来另一种是在插件初始化时动态生成常用的 Gadget Chain如 CommonsCollections1, Jdk7u21的字节码。请求构造将 Payload 进行 Base64 编码嵌入到特定的 SOAP XML 模板中。请求头需设置Content-Type: text/xml。结果判断延时检测如果利用的是执行命令的 Payload可能会让目标执行sleep 5通过判断响应时间是否显著延长来确认漏洞。这种方式相对隐蔽。回显检测更直接的方式是使用能回显命令结果的 Gadget如通过修改 Tomcat 的 Response 对象在响应体中直接查找命令执行结果。DNSLog 外带最安全、最通用的方式是让目标执行一条解析特定 DNS 记录的指令如ping或curl然后监控自己的 DNSLog 平台是否有收到请求从而确认漏洞存在且可利用。注意事项反序列化 Payload 的生成和利用高度依赖目标的 JDK 版本和应用的 ClassPath。一个在测试环境成功的 Payload在生产环境可能因为缺少某个依赖库而失败。因此一个健壮的插件应该准备多种 Gadget Chain 进行尝试并具备良好的错误处理和日志输出方便使用者排查原因。3.2 Tomcat AJP 文件包含/读取漏洞插件这里主要指 CVE-2020-1938 (GhostCat)。该漏洞源于 Tomcat AJP 协议设计缺陷允许攻击者读取或包含 Web 应用目录下的任意文件。实现要点协议连接插件需要实现 AJP 协议一个二进制协议的客户端与 Tomcat 默认的 8009 端口建立 TCP 连接。这比 HTTP 协议处理要复杂一些。构造恶意 AJP 请求按照 AJP 协议格式构造一个SC_REQ_ATTRIBUTE为javax.servlet.include.request_uri的请求并将要读取的文件路径设置到javax.servlet.include.path_info属性中。发送与解析将构造好的二进制数据包发送出去并解析返回的 AJP 响应消息提取出响应体即文件内容。结果判断如果成功读取到/WEB-INF/web.xml等敏感文件内容即可判定漏洞存在。对于文件包含可以尝试包含一个已知内容的文件在响应中搜索该内容。关键代码片段示意概念性// 建立到目标 8009 端口的 Socket 连接 Socket socket new Socket(targetIp, 8009); OutputStream out socket.getOutputStream(); InputStream in socket.getInputStream(); // 构造 AJP Forward Request 数据包 byte[] ajpRequest constructAjpRequestForFileRead(/WEB-INF/web.xml); // 发送请求 out.write(ajpRequest); out.flush(); // 读取并解析 AJP 响应 byte[] response readAjpResponse(in); String fileContent parseResponseBody(response); if (fileContent.contains(web-app)) { // 漏洞存在 saveVulnResult(target, fileContent); }3.3 Shiro 反序列化漏洞插件Apache Shiro 的反序列化漏洞CVE-2016-4437 等利用方式比较特殊关键在于 Shiro 使用了硬编码的 AES 加密密钥对用户身份信息RememberMe Cookie进行序列化、加密和传输。实现要点密钥检测漏洞利用的前提是攻击者知道了目标系统使用的 AES 密钥。Shiro 历史上存在多个版本的默认硬编码密钥社区也积累了非常庞大的常见密钥字典。插件的首要任务就是“撞库”。利用流程生成一个恶意序列化对象同样使用 ysoserial。使用一个候选 AES 密钥按照 Shiro 的规则AES-CBCPKCS5Padding对序列化后的字节进行加密。将加密结果进行 Base64 编码设置为 Cookie 头中rememberMe字段的值。发送携带此 Cookie 的请求到目标。结果判断与 Weblogic 类似采用延时、DNSLog 或回显的方式判断命令是否执行成功。如果成功则不仅证明了漏洞存在还揭示了当前系统使用的加密密钥。实操心得编写 Shiro 漏洞插件时性能优化很重要。因为密钥字典可能非常大数万条如果对每个密钥都重新生成完整的 Payload 并加密会非常慢。一个优化技巧是先使用一个简单的、无害的序列化对象比如只包含一个字符串作为“探针”用所有密钥加密并发送。通过响应特征如特定的错误信息、响应时间差异快速筛选出几个最可能的密钥候选然后再用真正的恶意 Payload 针对这几个候选密钥进行尝试能极大提升检测效率。3.4 Spring 相关漏洞插件Spring 框架的漏洞类型多样例如Spring Cloud Function SpEL 注入CVE-2022-22963向特定路径发送包含恶意 SpEL 表达式的 POST 请求。Spring Framework RCECVE-2022-22965通过构造特殊的请求参数在 JDK 9 环境下利用数据绑定机制实现 RCE。Spring Security 绕过某些配置不当导致的安全绕过。实现要点这类插件的编写更需要“因地制宜”。精准指纹Spring 应用的特征可能不那么明显需要结合路径如/actuator、/functionRouter、特定的错误信息、Cookie 中的JSESSIONID命名模式等综合判断。Payload 适配不同漏洞的利用 Payload 构造方式截然不同。例如 CVE-2022-22965 的 Payload 是一系列特殊的 HTTP 请求参数而 SpEL 注入的 Payload 则是T(java.lang.Runtime).getRuntime().exec(\calc\)这样的表达式。利用链探测Spring 漏洞的利用可能依赖特定的 ClassPath如 tomcat-embed-core, spring-webmvc。插件可能需要尝试不同的内存马注入方式如 Interceptor, Controller, Servlet来适配目标环境。4. 从扫描到 Getshell一键利用的实现“一键 getshell”是 Artillery 宣传的亮点也是其工具价值的集中体现。但这背后并非一个魔法按钮而是一系列标准化、自动化的操作流程。4.1 利用流程标准化对于一个被验证存在的漏洞其利用过程可以被抽象为环境确认根据漏洞类型确认利用所需的前置条件如是否需要特定端口开放、是否需要特定权限。Payload 投递将恶意代码如 WebShell、内存马通过漏洞通道投递到目标服务器。这可能是上传一个文件也可能是通过反序列化直接注入到内存中。通道建立确保投递的 Payload 能够成功创建一个可供远程控制的持久化或半持久化通道。交互测试尝试与建立的通道进行通信验证其可用性。在 Artillery 中点击“一键利用”按钮后对应的插件会自动化执行上述流程。例如对于一个 Tomcat 上传漏洞插件会自动生成一个冰蝎Behinder或哥斯拉Godzilla的 JSP WebShell。利用漏洞的上传功能将 WebShell 文件写到 web 目录下。尝试访问这个 WebShell 的 URL如果返回特定标识如连接密码验证前的固定字符串则判定利用成功。在 GUI 上高亮显示 WebShell 的访问地址和连接密码。4.2 内存马与文件 WebShell 的选择这是利用阶段的一个关键决策点。文件 WebShell传统方式在网站目录下写入一个.jsp或.php文件。优点是稳定、兼容性好各种管理客户端支持完善。缺点是非常容易被安全软件或运维人员通过文件监控发现并清除留下明显的攻击痕迹。内存马无文件落地技术。利用漏洞将恶意代码直接注入到目标应用的运行时内存中例如注册一个恶意的 Filter、Servlet 或 Controller。优点是隐蔽性极强没有文件重启应用前难以清除。缺点是技术实现复杂依赖特定的中间件和框架版本且应用重启后即失效。一个成熟的 Artillery 插件应该根据目标环境智能选择利用方式。例如检测到是 Tomcat 9 Spring Boot可以优先尝试注入 Filter 内存马如果是老版本的 Tomcat则可能回退到上传 JSP WebShell。4.3 利用后的“清理”与持久化思考严格来说作为攻击方模拟工具在取得 shell 后还应考虑后续的持久化操作。但 Artillery 作为扫描/验证工具通常不涉及这么深。不过在插件设计时可以提供一个“清理”功能选项用于在测试结束后自动删除上传的 WebShell 文件或卸载注入的内存马这是一个很好的实践体现了负责任的安全测试态度。5. 开发与使用中的常见问题与排查5.1 插件开发常见坑点类加载冲突这是插件化架构最常见的问题。插件 A 和插件 B 可能依赖了同一个库的不同版本如 httpclient 4.5 和 4.8或者插件依赖的库与 Artillery 核心引擎依赖的库冲突。这会导致NoSuchMethodError,ClassNotFoundException等错误。解决方案使用 Maven Shade Plugin 对插件进行重打包Relocation修改其依赖库的包路径。例如将插件中org.apache.http下的所有类重命名到com.artillery.plugin.xxx.shaded.org.apache.http下实现隔离。网络环境适配插件中的 HTTP 请求代码需要处理好代理、超时、重定向、SSL 证书验证等问题。特别是在内网复杂环境下可能需要支持 SOCKS 代理或 NTLM 认证。解决方案插件的网络请求最好复用 Artillery 核心引擎提供的统一 HTTP 客户端该客户端应已集成这些配置。如果插件必须自己实现则需要提供完善的配置项。并发安全插件的方法如check可能会被多个线程同时调用。必须确保插件内的操作是线程安全的避免使用可变的共享状态。解决方案将插件类设计为无状态的Stateless所有所需信息通过方法参数传入。如果必须有状态则使用ThreadLocal或每次调用创建新实例。5.2 工具使用排查指南问题现象可能原因排查步骤启动时报JavaFX runtime components are missing运行环境缺少 JavaFX 模块或打包不正确。1. 确认使用java --module-path path-to-javafx-lib --add-modules javafx.controls,javafx.fxml -jar artillery.jar命令启动。2. 或使用打包好的原生安装包。扫描过程中程序卡死或无响应GUI 线程被耗时操作阻塞并发数设置过高导致资源耗尽。1. 检查所有耗时的插件操作如网络请求是否在后台线程执行。2. 降低扫描并发线程数。3. 检查是否有插件陷入死循环。某个特定漏洞插件总是失败插件逻辑有 Bug目标环境与插件预期不符网络策略限制。1. 打开 Artillery 的详细日志模式查看该插件执行时的具体请求和响应。2. 手动使用其他工具如 curl, burp验证漏洞是否存在。3. 检查插件依赖的库是否完整。“一键利用”成功但连接不上 WebShell防火墙/安全组拦截WebShell 路径不对连接密码错误。1. 在目标服务器上验证 WebShell 文件是否确实存在且内容正确。2. 尝试从目标服务器内部访问该 WebShell URL看是否可达。3. 核对生成的 WebShell 类型与连接客户端是否匹配。扫描结果漏报插件指纹识别不准确目标有 WAF/IPS 拦截网络不稳定导致请求超时。1. 确认目标服务的真实版本和组件。2. 尝试在 Burp Suite 中重放插件的请求观察是否被 WAF 拦截。3. 适当增加请求超时时间。5.3 性能优化与稳定性建议连接池复用在核心引擎中为每个扫描目标维护一个 HTTP 连接池避免每次请求都建立新的 TCP 连接可以大幅提升扫描速度。超时与重试策略为网络请求设置合理的连接超时、读取超时时间并实现指数退避的重试机制以应对不稳定的网络环境。资源限制在 GUI 中提供选项限制最大并发任务数、每秒请求数RPS避免对目标造成过大压力也防止程序自身资源耗尽。结果去重与聚合同一个漏洞可能被多个插件以不同方式检测到引擎需要对结果进行智能去重和聚合避免报告界面混乱。最后我想强调的是像 Artillery 这样的工具其价值在于提高安全工作的效率和标准化程度但它永远替代不了人的判断。自动化扫描的结果必然存在误报和漏报每一个高危漏洞的确认都需要人工进行审慎的复核。工具让我们跑得更快但方向和道路仍需我们自己来把握。在合规的授权范围内善用工具持续学习才是安全从业者的立身之本。