资讯动态

Java漏洞扫描系统毕设实战:四层解耦架构与POC验证设计

发布时间:2026/10/16 1:40:38 来源:尧图企业网站定制
简介本资源是一套面向计算机专业本科生的毕业设计实战项目聚焦网络安全实践能力培养提供一个基于Java开发的漏洞扫描系统完整实现适用于课程设计、毕设参考及安全工具二次开发学习。压缩包共927个文件主体包含604个Nmap脚本.nse、146个Lua插件.lua用于扩展扫描能力30个编译后Java类.class与12个源码文件.java构成核心扫描逻辑辅以XML配置、JAR依赖库、批处理脚本.bat及多份开源协议文件LGPL-2.1、MIT等整体结构体现模块化设计与工程规范性包大小为33.11MB。已有204人学习下载读者可直接获取可运行的GUI或命令行扫描系统、完整的Nmap集成方案、常见Web漏洞SQL注入、XSS等检测逻辑实现、PDF/HTML报告生成模块及配套日志与调试支持是深入理解漏洞原理与Java安全编程的优质工程范例。1. 毕业设计——基于Java的漏洞扫描系统不是写个端口探测就叫“扫描”它得能复现真实渗透链路很多同学做毕设时一搜“Java漏洞扫描”立刻被Nmap调用、Socket发包、HTTP状态码判断这些碎片信息淹没最后交出一个能扫出IP存活开放端口简单Banner识别的控制台程序答辩时被问“这个结果怎么指导修复”就卡壳。这套毕业设计资源不是教你怎么打印[] Port 80 is open而是完整覆盖从资产发现→协议解析→漏洞特征匹配→POC验证→报告生成的闭环逻辑。它面向的是需要交付可演示、可答辩、可扩展的课程设计或本科毕设场景核心价值在于所有模块都按真实安全工具分层解耦网络层/应用层/规则层/报告层每层代码带注释、带测试用例、带配置开关你改3个参数就能切到不同目标环境换2个JSON文件就能新增CVE检测项。如果你正卡在“功能堆砌但逻辑散乱”“能跑通但讲不清设计依据”“老师问‘为什么不用SpringBoot而用Netty’答不上来”的阶段这份方案就是为你写的血泪经验沉淀。2. 总体架构设计四层解耦模型与Java技术栈选型依据2.1 四层职责划分为什么必须拆开网络层、协议层、规则层和报告层传统毕设常把扫描逻辑全塞进一个Scanner.java里先建Socket连目标再拼HTTP头接着parse响应体最后if-else判断关键词。这种写法在答辩时会被直接质疑“可维护性在哪加个新漏洞要改多少行”。本方案强制分层每层只解决一类问题网络层专注连接管理TCP/UDP超时、重试、并发控制不碰业务逻辑协议层封装HTTP/HTTPS/DNS等协议构造与解析提供统一Request/Response抽象规则层以JSON驱动漏洞检测逻辑如CVE-2023-1234的路径、请求头、响应特征、验证步骤避免硬编码报告层将扫描结果结构化为HTMLPDF双格式含风险等级、修复建议、原始请求/响应快照。提示分层不是为了炫技而是让答辩时你能指着UML图说清“老师我新增一个Log4j检测只需在rules/log4j.json里配规则在ReportGenerator.java里补一句修复建议模板其他层完全不动”。2.2 Java技术栈选型为什么用Netty不用HttpURLConnection为什么规则用JSON不用XML选型必须回答“为什么不用更简单的方案”。本系统选择组合是经过压测和可维护性权衡的结果组件选用理由替代方案对比说明Netty 4.1异步非阻塞IO单机支撑500并发扫描ChannelPipeline天然适配协议解析流水线HttpURLConnection无法控制连接池粒度高并发下线程阻塞严重Jackson 2.15JSON规则文件解析速度快支持注解绑定JsonProperty直映射到Rule对象XML解析冗余且学生易在DTD声明上翻车Thymeleaf 3.1HTML报告模板语法简洁th:each遍历漏洞列表比JSP标签直观得多FreeMarker学习成本高Velocity已过时iText 7.2PDF导出支持中文宋体嵌入避免答辩现场字体乱码Apache PDFBox对中文字体处理需额外配置关键决策点当老师问“为什么不用Spring Boot”标准答案是“本系统核心是IO密集型扫描任务Spring Boot的自动配置会引入大量无用Bean内存占用增加40%而Netty原生API对连接超时、SSL握手失败等异常的捕获粒度更细——比如SslHandshakeTimeoutException能精准定位到TLS版本不兼容这在渗透测试复现中至关重要。”2.3 核心数据流图从URL输入到PDF报告的7个关键节点整个扫描流程不是线性执行而是事件驱动的状态机。以扫描http://test.com为例数据流如下输入解析TargetParser.java将URL转为Target对象含host/port/protocol/scheme校验格式并标准化资产发现NetworkDiscovery.java调用ICMPTCP SYN探测生成存活主机列表非必须但体现工程思维服务识别ServiceDetector.java向80/443端口发送HEAD / HTTP/1.1解析Server、X-Powered-By等Header规则加载RuleLoader.java读取rules/web/目录下所有JSON按appType如apache-tomcat和severityHIGH/MEDIUM分类缓存POC验证PocExecutor.java根据规则中的requestTemplate动态填充payload用Netty Channel发送截获原始二进制响应结果匹配MatcherEngine.java执行多级匹配正则提取字符串包含状态码校验响应长度阈值任一失败即终止该POC报告聚合ReportAggregator.java将所有Vulnerability对象按targetId分组注入Thymeleaf模板生成HTML再由PdfExporter.java转PDF。注意第5步的“动态填充payload”是防翻车重点——规则JSON中写path: /${payload}/test代码里用String.format()替换时必须对payload做URL编码否则空格、斜杠会导致400错误。这个细节在PocExecutor.java第89行有URLEncoder.encode(payload, StandardCharsets.UTF_8)的强制处理。3. 关键模块实现从网络层到报告层的可抄作业代码3.1 网络层Netty客户端连接池与超时熔断机制Netty不是简单创建Bootstrap而是构建可复用的连接池。核心在于ChannelPoolMap的配置——它按host:port维度缓存Channel避免重复握手开销// NetworkClientFactory.java public class NetworkClientFactory { private static final EventLoopGroup GROUP new NioEventLoopGroup(4); private static final ChannelPoolMapInetSocketAddress, FixedChannelPool POOL_MAP new AbstractChannelPoolMapInetSocketAddress, FixedChannelPool() { Override protected FixedChannelPool newPool(InetSocketAddress key) { Bootstrap bootstrap new Bootstrap(); bootstrap.group(GROUP) .channel(NioSocketChannel.class) .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 3000) // 连接超时3秒 .option(ChannelOption.SO_KEEPALIVE, true) .handler(new ChannelInitializerSocketChannel() { Override protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new HttpResponseDecoder(4096, 4096, 2048, false)); ch.pipeline().addLast(new HttpRequestEncoder()); ch.pipeline().addLast(new HttpObjectAggregator(1024 * 1024)); // 聚合大响应 } }); return new FixedChannelPool(bootstrap, new SimpleChannelPoolHandler(), 10); // 最大10连接 } }; public static Channel acquire(InetSocketAddress address) throws Exception { return POOL_MAP.get(address).acquire().get(5, TimeUnit.SECONDS); // 获取超时5秒 } }设计说明CONNECT_TIMEOUT_MILLIS3000防止目标主机宕机时线程长期阻塞HttpObjectAggregator设置为1MB因为某些漏洞响应如SSRF回显可能包含大段HTMLFixedChannelPool的maxConnections10是经测试的平衡点低于5并发扫描慢高于15触发Linux本地端口耗尽TIME_WAIT堆积。实际使用时ScannerService.java中这样调用// 扫描单个URL的核心方法 public Vulnerability scanSingleUrl(String url) { try { InetSocketAddress addr parseToInetSocketAddress(url); // 解析host:port Channel channel NetworkClientFactory.acquire(addr); FullHttpRequest request buildHttpRequest(url); // 构造HTTP请求 channel.writeAndFlush(request).sync(); // 异步发送 // 后续监听ChannelFuture获取响应... } catch (TimeoutException e) { return new Vulnerability(CONNECTION_TIMEOUT, 目标连接超时请检查网络或防火墙); } }3.2 规则层JSON驱动的漏洞检测引擎与动态POC执行规则不是静态字符串匹配而是可编程的检测流程。以检测Struts2 S2-045为例规则文件rules/struts2/s2-045.json内容如下{ id: S2-045, name: Apache Struts2 Remote Code Execution, description: 通过Content-Type头注入OGNL表达式执行任意命令, severity: CRITICAL, appType: [struts2], requestTemplate: { method: POST, path: /login.action, headers: { Content-Type: ${#context[com.opensymphony.xwork2.dispatcher.HttpServletRequest].getRealPath(/)} }, body: }, matchers: [ { type: regex, part: body, pattern: /opt/tomcat|C:\\\\Program Files }, { type: status, code: 200 } ], remediation: 升级Struts2至2.5.22以上版本禁用动态方法调用 }对应Java解析与执行逻辑在PocExecutor.java中// PocExecutor.java public Vulnerability executePoc(Rule rule, String targetUrl) { try { // 1. 解析requestTemplate生成FullHttpRequest FullHttpRequest request buildRequestFromTemplate(rule.getRequestTemplate(), targetUrl); // 2. 发送请求复用NetworkClientFactory Channel channel NetworkClientFactory.acquire(getAddress(targetUrl)); ChannelFuture future channel.writeAndFlush(request); future.await(10, TimeUnit.SECONDS); // 等待10秒 // 3. 从Channel中获取响应需自定义ChannelHandler收集响应 HttpResponse response getResponseFromChannel(channel); byte[] responseBody getResponseBody(response); // 4. 多条件匹配 for (Matcher matcher : rule.getMatchers()) { if (!matchResponse(matcher, response, responseBody)) { return null; // 任一条件失败该POC不成立 } } return new Vulnerability(rule.getId(), rule.getName(), rule.getSeverity(), response.getStatus().code(), new String(responseBody)); } catch (Exception e) { log.warn(POC execution failed for {}: {}, rule.getId(), e.getMessage()); return null; } } private boolean matchResponse(Matcher matcher, HttpResponse response, byte[] body) { switch (matcher.getType()) { case regex: String content matcher.getPart().equals(body) ? new String(body) : response.getStatus().toString(); return Pattern.compile(matcher.getPattern()).matcher(content).find(); case status: return response.getStatus().code() matcher.getCode(); default: return false; } }设计说明buildRequestFromTemplate()会自动对requestTemplate.headers中的${...}占位符进行OGNL上下文注入仅限POC验证阶段生产环境禁用matchResponse()支持body/header/status多维度匹配比单纯contains(root:x:0:)更可靠所有异常捕获后返回null而非抛出保证单个POC失败不影响后续规则执行——这是答辩时强调“健壮性”的关键点。3.3 报告层Thymeleaf动态模板与iText中文字体嵌入HTML报告不是静态页面而是实时渲染扫描结果。report/template/vuln-report.html核心片段!DOCTYPE html html xmlns:thhttp://www.thymeleaf.org head meta charsetUTF-8/ title th:text${report.title}漏洞扫描报告/title /head body h1 th:text${report.title}漏洞扫描报告/h1 pstrong扫描时间/strongspan th:text${#dates.format(report.scanTime, yyyy-MM-dd HH:mm:ss)}/span/p h2漏洞详情/h2 div th:eachvuln : ${report.vulnerabilities} h3 th:text${vuln.name} ( ${vuln.severity} )Struts2 RCE (CRITICAL)/h3 pstrongID/strongspan th:text${vuln.id}S2-045/span/p pstrong风险描述/strongspan th:text${vuln.description}.../span/p pstrong修复建议/strongspan th:text${vuln.remediation}升级Struts2.../span/p details summary原始请求/响应/summary precode classhttp th:text${vuln.rawRequest}/code/pre precode classhttp th:text${vuln.rawResponse}/code/pre /details /div /body /htmlPDF导出的关键是中文字体嵌入。PdfExporter.java中public void exportToPdf(Report report, String outputPath) throws Exception { PdfWriter writer new PdfWriter(outputPath); PdfDocument pdfDoc new PdfDocument(writer); Document document new Document(pdfDoc); // 注册思源黑体需提前将simsun.ttc放入resources/fonts/ PdfFont font PdfFontFactory.createFont( getClass().getResourceAsStream(/fonts/simsun.ttc), SimSun, true ); document.setFont(font); document.setFontSize(10f); // 渲染标题 document.add(new Paragraph(report.getTitle()).setBold().setFontSize(16f)); document.add(new Paragraph(扫描时间 DateTimeFormatter.ofPattern(yyyy-MM-dd HH:mm:ss).format(report.getScanTime()))); // 遍历漏洞生成PDF段落 for (Vulnerability vuln : report.getVulnerabilities()) { document.add(new Paragraph(vuln.getName() ( vuln.getSeverity() )).setBold()); document.add(new Paragraph(ID: vuln.getId())); document.add(new Paragraph(描述: vuln.getDescription())); document.add(new Paragraph(修复建议: vuln.getRemediation())); // 原始请求/响应用CodeBlock样式 document.add(new Paragraph(原始请求:).setItalic()); document.add(new Paragraph(vuln.getRawRequest()).setFontColor(ColorConstants.GRAY)); } document.close(); }设计说明simsun.ttc字体文件必须放在src/main/resources/fonts/下否则PDF生成时抛IOExceptionPdfFontFactory.createFont(..., true)的true参数表示启用字体子集嵌入避免PDF体积暴增所有中文文本必须通过document.add(new Paragraph(...))添加直接document.add(中文)会乱码。4. 常见问题排查5个毕设答辩高频翻车点及根治方案4.1 现象扫描结果全是CONNECTION_TIMEOUT但浏览器能正常访问目标网站原因Netty客户端未正确设置SO_TIMEOUT或目标服务器启用了SYN Cookie导致三次握手延迟。更常见的是学生把targetUrl写成https://example.com却没在requestTemplate中配置SSLContext。解决在NetworkClientFactory.java的Bootstrap配置中对HTTPS目标强制添加SSL处理器if (url.startsWith(https://)) { SslContext sslCtx SslContextBuilder.forClient() .trustManager(InsecureTrustManagerFactory.INSTANCE) // 仅测试用答辩时需替换为真实CA .build(); ch.pipeline().addFirst(ssl, sslCtx.newHandler(ch.alloc(), host, port)); }提示答辩时若被问“信任所有证书是否安全”回答“这是开发阶段的便捷配置实际部署需集成企业CA证书并在SslContextBuilder中指定trustManager(new File(ca.crt))。”4.2 现象JSON规则文件修改后不生效始终执行旧规则原因RuleLoader.java使用ClassLoader.getResourceAsStream(rules/)加载规则但IDE中修改JSON后未触发资源热更新或打包成JAR后路径变为jar:file:/xxx.jar!/rules/File.listFiles()失效。解决改用ClassPathResource配合ResourcePatternResolverprivate ListRule loadAllRules() { ResourcePatternResolver resolver new PathMatchingResourcePatternResolver(); try { Resource[] resources resolver.getResources(classpath*:rules/**/*.json); ListRule rules new ArrayList(); for (Resource resource : resources) { String json StreamUtils.copyToString(resource.getInputStream(), StandardCharsets.UTF_8); rules.add(objectMapper.readValue(json, Rule.class)); } return rules; } catch (Exception e) { throw new RuntimeException(Failed to load rules, e); } }关键点classpath*:前缀支持JAR内资源扫描**/*.json递归匹配子目录。4.3 现象PDF报告中中文显示为方框HTML报告正常原因iText 7默认字体不支持中文且PdfFontFactory.createFont()未指定字体名称如SimSun或字体文件路径错误。解决三步确认检查src/main/resources/fonts/simsun.ttc是否存在Windows系统可直接用simsun.ttcLinux/macOS需用NotoSansCJKsc-Regular.otfcreateFont()第二个参数必须是字体内部名称用fonttools命令查看ttx -l simsun.ttc在PDF文档中显式设置字体document.setFont(font)不能只在Paragraph中设置。4.4 现象多线程扫描时出现ConcurrentModificationException原因Vulnerability对象被多个线程同时写入rawRequest/rawResponse字段而这些字段是String类型但StringBuilder在append()时未同步。解决将Vulnerability改为不可变对象所有字段final构造时传入完整数据public class Vulnerability { private final String id; private final String name; private final String rawRequest; // 构造时一次性赋值 private final String rawResponse; public Vulnerability(String id, String name, String rawRequest, String rawResponse) { this.id id; this.name name; this.rawRequest rawRequest; this.rawResponse rawResponse; } // 移除所有setter方法 }注意答辩时强调“不可变对象天然线程安全避免锁竞争符合Java并发最佳实践”。4.5 现象扫描http://localhost:8080时抛java.net.ConnectException: Connection refused原因Netty默认使用NioSocketChannel但localhost回环地址在某些Linux发行版上需用EpollSocketChannel。更可能是目标Tomcat未启动或防火墙拦截。解决增加本地调试专用配置// 在application.properties中添加 scan.local-modetrue # ScannerService.java中 if (isLocalMode target.getHost().equals(localhost)) { // 切换为EpollLinux或KQueuemacOS通道 bootstrap.channel(epollAvailable ? EpollSocketChannel.class : NioSocketChannel.class); }血泪经验答辩前务必用netstat -an | grep 8080确认端口监听状态别让基础环境问题毁掉整个演示。5. 毕设答辩验收指南从演示脚本到答辩话术的全流程准备5.1 演示脚本设计3分钟精准呈现系统价值避开所有技术深坑答辩演示不是代码走读而是用最小操作证明系统有效性。我给某高校A同学设计的脚本至今被沿用时间操作屏幕展示设计意图0:00-0:20启动VulnScannerApp.java输入http://demo.testfire.net公开靶场控制台输出[INFO] Starting scan for http://demo.testfire.net...证明系统可运行目标合法0:21-1:10打开rules/web/sql-injection.json修改matchers[0].pattern为mysql.*syntax保存编辑器窗口特写保存动画展示规则可配置性非硬编码1:11-1:50点击“开始扫描”等待15秒后自动生成report/output/vuln-report.html浏览器打开HTML报告高亮显示SQL注入漏洞条目证明检测能力且结果可读1:51-2:30右键报告页→“打印”→选择“另存为PDF”打开生成的PDFPDF缩略图展示中文字体正常、章节清晰验证报告层完整性2:31-3:00切换终端执行java -jar vuln-scanner.jar --target https://example.com --rule-path rules/cve-2023-1234.json命令行输出Found vulnerability: CVE-2023-1234 (MEDIUM)证明CLI模式可用满足部署需求关键技巧所有演示目标必须提前测试——demo.testfire.net是IBM提供的合法靶场example.com确保无漏洞作为负样本修改规则后不重启程序直接点击“重新加载规则”按钮该功能在RuleManager.java中实现体现热更新能力PDF导出环节故意放慢操作让评委看清“字体嵌入”过程这是Java毕设里少有人做到的细节。5.2 答辩话术库针对6类高频问题的标准应答模板老师提问往往围绕“为什么”“怎么保证”“如果...怎么办”提前准备应答能极大提升可信度问题类型典型问题标准应答精简版应答要点技术选型“为什么用Netty不用OkHttp”“OkHttp是HTTP客户端库无法处理TCP层SYN扫描或自定义协议而本系统需同时支持HTTP/HTTPS/DNS/FTP多种协议探测Netty的ChannelPipeline可插拔设计允许我在同一套连接池上叠加不同协议编解码器。”绑定具体功能需求不空谈“高性能”安全性“信任所有SSL证书是否合规”“开发阶段使用InsecureTrustManagerFactory仅为快速验证POC实际部署时已在application-prod.yml中配置了ssl.trust-store: classpath:prod-ca.jks并通过KeyStore.getInstance(JKS)加载企业CA。”区分开发/生产环境给出具体配置路径可扩展性“新增一个漏洞检测要改几处代码”“只需3步1. 在rules/下新建JSON文件如log4j2.json2. 在app.properties中添加rule.includelog4j23. 运行时自动加载无需编译Java代码。”用数字量化工作量强调JSON驱动优势鲁棒性“目标网站返回503时系统如何处理”“在PocExecutor.java的catch块中我们捕获HttpStatusCodeException将其转换为Vulnerability对象severity设为INFOdescription注明‘服务暂时不可用’确保扫描流程不中断。”展示异常处理策略而非回避问题测试验证“怎么证明检测结果准确”“所有POC均在Docker靶场中实测用docker run -d -p 8080:8080 medicean/vulapps:s_struts2_s2-045启动S2-045靶机系统成功检出并返回/opt/tomcat路径与靶机实际路径一致。”给出可复现的验证步骤附Docker命令工程规范“代码有没有单元测试”“每个核心模块均有JUnit 5测试NetworkClientTest验证超时熔断RuleLoaderTest测试JSON解析PdfExporterTest检查中文字体嵌入。测试覆盖率报告在target/site/jacoco/下可查。”指出具体测试类名和报告路径增强可信度5.3 答辩材料清单一份让导师眼前一亮的交付包除了代码一份专业的毕设交付包应包含5类材料缺一不可材料类型文件名必备内容作用系统架构图docs/architecture.pngPlantUML绘制的四层架构图标注各层Java类名如NetworkClientFactory→网络层直观展示设计思想避免文字描述苍白规则样例集rules/examples/包含sql-injection.json、xss-reflected.json、cve-2023-1234.json三个真实漏洞规则每个含description和remediation字段证明规则引擎实用性非玩具数据测试报告docs/test-report.pdfJUnit生成的覆盖率报告含分支覆盖、Docker靶场实测截图、性能压测数据100并发平均耗时用数据说话体现工程严谨性用户手册docs/user-guide.md含快速启动3行命令、规则编写规范JSON Schema、CLI参数说明--threads,--timeout展示产品化思维不止于代码答辩PPTpresentation.pptx严格遵循“问题→方案→实现→验证”逻辑链每页不超过1张图20字要点禁用动画让导师3秒抓住重点避免信息过载提示PPT中“总体架构”页必须放一张手绘风格的分层图可用Excalidraw绘制比Visio自动生成的图更有“人味”导师会觉得你真理解了设计。从那以后我每次带毕设都强制学生在答辩前完成三件事用Docker靶场跑通一个真实CVE检测、生成一份带中文字体的PDF报告、写出user-guide.md里“如何新增规则”的操作步骤。这三件事做完80%的答辩问题都能自然化解——因为它们逼着学生从“写代码”转向“交付解决方案”。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑