Ayeesha02/Network-Vulnerability-Scanner

GitHub: Ayeesha02/Network-Vulnerability-Scanner

一款零依赖的 Python 网络漏洞扫描 CLI,自动化完成主机发现、端口扫描、服务指纹识别与 CVE 匹配并输出结构化报告,专为授权渗透测试而构建。

Stars: 0 | Forks: 1

# 网络漏洞扫描器 (NVS) ## 目录 1. [概述](#overview) 2. [架构](#architecture) 3. [项目结构](#project-structure) 4. [扫描流水线](#scan-pipeline) 5. [安装说明](#installation) 6. [快速开始](#quick-start) 7. [CLI 参考](#cli-reference) 8. [模块文档](#module-documentation) 9. [CVE 特征数据库](#cve-pattern-database) 10. [报告格式](#report-format) 11. [运行测试套件](#running-the-test-suite) 12. [扩展 NVS](#extending-nvs) 13. [性能调优](#performance-tuning) 14. [限制与已知问题](#limitations--known-issues) 15. [贡献指南](#contributing) 16. [许可证](#license) ## 概述 NVS 是一个零依赖的 Python CLI,它自动化了网络渗透测试的前四个阶段 ——主机发现 (ICMP + TCP-ping), 端口枚举 (TCP connect + UDP),服务指纹识别(针对 15+ 协议的 banner 解析),以及 CVE 分诊(针对精选的 40 条漏洞数据库 进行特征匹配)——并导出带有 CVSS 加权风险评分和优先修复措施的 结构化 JSON 报告。 专为需要快速、可审计、适合物理隔离网络(air-gap)替代方案 来替代组合使用 nmap + grep + 电子表格的安全工程师而构建。 ⚠️ 仅限用于授权的渗透测试。在大多数司法管辖区,未经 明确书面许可扫描系统是非法的。 ``` Targets → Live hosts → Open ports → Service versions → CVE matches → JSON report ``` | 功能 | 实现方式 | 权限要求 | |---|---|---| | 主机发现 | ICMP Echo Request (原始套接字) | root / CAP_NET_RAW | | 主机发现 (备用) | TCP 连接常用端口 | 无 | | 端口枚举 | TCP 三次握手 | 无 | | UDP 端口扫描 | 特定协议探测 | 无 | | Banner 抓取 | recv() / TLS 封装 | 无 | | 服务指纹识别 | 每种协议的正则解析器 | 无 | | 操作系统检测 | python-nmap (-O) | root (针对 Nmap) | | CVE 特征匹配 | 本地 JSON 数据库 | 无 | | 报告生成 | 结构化 JSON | 无 | **核心设计原则:** - **零强制第三方依赖** — 核心流水线运行于 Python 标准库上;`python-nmap` 和 `rich` 是可选的附加组件。 - **线程池并发** — 主机发现和端口扫描均使用 `ThreadPoolExecutor`;每次扫描均可调整池大小。 - **优雅降级** — 无权限时,原始套接字 ICMP 会回退到 TCP-ping;缺少二进制文件时会静默跳过 Nmap 阶段。 - **结构化输出** — 每次扫描都会生成适合导入漏洞管理平台的机器可读 JSON。 ## 架构 ``` ┌─────────────────────────────────────────────────────────────────┐ │ CLI (cli.py) │ │ argparse → target resolution → pipeline orchestration │ └────────────────┬────────────────────────────────────────────────┘ │ ┌─────────▼─────────┐ │ Phase 1 │ host_discovery.py │ Host Discovery │ ICMP ping sweep (raw socket) │ │ TCP-ping fallback (no root needed) └─────────┬──────────┘ │ live_hosts[] ┌─────────▼──────────┐ │ Phase 2a │ port_scanner.py │ Port Enumeration │ TCP connect scan (multi-threaded) │ │ Optional UDP probes └─────────┬──────────┘ │ open_ports[] ┌─────────▼──────────┐ │ Phase 2b │ service_detector.py │ Service Detection │ Banner parsing per protocol │ │ TLS handshake + cert extraction └─────────┬──────────┘ │ (optional) ┌─────────▼──────────┐ │ Phase 3 │ nmap_scanner.py │ Nmap Enrichment │ OS fingerprinting (-O) │ (optional) │ Service version detection (-sV) │ │ NSE script execution └─────────┬──────────┘ │ ┌─────────▼──────────┐ │ Phase 4 │ cve_mapper.py │ CVE Mapping │ Port / service / banner / version │ │ cross-referenced against JSON DB └─────────┬──────────┘ │ ┌─────────▼──────────┐ │ Output │ report_generator.py │ JSON Report │ Executive summary + risk score │ │ Per-host findings + remediation └────────────────────┘ Shared utilities: utils.py IP/CIDR validation · hostname resolution · port-range parsing ANSI colours · progress bar · timestamps ``` ## 项目结构 ``` nvs/ │ ├── scanner/ # Main Python package │ ├── __init__.py # Public API re-exports │ ├── cli.py # CLI entry point (argparse + orchestration) │ ├── utils.py # Shared helpers (IPs, ports, colours, progress) │ ├── host_discovery.py # Phase 1: ICMP + TCP-ping host sweep │ ├── port_scanner.py # Phase 2a: TCP connect + UDP scanning │ ├── service_detector.py # Phase 2b: Banner parsing & fingerprinting │ ├── nmap_scanner.py # Phase 3: python-nmap wrapper (optional) │ ├── cve_mapper.py # Phase 4: CVE pattern matching engine │ └── report_generator.py # JSON report builder │ ├── data/ │ └── cve_patterns.json # Bundled CVE database (40 patterns, v1.0.0) │ ├── tests/ │ ├── __init__.py │ ├── test_host_discovery.py # ICMP checksum, packet structure, sweep logic │ ├── test_port_scanner.py # PortResult, TCP scan, UDP scan, port parsing │ └── test_cve_mapper.py # CVE loading, matching, filtering, report gen │ ├── reports/ # Runtime output directory (git-ignored) │ └── .gitkeep │ ├── requirements.txt # Optional dependencies ├── setup.py # Package installer & entry-point definition ├── .gitignore └── README.md ``` ## 扫描流水线 ### 阶段 1 — 主机发现 (`host_discovery.py`) **目标:** 在花费时间对死主机进行端口扫描之前,识别目标范围内哪些 IP 可达。 **ICMP 扫描(首选,需要 root)** 1. 创建原始 `AF_INET / SOCK_RAW / IPPROTO_ICMP` 套接字。 2. 构建 ICMP type-8 (Echo Request) 数据包,包含: - Type=8, Code=0 - Identifier = `os.getpid() & 0xFFFF` - Sequence = 1 - Payload = 时间戳字节 - Checksum = 基于 header + payload 的 RFC 1071 Internet 校验和 3. 捕获回复(type-0 Echo Reply);计算 RTT。 **TCP-Ping 备用方案(无 root)** 当抛出 `PermissionError`(无 `CAP_NET_RAW`)时,会尝试 TCP 连接一系列常用端口(80, 443, 22, 445…)。任何成功的 `connect_ex() == 0` 都意味着主机存活。 **并发:** `ThreadPoolExecutor(max_workers=discovery_threads)` — 默认 50 个工作线程,可通过 `--discovery-threads` 调整。 ### 阶段 2a — 端口枚举 (`port_scanner.py`) **TCP Connect 扫描** 对于每个端口,调用 `socket.connect_ex((target, port))` 并设置 `settimeout(timeout)`。返回码: | 返回码 | 状态 | |---|---| | `0` | **open** | | `ECONNREFUSED` (111) | **closed** | | 超时 / 其他 | **filtered** | 默认仅返回 `open` 端口(verbose 模式包含所有状态)。 **Banner 抓取**(可选,使用 `--no-banners` 禁用) 成功连接后: 1. **被动 recv:** 针对立即发送数据的协议(SSH, FTP, SMTP, POP3, IMAP)。 2. **HTTP GET 探测:** 针对 HTTP/HTTPS 端口,发送最简的 `GET / HTTP/1.0` 请求。 3. **TLS 封装:** 针对 TLS 端口(443, 8443, 993…),第二次连接会使用 `ssl.create_default_context()` 封装套接字(对自签名证书禁用验证)。 **UDP 扫描** (`--udp`) 向众所周知的 UDP 端口发送特定协议的探测。状态推断: | 结果 | 状态 | |---|---| | 收到响应 | **open** | | `ConnectionRefusedError` (ICMP port-unreachable) | **closed** | | 超时 | **open\|filtered** | **并发:** `ThreadPoolExecutor(max_workers=threads)` — 默认 100 个工作线程,可通过 `--threads` 调整。 ### 阶段 2b — 服务检测 (`service_detector.py`) 基于端口的正则解析器从原始 banner 中提取结构化元数据: | 服务 | 解析器 | 提取字段 | |---|---|---| | SSH | `_parse_ssh()` | 产品,版本,OS 提示 | | FTP | `_parse_ftp()` | 产品,版本 | | SMTP | `_parse_smtp()` | 产品,版本 | | HTTP | `_parse_http()` | 产品,版本,框架提示 | | POP3 | `_parse_pop3()` | 版本字符串 | | IMAP | `_parse_imap()` | 版本字符串 | | MySQL | `_parse_mysql()` | 版本 (来自 Protocol v10 数据包) | | Redis | `_parse_redis()` | 版本字符串 | | RDP | `_parse_rdp()` | 静态标识 | 对于 TLS 端口,`ssl.SSLSocket.cipher()` 和 `getpeercert()` 提取: - 协商的 TLS 版本 (TLSv1.2, TLSv1.3) - Cipher suite 名称 - 证书 Common Name 和 SAN 列表 - 证书过期日期 ### 阶段 3 — Nmap 增强 (`nmap_scanner.py`) *(可选)* 使用 `--nmap` 激活。需要同时满足: - `$PATH` 中存在 `nmap` 二进制文件 - `pip install python-nmap` **默认参数:** `-sV -O --version-intensity 5` NVS 仅将**已发现的开放端口**传递给 Nmap,使得运行速度明显快于完整的 Nmap 扫描。 **合并策略:** 将 Nmap 数据叠加到现有的主机字典中: - 仅当当前的 `product` 和 `version` 为空或“unknown”时,才进行回填。 - `os_guess` 和 `os_accuracy` 在主机级别设置。 - NSE 脚本输出存储在每个端口的 `extra.nmap_scripts` 字典中。 **NSE 脚本** (`--nmap-scripts "default,vuln"`):执行 Nmap 内置的漏洞检测脚本。`vuln` 类别具有侵入性——仅在授权目标上使用。 ### 阶段 4 — CVE 特征匹配 (`cve_mapper.py`) 使用四个匹配维度(跨维度采用 OR 逻辑),针对 `data/cve_patterns.json` 中的每个特征测试每个开放端口: | 维度 | 条件 | |---|---| | **端口匹配** | 目标端口 ∈ `affected_ports` 且协议匹配 | | **服务关键词** | `service_keywords[i]` 是检测到的服务名称的子字符串 | | **Banner 模式** | `banner_patterns[i]` 是原始 banner(转换为小写后)的子字符串 | | **版本范围** | 检测到的版本 ∈ [`version_min`, `version_max`](语义化版本比较) | 结果按严重性排序:`CRITICAL → HIGH → MEDIUM → LOW → INFO`。 CVSS 严重性阈值(v3 标准): | CVSS 分数 | 严重性 | |---|---| | 9.0 – 10.0 | **CRITICAL** | | 7.0 – 8.9 | **HIGH** | | 4.0 – 6.9 | **MEDIUM** | | 0.1 – 3.9 | **LOW** | | 0.0 | **INFO** | 使用 `--min-cvss 7.0` 可以在初始分诊期间过滤杂音。 ## 安装说明 ### 前置条件 | 要求 | 版本 | 用途 | |---|---|---| | Python | ≥ 3.8 | 运行环境 | | pip | 任意 | 包管理 | | nmap binary | ≥ 7.0 | 阶段 3 (可选) | | Root / sudo | — | ICMP ping, Nmap -O | ### 从源码安装 ``` # Clone 仓库 git clone https://github.com/example/network-vuln-scanner.git cd network-vuln-scanner # 创建并激活虚拟环境(推荐) python3 -m venv .venv source .venv/bin/activate # Linux / macOS # .venv\Scripts\activate.bat # Windows # 安装软件包(仅核心 — 无第三方依赖) pip install -e . # 可选:Nmap 集成 pip install -e ".[nmap]" # 可选:完整开发安装 pip install -e ".[all]" ``` ### 验证安装 ``` nvs --help python -m pytest tests/ -v ``` ## 快速开始 ``` # 扫描单个主机(前 100 个端口,无需 root) nvs -t 192.168.1.10 # 扫描 /24 子网并保存 JSON 报告 sudo nvs -t 192.168.1.0/24 -p top-100 -r reports/scan.json # 完整 TCP 端口范围 + UDP + Nmap OS 检测 sudo nvs -t 10.0.0.5 -p 1-65535 --udp --nmap -r full_scan.json # 从文件读取目标,筛选 CVSS >= 7.0 的发现 nvs -f targets.txt -p 22,80,443,3389,8080 --min-cvss 7.0 -r report.json # 跳过主机发现(假定所有目标都活跃) nvs -t 10.0.0.100 -p top-100 --skip-discovery -v # 使用自定义 CVE 数据库 + 运行 Nmap NSE 脚本 sudo nvs -t 10.0.0.1 -p top-100 --nmap --nmap-scripts "default,vuln" \ --cve-db /opt/my_cve_db.json -r vuln_report.json ``` ## CLI 参考 ``` usage: nvs [-h] (-t TARGET | -f FILE) [-p PORTS] [--udp] [--skip-discovery] [--timeout S] [--threads N] [--discovery-threads N] [--no-banners] [--nmap] [--nmap-args ARGS] [--nmap-scripts SCRIPTS] [--no-cve] [--cve-db PATH] [--min-cvss SCORE] [-r FILE] [--no-color] [-v] [-q] ``` ### 目标指定 | 参数 | 描述 | |---|---| | `-t`, `--target TARGET` | 单个 IP、CIDR 块 (`192.168.1.0/24`) 或主机名 | | `-f`, `--target-file FILE` | 包含 IP / CIDR / 主机名的换行符分隔文件(允许 `#` 注释) | ### 端口指定 | 参数 | 默认值 | 描述 | |---|---|---| | `-p`, `--ports PORTS` | `top-100` | `top-100` \| `22,80,443` \| `1-1024` \| 混合 | | `--udp` | off | 在 TCP 之外探测常用 UDP 端口 | | `--skip-discovery` | off | 将所有目标视为存活;跳过阶段 1 | ### 扫描调优 | 参数 | 默认值 | 描述 | |---|---|---| | `--timeout S` | `1.0` | 每个端口的连接超时时间(秒) | | `--threads N` | `100` | TCP 扫描线程池大小 | | `--discovery-threads N` | `50` | 主机发现线程池大小 | | `--no-banners` | off | 跳过 banner 抓取(速度更快;服务信息更少) | ### Nmap 集成 | 参数 | 默认值 | 描述 | |---|---|---| | `--nmap` | off | 启用阶段 3 Nmap 增强 | | `--nmap-args ARGS` | `-sV -O --version-intensity 5` | 原始 Nmap 参数字符串 | | `--nmap-scripts SCRIPTS` | — | NSE 脚本(例如 `default,vuln`)。隐含 `--nmap`。 | ### CVE 映射 | 参数 | 默认值 | 描述 | |---|---|---| | `--no-cve` | off | 跳过阶段 4 CVE 特征匹配 | | `--cve-db PATH` | `data/cve_patterns.json` | 自定义 CVE 特征 JSON 文件 | | `--min-cvss SCORE` | `0.0` | 报告的最小 CVSS 分数(0.0 = 全部) | ### 输出 | 参数 | 默认值 | 描述 | |---|---|---| | `-r`, `--report FILE` | — | 将 JSON 报告写入 FILE | | `--no-color` | off | 禁用 ANSI 颜色代码 | | `-v`, `--verbose` | off | 显示 closed / filtered 端口 | | `-q`, `--quiet` | off | 隐藏进度;仅输出发现结果 | ## 模块文档 ### `scanner.utils` 整个流水线中使用的共享辅助工具。 ``` from scanner.utils import ( validate_ip, # bool: is string a valid IPv4/v6? validate_cidr, # bool: is string valid CIDR notation? expand_cidr, # List[str]: CIDR → individual host IPs resolve_hostname, # Optional[str]: forward DNS lookup reverse_dns, # Optional[str]: PTR record lookup parse_port_range, # List[int]: "22,80-90,top-100" → sorted int list is_root, # bool: running as root / Administrator? format_duration, # str: 3661.0 → "1h 1m 1s" get_timestamp, # str: ISO-8601 current timestamp Colors, # ANSI colour namespace; Colors.disable() for plain ProgressBar, # In-place terminal progress bar ) ``` ### `scanner.host_discovery` ### `scanner.port_scanner` ``` from scanner.port_scanner import PortScanner, UDPScanner # TCP connect 扫描 scanner = PortScanner(timeout=1.0, max_workers=100, grab_banners=True) results = scanner.scan("10.0.0.1", ports=[22, 80, 443, 8080]) for r in results: # only open ports returned print(r.port, r.service, r.banner, r.rtt_ms) print(r.to_dict()) # serialisable dict # UDP 扫描 udp = UDPScanner(timeout=2.0, retries=2) res = udp.scan_port("10.0.0.1", 53) print(res.state) # "open" | "closed" | "open|filtered" ``` ### `scanner.service_detector` ``` from scanner.service_detector import ServiceDetector det = ServiceDetector() meta = det.detect(port=22, banner="SSH-2.0-OpenSSH_8.9p1 Ubuntu", tls=False) # → {"service": "ssh", "product": "OpenSSH", "version": "8.9p1", # "os_hint": "Ubuntu", "version_string": "SSH-2.0-OpenSSH_8.9p1 Ubuntu"} meta = det.detect(port=443, banner="HTTP/1.1 200 OK\r\nServer: nginx/1.22.1", tls=True, target="10.0.0.1") # → {"service": "https", "product": "nginx", "version": "1.22.1", # "tls_info": {"tls_version": "TLSv1.3", "cipher_name": "...", ...}} ``` ### `scanner.nmap_scanner` ``` from scanner.nmap_scanner import NmapScanner nmap = NmapScanner() if nmap.is_available(): raw = nmap.scan("10.0.0.1", ports=[22, 80, 443]) host = nmap.merge_results(existing_host_dict, raw) # NSE script scanning raw = nmap.scan_with_scripts("10.0.0.1", [80], scripts="http-headers,http-title") ``` ### `scanner.cve_mapper` ``` from scanner.cve_mapper import CVEMapper mapper = CVEMapper(min_cvss=7.0) # bundled DB mapper = CVEMapper(cve_db_path="/path/custom.json") # custom DB vulns = mapper.map_host(host_dict) # → [{"cve_id": "CVE-...", "severity": "CRITICAL", "cvss_score": 9.8, # "affected_port": 445, "remediation": "...", ...}] # Batch all_vulns = mapper.map_multiple_hosts(hosts) # Dict[ip, List[vuln]] # DB 统计信息 print(mapper.stats()) # → {"total_patterns": 40, "by_severity": {"CRITICAL": 22, "HIGH": 8, ...}} ``` ### `scanner.report_generator` ``` from scanner.report_generator import ReportGenerator import json gen = ReportGenerator() report = gen.generate(hosts=enriched_hosts, scan_info=meta) json.dump(report, open("report.json", "w"), indent=2) ``` ## CVE 特征数据库 内置数据库 (`data/cve_patterns.json`) 提供了 **40 个特征**,涵盖严重的面向网络的漏洞和常见的错误配置。 ### 包含的特征 | CVE ID | 名称 | 严重性 | 主要端口 | |---|---|---|---| | CVE-2017-0144 | EternalBlue (SMBv1 RCE) | CRITICAL | 445, 139 | | CVE-2020-0796 | SMBGhost (SMBv3 RCE) | CRITICAL | 445 | | CVE-2019-0708 | BlueKeep (RDP RCE) | CRITICAL | 3389 | | CVE-2021-44228 | Log4Shell | CRITICAL | 80, 443, 8080 | | CVE-2014-0160 | Heartbleed | HIGH | 443, 993, 995 | | CVE-2014-6271 | Shellshock | CRITICAL | 80, 443 | | CVE-2021-26855 | ProxyLogon (Exchange) | CRITICAL | 443 | | CVE-2022-26134 | Confluence OGNL Injection | CRITICAL | 8090 | | CVE-2022-22965 | Spring4Shell | CRITICAL | 80, 8080 | | CVE-2021-41773 | Apache 2.4.49 Path Traversal | CRITICAL | 80 | | CVE-2017-5638 | Apache Struts Multipart RCE | CRITICAL | 80, 8080 | | CVE-2019-11510 | Pulse Secure VPN File Read | CRITICAL | 443 | | CVE-2020-5902 | F5 BIG-IP TMUI RCE | CRITICAL | 443 | | CVE-2020-1472 | ZeroLogon | CRITICAL | 135, 445 | | CVE-2021-34527 | PrintNightmare | CRITICAL | 445 | | CVE-2018-13379 | Fortinet FortiOS LFI | CRITICAL | 443 | | CVE-2023-20198 | Cisco IOS XE Web UI LPE | CRITICAL | 80, 443 | | CVE-2023-46747 | F5 BIG-IP Auth Bypass | CRITICAL | 443 | | CVE-2023-35078 | Ivanti EPMM Auth Bypass | CRITICAL | 443 | | CVE-2021-3156 | Baron Samedit (sudo) | HIGH | 22 | | CVE-2016-6662 | MySQL RCE via config | CRITICAL | 3306 | | CVE-2022-0778 | OpenSSL Infinite Loop DoS | HIGH | 443 | | CVE-2015-3306 | ProFTPD mod_copy RCE | CRITICAL | 21 | | CVE-2019-19781 | Citrix ADC Path Traversal | CRITICAL | 443 | | CVE-2023-44487 | HTTP/2 Rapid Reset DDoS | HIGH | 443, 80 | | CVE-2018-11776 | Apache Struts Namespace RCE | HIGH | 80, 8080 | | CVE-2012-1823 | PHP-CGI Argument Injection | HIGH | 80 | | CVE-2022-30190 | Follina (MSDT) | HIGH | 80, 445 | | CVE-2023-23397 | Outlook NTLM Theft | CRITICAL | 445, 25 | | CVE-2009-3960 | Redis No-Auth Exposed | CRITICAL | 6379 | | CVE-2017-8291 | Ghostscript Sandbox Escape | HIGH | 80 | | CVE-2015-1635 | IIS HTTP.sys RCE (MS15-034) | CRITICAL | 80 | | CVE-2022-47966 | ManageEngine SAML RCE | CRITICAL | 443, 8443 | | CVE-2021-20016 | SonicWall SSL-VPN SQLi | CRITICAL | 443 | | CVE-2023-4911 | Looney Tunables (glibc) | HIGH | 22 | | CVE-2022-21907 | IIS HTTP Trailer RCE | CRITICAL | 80, 443 | | CVE-2021-26084 | Confluence Widget OGNL | CRITICAL | 8090 | | MISCONFIG-001 | MongoDB No-Auth | CRITICAL | 27017 | | MISCONFIG-002 | Elasticsearch No-Auth | HIGH | 9200 | | MISCONFIG-003 | VNC No-Auth | CRITICAL | 5900 | | MISCONFIG-004 | Telnet Cleartext | HIGH | 23 | | MISCONFIG-005 | Anonymous FTP | MEDIUM | 21 | | MISCONFIG-006 | SNMP Default Community | MEDIUM | 161/udp | ### 特征结构 ``` { "cve_id": "CVE-2017-0144", "name": "EternalBlue – SMBv1 RCE", "description": "Full technical description …", "affected_ports": [445, 139], // TCP/UDP port numbers "affected_protocols": ["tcp"], // "tcp" | "udp" "service_keywords": ["microsoft-ds"], // substrings of service name "banner_patterns": ["windows"], // substrings searched in banner "version_min": null, // inclusive lower bound (or null) "version_max": null, // inclusive upper bound (or null) "cvss_score": 9.3, "cvss_vector": "AV:N/AC:M/Au:N/C:C/I:C/A:C", "severity": "CRITICAL", "exploitable_remotely": true, "authentication_required": false, "affected_systems": ["Windows XP", "Windows 7"], "remediation": "Disable SMBv1; apply MS17-010.", "references": ["https://nvd.nist.gov/vuln/detail/CVE-2017-0144"], "tags": ["rce", "worm", "ms17-010"] } ``` ### 添加自定义特征 ``` // my_patterns.json { "metadata": { "schema_version": "1.0.0" }, "cve_patterns": [ { "cve_id": "CVE-2024-XXXXX", "name": "My Custom Finding", "description": "...", "affected_ports": [8888], "affected_protocols": ["tcp"], "service_keywords": ["custom-app"], "banner_patterns": ["vulnerable-version"], "version_min": "1.0.0", "version_max": "1.4.9", "cvss_score": 8.8, "severity": "HIGH", "exploitable_remotely": true, "authentication_required": false, "affected_systems": ["CustomApp <= 1.4.9"], "remediation": "Upgrade to 1.5.0.", "references": ["https://vendor.com/advisory"], "tags": ["rce"] } ] } ``` ``` nvs -t 10.0.0.1 -p top-100 --cve-db my_patterns.json ``` ## 报告格式 JSON 报告结构: ``` { "report_id": "550e8400-e29b-41d4-a716-446655440000", "generated_at": "2024-11-01T14:30:00", "scanner_version": "1.0.0", "scan_metadata": { "targets": ["192.168.1.0/24"], "ports_scanned": [22, 80, 443, ...], "port_count": 100, "scan_duration_seconds": 42.5, "options": { "udp_enabled": false, "nmap_used": true, "banners_grabbed": true, "cve_mapping": true, "min_cvss": 0.0 } }, "executive_summary": { "total_hosts_scanned": 254, "live_hosts": 12, "total_open_ports": 48, "total_findings": 7, "unique_cves": 5, "findings_by_severity": { "CRITICAL": 2, "HIGH": 3, "MEDIUM": 2, "LOW": 0, "INFO": 0 }, "hosts_with_critical": 2 }, "risk_score": { "score": 72, "max_score": 100, "label": "HIGH", "methodology": "CVSS-weighted sum, capped at 100" }, "hosts": [ { "ip": "192.168.1.10", "hostname": "web01.local", "os_guess": "Ubuntu 22.04", "os_accuracy": "95%", "rtt_ms": 1.2, "open_ports": [ { "port": 80, "protocol": "tcp", "state": "open", "service": "http", "product": "Apache", "version": "2.4.49", "version_string": "Apache/2.4.49 (Debian)", "banner": "Server: Apache/2.4.49 (Debian)\r\n...", "tls": false, "rtt_ms": 0.5 } ], "vulnerabilities": [ { "cve_id": "CVE-2021-41773", "name": "Apache 2.4.49 Path Traversal / RCE", "severity": "CRITICAL", "cvss_score": 9.8, "description": "...", "affected_port": 80, "exploitable_remotely": true, "remediation": "Upgrade Apache to >= 2.4.51 immediately.", "references": ["https://nvd.nist.gov/..."] } ] } ], "findings_index": [ { "cve_id": "CVE-2021-41773", "severity": "CRITICAL", "cvss_score": 9.8, "affected_hosts": [{ "ip": "192.168.1.10", "port": 80 }], "remediation": "Upgrade Apache to >= 2.4.51." } ], "recommendations": [ { "action": "Upgrade Apache to >= 2.4.51 immediately.", "priority": "CRITICAL", "max_cvss": 9.8, "cves": ["CVE-2021-41773"] } ] } ``` ## 运行测试套件 ``` # 运行所有测试并输出详细信息 python -m pytest tests/ -v # 运行并生成覆盖率报告 python -m pytest tests/ --cov=scanner --cov-report=term-missing # 运行单个测试模块 python -m pytest tests/test_cve_mapper.py -v # 运行特定的测试类 python -m pytest tests/test_port_scanner.py::TestPortScanner -v # 运行特定的测试方法 python -m pytest tests/test_host_discovery.py::TestInetChecksum::test_known_value -v ``` **测试覆盖率目标:** | 模块 | 测试 | 覆盖重点 | |---|---|---| | `host_discovery.py` | `test_host_discovery.py` | Checksum, packet, sweep, CIDR | | `port_scanner.py` | `test_port_scanner.py` | PortResult, TCP/UDP 状态, 解析 | | `service_detector.py` | `test_port_scanner.py` | 各协议 banner 解析器 | | `cve_mapper.py` | `test_cve_mapper.py` | 数据库加载,所有匹配维度 | | `report_generator.py` | `test_cve_mapper.py` | 所有报告部分 | | `utils.py` | `test_host_discovery.py` | CIDR 扩展,端口解析 | ## 扩展 NVS ### 添加新的服务解析器 1. 在 `service_detector.py` 中添加 `_parse_myservice(banner: str) -> Dict` 函数。 2. 在 `ServiceDetector._HANDLERS` 中注册它: ``` _HANDLERS = { ... 9999: _parse_myservice, } ``` ### 添加新的 CVE 特征 按照上述结构编辑 `data/cve_patterns.json`,或者使用 `--cve-db` 提供单独的文件。 ### 添加新的报告部分 子类化或扩展 `ReportGenerator.generate()`: ``` class MyReportGenerator(ReportGenerator): def generate(self, hosts, scan_info=None): report = super().generate(hosts, scan_info) report["my_section"] = self._build_my_section(hosts) return report ``` ### 编程 API ``` from scanner import HostDiscovery, PortScanner, ServiceDetector, CVEMapper, ReportGenerator from scanner.utils import expand_cidr, parse_port_range ips = expand_cidr("10.0.0.0/24") ports = parse_port_range("22,80,443,8080") live = HostDiscovery(max_workers=50).sweep(ips) det = ServiceDetector() hosts = [] for h in live: scanner = PortScanner(timeout=1.0, max_workers=100) prs = scanner.scan(h["ip"], ports) h["open_ports"] = [ {**pr.to_dict(), **det.detect(pr.port, pr.banner, pr.tls)} for pr in prs ] hosts.append(h) mapper = CVEMapper(min_cvss=7.0) for h in hosts: h["vulnerabilities"] = mapper.map_host(h) report = ReportGenerator().generate(hosts) ``` ## 性能调优 | 场景 | 推荐设置 | |---|---| | 快速 /24 扫描 | `--discovery-threads 100 --threads 200 --timeout 0.5 --no-banners` | | 彻底的单主机扫描 | `--threads 50 --timeout 2.0 -p 1-65535` | | 隐蔽 / IDS 规避 | `--threads 10 --timeout 3.0` | | 大型 /16 网络 | `--discovery-threads 200 --threads 50 --timeout 0.3 --no-banners -p top-100` | ## 限制与已知问题 | 限制 | 详情 | |---|---| | **不支持 SYN 扫描** | NVS 使用完整的 TCP 连接。SYN 扫描速度更快且更隐蔽,但需要原始套接字。如果需要 SYN 扫描,请直接使用 Nmap。 | | **UDP 准确性** | 没有 root 权限,关闭的 UDP 端口与被过滤的端口无法区分。许多 UDP 端口将显示为 `open\|filtered`。 | | **CVE 匹配查全率** | 特征匹配是启发式的。没有发现结果并不代表主机是安全的。务必结合人工验证。 | | **误报** | 基于 Banner 的匹配可能会在展示了软件名称但已打过补丁的主机上触发。请独立验证版本。 | | **不支持 IPv6** | 主机发现和端口扫描仅针对 IPv4。 | | **无速率限制** | NVS 不会限制出站数据包速率。在拥塞的链路上,请减少线程数并增加超时时间。 | | **Windows 支持** | 原始 ICMP 套接字在 Windows 上需要管理员权限;TCP-ping 备用方案无需提权即可运行。 | ## 贡献指南 1. **Fork** 仓库并创建功能分支:`git checkout -b feature/my-improvement` 2. 为 `tests/` 中的任何新功能**编写测试**。 3. 确保 `python -m pytest tests/ -v` 通过且没有失败。 4. 遵循 PEP 8 规范;为所有公共函数和类添加 docstrings。 5. **更新** `data/cve_patterns.json`,为任何新的 CVE 条目提供来源和参考。 6. 提交一个带有清晰变更描述及其安全理由的 **Pull Request**。 ### 添加 CVE 条目 对 `cve_patterns.json` 的贡献必须包含: - 有效的 CVE ID(或针对无 CVE 的错误配置使用 `MISCONFIG-NNN`)。 - 来自 [nvd.nist.gov](https://nvd.nist.gov) 的经过验证的 `cvss_score`。 - 至少一个指向官方安全公告的 `references` URL。 - 简明的 `remediation` 操作。 ## 许可证 ``` MIT License Copyright (c) 2024 NVS Project Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ``` *为安全社区而生。请负责任地进行测试。*
标签:Python, Scrypt密钥派生, 加密, 插件系统, 数据统计, 无后门, 服务指纹识别, 漏洞扫描器, 端口扫描, 网络安全, 逆向工具, 隐私保护