Skip to content

Ayeesha02/Network-Vulnerability-Scanner

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Network Vulnerability Scanner (NVS)

⚠ Legal Notice: This tool is intended exclusively for authorised penetration testing and security research. Using it against systems you do not own or have explicit written permission to test is illegal. The authors accept no liability for misuse.


Table of Contents

  1. Overview
  2. Architecture
  3. Project Structure
  4. Scan Pipeline
  5. Installation
  6. Quick Start
  7. CLI Reference
  8. Module Documentation
  9. CVE Pattern Database
  10. Report Format
  11. Running the Test Suite
  12. Extending NVS
  13. Performance Tuning
  14. Limitations & Known Issues
  15. Contributing
  16. License

Overview

NVS is a zero-dependency Python CLI that automates the first four phases of a network penetration test — host discovery (ICMP + TCP-ping), port enumeration (TCP connect + UDP), service fingerprinting (banner parsing for 15+ protocols), and CVE triage (pattern matching against a curated 40-entry vulnerability database) — and exports structured JSON reports with CVSS-weighted risk scores and prioritised remediation actions.

Built for security engineers who need a fast, auditable, air-gap-friendly alternative to stringing together nmap + grep + spreadsheets.

⚠️ For authorised penetration testing only. Scanning systems without explicit written permission is illegal in most jurisdictions.

Targets → Live hosts → Open ports → Service versions → CVE matches → JSON report
Capability Implementation Privilege
Host discovery ICMP Echo Request (raw socket) root / CAP_NET_RAW
Host discovery (fallback) TCP connect to common ports none
Port enumeration TCP three-way handshake none
UDP port scanning Protocol-specific probes none
Banner grabbing recv() / TLS wrap none
Service fingerprinting Regex parsers per protocol none
OS detection python-nmap (-O) root (for Nmap)
CVE pattern matching Local JSON database none
Reporting Structured JSON none

Key design principles:

  • Zero mandatory third-party dependencies — the core pipeline runs on the Python standard library; python-nmap and rich are optional extras.
  • Thread-pool concurrencyThreadPoolExecutor is used for both host discovery and port scanning; pool sizes are tunable per scan.
  • Graceful degradation — raw-socket ICMP falls back to TCP-ping when unprivileged; Nmap phase is silently skipped when the binary is absent.
  • Structured output — every scan produces machine-readable JSON suitable for import into vulnerability-management platforms.

Architecture

┌─────────────────────────────────────────────────────────────────┐
│                          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

Project Structure

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

Scan Pipeline

Phase 1 — Host Discovery (host_discovery.py)

Goal: Identify which IPs in the target range are reachable before spending time port-scanning dead hosts.

ICMP Sweep (preferred, requires root)

  1. A raw AF_INET / SOCK_RAW / IPPROTO_ICMP socket is created.
  2. An ICMP type-8 (Echo Request) packet is built with:
    • Type=8, Code=0
    • Identifier = os.getpid() & 0xFFFF
    • Sequence = 1
    • Payload = timestamp bytes
    • Checksum = RFC 1071 Internet Checksum over header + payload
  3. The reply (type-0 Echo Reply) is captured; RTT is computed.

TCP-Ping Fallback (no root)

When PermissionError is raised (no CAP_NET_RAW), a TCP connect to a list of common ports (80, 443, 22, 445…) is tried. Any successful connect_ex() == 0 means the host is alive.

Concurrency: ThreadPoolExecutor(max_workers=discovery_threads) — default 50 workers, tunable via --discovery-threads.


Phase 2a — Port Enumeration (port_scanner.py)

TCP Connect Scan

For each port, socket.connect_ex((target, port)) is called with settimeout(timeout). Return codes:

Return code State
0 open
ECONNREFUSED (111) closed
timeout / other filtered

Only open ports are returned by default (verbose mode includes all states).

Banner Grabbing (optional, --no-banners to disable)

After a successful connect:

  1. Passive recv: for protocols that send data immediately (SSH, FTP, SMTP, POP3, IMAP).
  2. HTTP GET probe: for HTTP/HTTPS ports, a minimal GET / HTTP/1.0 request is sent.
  3. TLS wrap: for TLS ports (443, 8443, 993…) a second connection wraps the socket with ssl.create_default_context() (verification disabled for self-signed certs).

UDP Scanning (--udp)

Protocol-specific probes are sent to well-known UDP ports. State inference:

Result State
Response received open
ConnectionRefusedError (ICMP port-unreachable) closed
Timeout open|filtered

Concurrency: ThreadPoolExecutor(max_workers=threads) — default 100 workers, tunable via --threads.


Phase 2b — Service Detection (service_detector.py)

Per-port regex parsers extract structured metadata from raw banners:

Service Parser Extracted Fields
SSH _parse_ssh() product (OpenSSH), version, OS hint
FTP _parse_ftp() product (ProFTPD, vsftpd), version
SMTP _parse_smtp() product (Postfix, Exim), version
HTTP _parse_http() product, version, framework hint
POP3 _parse_pop3() version string
IMAP _parse_imap() version string
MySQL _parse_mysql() version (from Protocol v10 packet)
Redis _parse_redis() version string
RDP _parse_rdp() static identification

For TLS ports, ssl.SSLSocket.cipher() and getpeercert() extract:

  • Negotiated TLS version (TLSv1.2, TLSv1.3)
  • Cipher suite name
  • Certificate Common Name and SAN list
  • Certificate expiry date

Phase 3 — Nmap Enrichment (nmap_scanner.py) (optional)

Activated with --nmap. Requires both:

  • nmap binary on $PATH
  • pip install python-nmap

Default arguments: -sV -O --version-intensity 5

NVS only passes already-discovered open ports to Nmap, making the run significantly faster than a full Nmap sweep.

Merge strategy: Nmap data is overlaid on the existing host dict:

  • product and version are backfilled only when currently blank or "unknown".
  • os_guess and os_accuracy are set at the host level.
  • NSE script output is stored in each port's extra.nmap_scripts dict.

NSE scripts (--nmap-scripts "default,vuln"): execute Nmap's built-in vulnerability detection scripts. The vuln category is intrusive — use only on authorised targets.


Phase 4 — CVE Pattern Matching (cve_mapper.py)

Each open port is tested against every pattern in data/cve_patterns.json using four matching dimensions (OR-logic across dimensions):

Dimension Condition
Port match Target port ∈ affected_ports AND protocol matches
Service keyword service_keywords[i] substring of detected service name
Banner pattern banner_patterns[i] substring of raw banner (lowercased)
Version range Detected version ∈ [version_min, version_max] (semver comparison)

Findings are sorted by severity: CRITICAL → HIGH → MEDIUM → LOW → INFO.

CVSS severity thresholds (v3 scale):

CVSS Score Severity
9.0 – 10.0 CRITICAL
7.0 – 8.9 HIGH
4.0 – 6.9 MEDIUM
0.1 – 3.9 LOW
0.0 INFO

Use --min-cvss 7.0 to suppress noise during initial triage.


Installation

Prerequisites

Requirement Version Purpose
Python ≥ 3.8 Runtime
pip any Package management
nmap binary ≥ 7.0 Phase 3 (optional)
Root / sudo ICMP ping, Nmap -O

Install from source

# 1. Clone the repository
git clone https://github.com/example/network-vuln-scanner.git
cd network-vuln-scanner

# 2. Create and activate a virtual environment (recommended)
python3 -m venv .venv
source .venv/bin/activate          # Linux / macOS
# .venv\Scripts\activate.bat       # Windows

# 3. Install the package (core only — no third-party deps)
pip install -e .

# 4. Optional: Nmap integration
pip install -e ".[nmap]"

# 5. Optional: full development install
pip install -e ".[all]"

Verify installation

nvs --help
python -m pytest tests/ -v

Quick Start

# Scan a single host (top 100 ports, no root required)
nvs -t 192.168.1.10

# Scan a /24 subnet and save JSON report
sudo nvs -t 192.168.1.0/24 -p top-100 -r reports/scan.json

# Full TCP port range + UDP + Nmap OS detection
sudo nvs -t 10.0.0.5 -p 1-65535 --udp --nmap -r full_scan.json

# Read targets from file, filter findings CVSS >= 7.0
nvs -f targets.txt -p 22,80,443,3389,8080 --min-cvss 7.0 -r report.json

# Skip host discovery (all targets assumed live)
nvs -t 10.0.0.100 -p top-100 --skip-discovery -v

# Use custom CVE database + run Nmap NSE scripts
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 Reference

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]

Target Specification

Flag Description
-t, --target TARGET Single IP, CIDR block (192.168.1.0/24), or hostname
-f, --target-file FILE Newline-delimited file of IPs / CIDRs / hostnames (# comments OK)

Port Specification

Flag Default Description
-p, --ports PORTS top-100 top-100 | 22,80,443 | 1-1024 | mixed
--udp off Probe common UDP ports in addition to TCP
--skip-discovery off Treat all targets as live; skip Phase 1

Scan Tuning

Flag Default Description
--timeout S 1.0 Per-port connection timeout (seconds)
--threads N 100 TCP scan thread-pool size
--discovery-threads N 50 Host discovery thread-pool size
--no-banners off Skip banner grabbing (faster; less service info)

Nmap Integration

Flag Default Description
--nmap off Enable Phase 3 Nmap enrichment
--nmap-args ARGS -sV -O --version-intensity 5 Raw Nmap argument string
--nmap-scripts SCRIPTS NSE scripts (e.g. default,vuln). Implies --nmap.

CVE Mapping

Flag Default Description
--no-cve off Skip Phase 4 CVE pattern matching
--cve-db PATH data/cve_patterns.json Custom CVE patterns JSON file
--min-cvss SCORE 0.0 Minimum CVSS score to report (0.0 = all)

Output

Flag Default Description
-r, --report FILE Write JSON report to FILE
--no-color off Disable ANSI colour codes
-v, --verbose off Show closed / filtered ports
-q, --quiet off Suppress progress; print findings only

Module Documentation

scanner.utils

Shared helpers used across the pipeline.

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

from scanner.host_discovery import HostDiscovery, probe_host

# Probe a single host
result = probe_host("192.168.1.10", timeout=1.0)
# → {"ip": "192.168.1.10", "alive": True, "rtt_ms": 0.8,
#    "method": "icmp", "hostname": "web.local", "discovered_at": "..."}

# Sweep a subnet
hd = HostDiscovery(max_workers=50, timeout=0.5, resolve=True)
live = hd.sweep(["192.168.1.1", "192.168.1.2", ...])
# or
live = hd.discover_from_cidr("192.168.1.0/24")

scanner.port_scanner

from scanner.port_scanner import PortScanner, UDPScanner

# TCP connect scan
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 scan
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 statistics
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 Pattern Database

The bundled database (data/cve_patterns.json) ships with 40 patterns covering critical network-facing vulnerabilities and common misconfigurations.

Included Patterns

CVE ID Name Severity Primary Port(s)
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

Pattern Schema

{
  "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"]
}

Adding Custom Patterns

// 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

Report Format

The JSON report structure:

{
  "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"]
    }
  ]
}

Running the Test Suite

# Run all tests with verbose output
python -m pytest tests/ -v

# Run with coverage report
python -m pytest tests/ --cov=scanner --cov-report=term-missing

# Run a single test module
python -m pytest tests/test_cve_mapper.py -v

# Run a specific test class
python -m pytest tests/test_port_scanner.py::TestPortScanner -v

# Run a specific test method
python -m pytest tests/test_host_discovery.py::TestInetChecksum::test_known_value -v

Test coverage targets:

Module Tests Coverage Focus
host_discovery.py test_host_discovery.py Checksum, packet, sweep, CIDR
port_scanner.py test_port_scanner.py PortResult, TCP/UDP states, parsing
service_detector.py test_port_scanner.py Per-protocol banner parsers
cve_mapper.py test_cve_mapper.py DB loading, all match dimensions
report_generator.py test_cve_mapper.py All report sections
utils.py test_host_discovery.py CIDR expansion, port parsing

Extending NVS

Adding a New Service Parser

  1. Add a _parse_myservice(banner: str) -> Dict function to service_detector.py.
  2. Register it in ServiceDetector._HANDLERS:
_HANDLERS = {
    ...
    9999: _parse_myservice,
}

Adding a New CVE Pattern

Edit data/cve_patterns.json following the schema above, or supply a separate file with --cve-db.

Adding a New Report Section

Subclass or extend 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

Programmatic 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)

Performance Tuning

Scenario Recommended Settings
Fast /24 survey --discovery-threads 100 --threads 200 --timeout 0.5 --no-banners
Thorough single-host --threads 50 --timeout 2.0 -p 1-65535
Stealth / IDS evasion --threads 10 --timeout 3.0
Large /16 network --discovery-threads 200 --threads 50 --timeout 0.3 --no-banners -p top-100

Note: Aggressive thread counts and short timeouts increase the chance of missing hosts behind rate-limiting firewalls. Adjust based on network conditions and engagement scope.


Limitations & Known Issues

Limitation Details
No SYN scan NVS uses full TCP connect. SYN scanning is faster and stealthier but requires raw sockets. Use Nmap directly if SYN scanning is required.
UDP accuracy Without root, closed UDP ports are indistinguishable from filtered. Many UDP ports will show as open|filtered.
CVE matching recall Pattern matching is heuristic. Absence of a finding does NOT mean a host is safe. Always combine with manual verification.
False positives Banner-based matching can fire on hosts that display the software name but have already been patched. Verify version independently.
No IPv6 support Host discovery and port scanning target IPv4 only.
No rate limiting NVS does not throttle outbound packets. On congested links, reduce thread counts and increase timeouts.
Windows support Raw ICMP sockets require Administrator on Windows; the TCP-ping fallback works without elevation.

Contributing

  1. Fork the repository and create a feature branch: git checkout -b feature/my-improvement
  2. Write tests for any new functionality in tests/.
  3. Ensure python -m pytest tests/ -v passes with no failures.
  4. Follow PEP 8 style; add docstrings to all public functions and classes.
  5. Update data/cve_patterns.json with sources and references for any new CVE entries.
  6. Open a Pull Request with a clear description of the change and its security rationale.

Adding CVE entries

Contributions to cve_patterns.json must include:

  • A valid CVE ID (or MISCONFIG-NNN for misconfigurations without a CVE).
  • A verified cvss_score from nvd.nist.gov.
  • At least one references URL pointing to an official advisory.
  • A concise remediation action.

License

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.

Built for the security community. Test responsibly.

About

Python CLI for host discovery, port scanning, service fingerprinting & CVE triage. Zero mandatory dependencies. For authorised penetration testing only.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages