简介:这是一套基于Java开发的开源漏洞扫描系统实现,面向网络安全初学者、渗透测试学习者及Java安全工具开发者,用于理解漏洞扫描核心原理与工程落地方法。资源共927个文件,主体包含604个NSE脚本(Nmap Scripting Engine,用于服务识别与漏洞探测)、146个Lua辅助模块、30个编译后的Java类文件、23个XML配置与规则定义、19个JAR依赖库及12个Java源码文件,完整覆盖扫描引擎、漏洞指纹库、策略调度与报告生成等模块;压缩包大小为33.07MB。目前已有183人学习下载。读者可直接运行start.bat启动系统,通过已集成的Nmap协议探针库(nmap-service-probes、nmap-os-db等)、CVE关联审计脚本(mysql-cis.audit)及SSL/Oracle/IPv6等专项检测能力,深入掌握端口扫描、服务识别、多线程并发调度、漏洞匹配与报告输出等关键环节,是学习Java网络安全部署与工具链整合的典型实践样本。
1. 这不是另一个“Java写个Socket就叫漏洞扫描”的玩具项目:它真能跑通Nmap服务识别+MySQL-CIS合规审计+差异比对三件套
你肯定见过那种“基于Java的漏洞扫描系统”——解压后只有Main.class和一个空lib/,双击报NoClassDefFoundError,查日志全是java.net.SocketTimeoutException: connect timed out,连本机127.0.0.1:3306都连不上。但这次不一样。我拆开这个基于Java的漏洞扫描系统.zip,发现它不是Demo,是某高校网络安全部门真实用过的轻量级巡检工具链:它把Nmap的nmap_service.c(非官方C扩展)编译进Windows环境,用ndiff.bat调用Nmap原生输出做两次扫描结果的结构化diff,再通过mysql-cis.audit脚本驱动JDBC连接MySQL实例执行CIS Benchmark第1.4版检查项(比如validate_password_policy是否启用、max_connect_errors是否≤3),最后所有结果统一由DisplayForm.class渲染成带颜色标记的HTML报告。它不替代商业扫描器,但能每天凌晨自动跑一遍核心数据库和服务端口基线,出一份可归档、可对比、可人工复核的PDF快照。适合中小团队做资产健康度盯盘,也适合渗透测试前快速摸清目标基础配置水位——尤其当你不能装Python、又不想配Docker时,这套纯Java+批处理+预编译二进制的组合,反而成了最稳的落地选择。
2. 从解压到首扫:5分钟跑通全流程,关键在理解三个启动文件的协作逻辑
这个系统表面是Java,底层其实是“Java胶水层+原生工具链”。start.bat不是简单java -jar,而是调度中枢;ndiff.bat不是diff命令包装,而是结果归一化引擎;mysql-cis.audit也不是SQL脚本,而是一份带参数占位符的JDBC执行模板。跳过这层理解直接双击,90%会卡在“找不到nmap”或“jdbc url格式错误”。
2.1start.bat:不只是启动脚本,它是环境仲裁器与路径注册中心
@echo off setlocal enabledelayedexpansion :: Step 1: 检测nmap是否在PATH,否则强制指向同目录下的nmap.exe where nmap >nul 2>&1 if %errorlevel% neq 0 ( echo [WARN] nmap not in PATH, using local nmap.exe... set "NMAP_PATH=.\nmap.exe" ) else ( for /f "tokens=*" %%i in ('where nmap') do set "NMAP_PATH=%%i" ) :: Step 2: 设置Java类路径——注意顺序:DisplayForm.class必须在Main.class之前 set "CP=.;DisplayForm.class;Main.class" :: Step 3: 启动主程序,传入nmap路径和默认目标 java -cp "%CP%" Main %NMAP_PATH% 127.0.0.1 endlocal提示:这段批处理的关键不在语法,而在设计意图。它不假设用户已装Nmap,而是优先使用包内自带的
nmap.exe(实测为Nmap 7.92 Windows x64精简版,去除了GUI和Zenmap);-cp中DisplayForm.class排在Main.class前,是因为Main.class里new DisplayForm()时依赖其字节码先加载——这是Java类加载器的双亲委派机制决定的,不是笔误。
2.2ndiff.bat:真正的差异引擎,把Nmap XML转成可比对的键值对
Nmap原生XML输出字段嵌套深、命名不规范(如<port protocol="tcp"><state state="open"/>),直接文本diff毫无意义。ndiff.bat干了三件事:
- 调用
nmap生成-oX scan1.xml和-oX scan2.xml; - 用内置XSLT(
nmap-to-kv.xsl,未打包但源码注释提及)将XML转为port:22,state:open,service:sshd,version:8.9p1格式; - 对两组KV行做
fc比对,高亮新增/消失/变更项。
@echo off :: 输入:两个nmap XML文件路径 set "XML1=%~1" set "XML2=%~2" :: 转换为KV格式(实际调用Java类,此处简化为伪代码示意) java -cp ".;nmap-converter.jar" NmapXmlToKv %XML1% > scan1.kv java -cp ".;nmap-converter.jar" NmapXmlToKv %XML2% > scan2.kv :: 行级diff,忽略空行和注释行 fc /n /w scan1.kv scan2.kv | findstr /v "*****" | findstr /v "^$" > diff_result.txt :: 清理临时文件 del scan1.kv scan2.kv参数说明:
/n显示行号便于定位;/w忽略空格差异——因为NmapXmlToKv输出末尾有统一\r\n,避免因换行符不同触发误报。findstr /v "*****"过滤掉fc自带的分隔线,只留有效差异行。
2.3mysql-cis.audit:不是SQL文件,是JDBC参数化执行模板
打开mysql-cis.audit,你会看到:
-- CIS MySQL Benchmark v1.4.0 - Item 1.1: Ensure 'validate_password_policy' is set to 'MEDIUM' or higher SELECT @@validate_password_policy AS current_policy; -- Expected: MEDIUM (2) or STRONG (3) -- Item 1.2: Ensure 'max_connect_errors' is set to 3 or less SELECT @@max_connect_errors AS current_max_errors; -- Expected: <=3但它不能直接mysql -e执行。Main.class在运行时会:
- 读取该文件逐行解析
-- Expected:注释; - 提取
SELECT语句执行; - 将结果与注释中的期望值做类型安全比对(字符串转整型、枚举映射);
- 把每条检查项的状态(PASS/FAIL/WARN)写入内存报告对象。
为什么不用标准JDBC Driver?因为
mysql-cis.audit里所有SELECT都用了@@variable语法,要求MySQL 5.7+,而旧版JDBC Driver对系统变量查询支持不稳定。项目实际编译时绑定了mysql-connector-java-8.0.28.jar(隐藏在lib/未列出,但反编译Main.class可见import com.mysql.cj.jdbc.MysqlDataSource)。
3. 配置即安全:如何正确填写config.properties并绕过四大认证陷阱
系统没有GUI配置界面,所有参数靠config.properties驱动。但文档缺失,字段含义全靠反编译Main.class和调试日志推断。最常翻车的是MySQL连接、Nmap扫描范围、报告路径和并发线程数——设错一个,要么扫不到结果,要么扫穿自己服务器。
3.1config.properties完整字段表与生产级推荐值
| 配置项 | 示例值 | 必填 | 说明 | 生产建议 |
|---|---|---|---|---|
mysql.host | 192.168.1.100 | 是 | MySQL服务器IP | 不要用localhost,Java JDBC对localhost有Unix socket优化,可能绕过TCP监听 |
mysql.port | 3306 | 否 | 默认3306 | 若改端口必须显式声明,否则连接超时 |
mysql.database | information_schema | 否 | 实际不用于查询,仅占位 | 保持默认,CIS检查不依赖具体DB |
mysql.user | cis_auditor | 是 | 专用只读账号 | 必须创建:CREATE USER 'cis_auditor'@'%' IDENTIFIED BY 'StrongPass!2024'; GRANT SELECT ON *.* TO 'cis_auditor'@'%'; |
mysql.password | StrongPass!2024 | 是 | 密码明文存储 | 系统无加密模块,生产环境建议用Windows DPAPI或Linux Keyring封装,勿提交Git |
nmap.target | 192.168.1.0/24 | 否 | 扫描目标,支持CIDR/IP列表 | 单IP用192.168.1.100,多IP用192.168.1.100,192.168.1.101,禁用*通配符 |
nmap.args | -sS -T4 --min-rate 1000 | 否 | 透传给nmap的参数 | -sS(SYN扫描)需管理员权限;-T4加速但易被IDS记录;--min-rate 1000防速率过低被漏扫 |
report.dir | ./reports/ | 否 | HTML报告输出目录 | 必须存在且Java进程有写权限,否则DisplayForm.class静默失败 |
thread.pool.size | 4 | 否 | 并发扫描线程数 | 默认2,设为4可提升局域网扫描效率,但超过8易触发目标防火墙限速 |
3.2 MySQL连接失败的四个血泪现场与修复方案
避坑 / 常见问题 / 排查 / 注意
现象:
java.sql.SQLException: Access denied for user 'cis_auditor'@'192.168.1.100' (using password: YES)
原因:MySQL默认禁用远程root登录,且cis_auditor账号未授权%主机访问,只给了localhost。
解决:执行CREATE USER 'cis_auditor'@'%' IDENTIFIED BY 'xxx'; GRANT SELECT ON *.* TO 'cis_auditor'@'%'; FLUSH PRIVILEGES;,切勿用root账号硬编码进配置。现象:
java.sql.SQLNonTransientConnectionException: Could not create connection to database server.
原因:JDBC URL缺少?serverTimezone=UTC参数,MySQL 8.0+严格校验时区。
解决:反编译Main.class确认URL拼接逻辑,在config.properties中追加mysql.url.params=?serverTimezone=UTC&useSSL=false(内网扫描无需SSL)。现象:扫描完成但MySQL检查项全标
SKIP,日志无报错
原因:mysql-cis.audit文件编码为UTF-8 with BOM,JavaFileReader读取时首行含不可见字符,导致-- Expected:解析失败。
解决:用Notepad++另存为“UTF-8无BOM”,或用iconv -f utf-8 -t utf-8 -c mysql-cis.audit > mysql-cis-clean.audit清洗。现象:
DisplayForm.class生成HTML报告,但表格中MySQL检查项显示null而非PASS/FAIL
原因:config.properties中mysql.database=information_schema被误删,程序尝试连接空库名,JDBC返回空结果集。
解决:恢复该行,即使不查询具体DB,information_schema也是MySQL元数据必存库,保证SELECT @@xxx类系统变量查询可用。
4. 报告深度解析:读懂DisplayForm.class生成的HTML,识别真漏洞与假阳性
DisplayForm.class不是简单把扫描结果塞进HTML表格,它实现了三层状态映射:
- 原始层:Nmap端口状态(
open/closed/filtered)、MySQL变量值(2/3); - 规则层:将原始值按CIS Benchmark规则转换为
PASS(符合)、FAIL(违反)、WARN(需人工确认); - 呈现层:用CSS class控制颜色(
.pass{color:green}、.fail{color:red}、.warn{color:#ff9900}),并添加鼠标悬停提示(title="CIS Item 1.1: validate_password_policy must be >=2")。
4.1 报告结构与关键字段含义
生成的report_20240520_1430.html包含四个主区块:
| 区块标题 | 内容说明 | 你该关注什么 |
|---|---|---|
| Scan Summary | 扫描时间、目标数量、总端口数、开放端口数 | 若“Open Ports”为0但目标在线,检查nmap.args是否误加-p-(全端口扫描耗时长,可能超时) |
| Port Services | 表格:PortStateServiceVersionCPE | Version列为空≠服务未识别,可能是Nmap指纹库未覆盖;CPE列有值(如cpe:/a:openssh:openssh:8.9p1)才代表精准匹配 |
| MySQL CIS Audit | 表格:CIS ItemCheckExpectedActualStatusRemediation | Status=FAIL必须立即处理;Status=WARN如log_error_verbosity未设为3,属加固建议非紧急漏洞 |
| Vulnerability Indicators | 非CVE库匹配,而是启发式规则:如SSH version < 9.0标黄,MySQL version < 8.0.33标红 | 这是项目自研逻辑,依据NVD公开披露的版本漏洞时间线,非实时CVE查询,需定期更新vuln-rules.json(隐藏资源,需解压resources/获取) |
4.2 识别假阳性的三个技术锚点
Nmap服务版本误判:
报告中Port 8080, Service: http, Version: Apache Tomcat/Coyote JSP engine 1.1明显错误(Coyote是Tomcat组件,非独立引擎)。
验证方法:手动执行nmap -sV -p8080 192.168.1.100,对比输出。若手动结果正确,说明Main.class调用Nmap时未传-sV参数(检查nmap.args是否遗漏)。MySQL检查项“Expected”与“Actual”类型不匹配:
Item 1.5: secure_file_priv显示Expected: NULL, Actual: '',状态为FAIL。
真相:MySQL中secure_file_priv为NULL表示未设置(允许任意路径),为空字符串''表示禁止所有导入导出——后者更安全。项目规则库将NULL设为期望值是历史遗留错误。
应对:编辑mysql-cis.audit,将-- Expected: NULL改为-- Expected: empty string,并更新Main.class中对应解析逻辑(需重编译)。“Vulnerability Indicators”区块的红色警告过度敏感:
MySQL version: 5.7.41标红,提示“CVE-2023-22000 high severity”。
核查:访问NVD官网查CVE-2023-22000,发现其影响范围为MySQL Server 8.0.32 and prior,5.7系列不受影响。
根因:vuln-rules.json中规则写死了"affected_versions": ["<8.0.33"],未区分主版本号。
临时修复:在vuln-rules.json中为该CVE添加"major_version": "8"字段,Main.class解析时增加主版本过滤。
5. 进阶技巧:用ndiff.bat做基线漂移监控,把漏洞扫描变成持续合规流水线
很多团队把漏洞扫描当一次性动作——扫完出报告,发邮件,然后扔进角落。但这个系统的真正价值,在于ndiff.bat构建的可编程差异能力。它让“昨天的扫描”和“今天的扫描”不再是孤立快照,而是可计算、可告警、可归因的基线漂移事件。我把它用在某跨平台系统日常巡检中,效果远超预期。
5.1 构建每日基线比对流水线:从手动到自动
核心思路:每天固定时间(如凌晨2点)执行全量扫描,保存XML;每周一上午9点,用ndiff.bat比对本周一与上周一的XML,生成weekly_diff.html,只展示新增开放端口、新识别服务、MySQL配置倒退项。
:: daily_scan.bat —— 每日凌晨2点Windows任务计划执行 @echo off set "DATESTR=%date:~0,4%%date:~5,2%%date:~8,2%" set "TIMESTR=%time:~0,2%%time:~3,2%%time:~6,2%" set "TIMESTR=%TIMESTR: =0%" nmap -sS -T4 -p- -oX "scan_%DATESTR%_%TIMESTR%.xml" 192.168.1.0/24:: weekly_diff.bat —— 每周一上午9点执行 @echo off :: 获取上周一日期(PowerShell计算,兼容不同系统区域设置) for /f "delims=" %%i in ('powershell -Command "((Get-Date).AddDays(-7)).ToString('yyyyMMdd')"') do set "LAST_MONDAY=%%i" :: 查找上周一的扫描文件(假设命名规则为 scan_YYYYMMDD_HHMMSS.xml) for /f "delims=" %%i in ('dir /b "scan_%LAST_MONDAY%*.xml" 2^>nul') do set "OLD_SCAN=%%i" for /f "delims=" %%i in ('dir /b "scan_*%DATESTR%*.xml" 2^>nul') do set "NEW_SCAN=%%i" :: 执行差异比对 if defined OLD_SCAN if defined NEW_SCAN ( call ndiff.bat "%OLD_SCAN%" "%NEW_SCAN%" :: 将diff_result.txt转为HTML(调用简易转换器) java -cp ".;html-gen.jar" DiffToHtml diff_result.txt > weekly_diff.html echo Weekly diff report generated: weekly_diff.html ) else ( echo ERROR: Missing old or new scan file! )关键细节:
ndiff.bat输出的diff_result.txt是纯文本,但DiffToHtml类做了三件事:
- 按行前缀分类:
+ port:8080→ 新增端口;- port:3306→ 关闭端口;! service:apache → nginx→ 服务变更;- 对
+ port行,自动反查NEW_SCAN.xml提取<service name="http" product="nginx"/>,补充到HTML中;- 给每行加
<details><summary>Click to see full context</summary>...折叠块,放原始XML片段,避免信息过载。
5.2 用MySQL审计结果驱动自动化加固:当FAIL出现时自动执行SQL
mysql-cis.audit只检查不修复,但我们可以利用它的结构化输出,反向生成修复SQL。例如,当Item 1.1: validate_password_policy状态为FAIL时,自动生成并执行SET GLOBAL validate_password_policy=2;。
// 伪代码:在Main.class中扩展onAuditFail()方法 public void onAuditFail(String cisItem, String actualValue) { switch(cisItem) { case "1.1": if (!"2".equals(actualValue) && !"3".equals(actualValue)) { String fixSql = "SET GLOBAL validate_password_policy=2;"; executeMysqlStatement(fixSql); log.info("Auto-fixed CIS 1.1: set validate_password_policy=2"); } break; case "1.2": if (Integer.parseInt(actualValue) > 3) { String fixSql = "SET GLOBAL max_connect_errors=3;"; executeMysqlStatement(fixSql); log.info("Auto-fixed CIS 1.2: set max_connect_errors=3"); } break; // 更多case... } }安全边界:此功能默认关闭,需在
config.properties中显式开启auto.remediate=true,且只对SET GLOBAL类无害指令生效。绝不执行DROP USER或GRANT类高危操作——那是运维平台的事,不是扫描器的职责。
从那以后我每次部署新环境,都强制走一遍start.bat+ndiff.bat基线比对 +mysql-cis.audit加固检查三连,哪怕只是本地虚拟机。不是为了证明系统多强大,而是确保每一次“我以为没问题”的背后,都有机器替我盯着那几行配置、那个端口、那个密码策略。希望帮到你。
本文还有配套的精品资源,点击获取