返回首页

用Python复刻Nessus:个人主机漏洞扫描器完整实现

前言

在企业安全建设中, 作为商业漏洞扫描器的标杆,几乎是安全团队的标配工具。然而其高昂的商业授权费用让很多个人开发者和小型团队望而却步。本文将手把手带你用 从零实现一个功能完备的个人主机漏洞扫描器——VulnScanner,覆盖端口扫描、服务识别、漏洞匹配、Web漏洞检测、SSL/TLS检查、SMB/SSH/MySQL专项检查等核心功能,最终生成专业的报告。

项目完整代码已开源,总计 5800+ 行 Python 代码,包含 500+ 条CVE漏洞特征库。

一、架构设计

1.1 整体流程

扫描器采用经典的五阶段流水线架构:

端口扫描 → 服务识别 → CVE匹配 → 专项检查 → 报告生成

每个阶段都是独立模块,通过字典结构传递数据,便于扩展和维护。

1.2 项目结构

vuln-scanner/
├── scanner.py               # 主程序入口(331行)
├── utils.py                 # 工具函数(393行)
├── vuln_db.py               # 漏洞特征库(1284行,500+ CVE)
├── report.py                # HTML报告生成(358行)
├── wordlist/passwords.txt    # 弱密码字典(164条)
├── requirements.txt
└── modules/
    ├── port_scan.py          # 端口扫描(525行)
    ├── service_detect.py     # 服务检测(434行)
    ├── cve_match.py          # CVE匹配(121行)
    ├── web_vuln.py           # Web漏洞(504行)
    ├── ssl_check.py          # SSL检查(456行)
    ├── smb_check.py          # SMB检查(454行)
    ├── ssh_check.py          # 检查(275行)
    └── mysql_check.py        # MySQL检查(392行)

二、核心模块实现

2.1 端口扫描模块

端口扫描是整个流程的起点。我们使用 TCP Connect Scan(全连接扫描),通过 Python 的 socket 模块实现:

def tcp_connect_scan(host, port, timeout=2.0):
    try:
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.settimeout(timeout)
        result = sock.connect_ex((host, port))
        sock.close()
        return result == 0
    except (socket.error, OSError):
        return False

关键设计点:

  • 并发控制:使用 ThreadPoolExecutor 实现多线程扫描,默认200个线程
  • 进度条:自定义 ProgressBar 类实时显示扫描进度、速度和ETA
  • Banner抓取:对开放端口自动发送探测报文获取服务Banner
  • 端口列表:内置 Top 1000 常用端口列表,覆盖绝大多数场景

对于不同协议的Banner抓取策略各有不同。HTTP端口发送HEAD请求获取Server头,SSH/FTP/SMTP等协议会主动发送Banner,MySQL则需要解析Greeting包:

def grab_banner(host, port, timeout=3.0):
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.settimeout(timeout)
    sock.connect((host, port))

    if port in http_ports:
        probe = f"HEAD / HTTP/1.1\r\nHost: {host}\r\n\r\n"
        sock.send(probe.encode())
    # SSH/FTP/SMTP会主动发送Banner,无需发送探测
    # MySQL Greeting也会主动发送

     = sock.recv(4096)
    sock.close()
    return data.decode('utf-8', errors='replace').strip()

2.2 服务版本检测模块

拿到Banner后,我们需要精确识别服务类型和版本号。service_detect.py 实现了针对20+种服务的深度检测:

SSH检测:解析SSH协议Banner字符串 SSH-2.0-OpenSSH_8.9p1 Ubuntu,提取协议版本、软件名和具体版本号。

HTTP检测:发送HTTP请求,从Server头和X-Powered-By头中提取Web服务器版本和技术栈。支持HTTPS(自动SSL握手)。

MySQL检测:解析MySQL Greeting包结构——4字节长度 + 1字节序列号 + null结尾的版本字符串,从中提取MySQL/MariaDB版本。

SMB检测:发送SMB Negotiate Protocol Request,解析响应获取操作系统信息和SMB版本。

每个检测器都是 ServiceDetector 类的方法,通过端口号和Banner内容自动选择检测策略:

class ServiceDetector:
    def detect(self, host, port, banner='', service_hint=''):
        if port == 22 or service_hint == 'ssh':
            return self._detect_ssh(host, port)
        elif port in (80, 443, ...) or service_hint in ('http', 'https'):
            return self._detect_http(host, port)
        # ... 20+ 种服务检测策略

2.3 CVE漏洞匹配模块

这是扫描器的核心价值所在。vuln_db.py 构建了一个包含 500+ 条目的漏洞特征库,覆盖:

  • :30+ CVE,覆盖 5.1 到 9.5 版本
  • Apache HTTP Server:20+ CVE,覆盖 2.4.1 到 2.4.55
  • :10+ CVE,覆盖 1.6 到 1.23
  • MySQL/MariaDB:40+ CVE,覆盖 5.6 到 8.0
  • Tomcat:30+ CVE,覆盖 8.0 到 10.1
  • FTP (vsftpd/ProFTPD):15+ CVE
  • PostgreSQL:15+ CVE

每条漏洞记录包含CVE编号、受影响服务、版本模式、严重等级、CVSS评分、描述和修复建议:

@dataclass
class VulnEntry:
    cve_id: str           # CVE-2021-41773
    service: str          # http
    version_pattern: str  # 2.4.49
    severity: Severity    # 
    cvss: float           # 9.8
    description: str      # Apache路径遍历+
    remediation: str      # 升级到2.4.50+
    exploit_available: bool  # True

匹配逻辑支持精确匹配、前缀匹配(如 2.4.)和范围匹配(如 7.0-7.4):

def matches(self, service, version):
    if self.service.lower() != service.lower():
        return False
    vp = self.version_pattern.lower()
    ver = version.lower()
    if vp.endswith('.x'):
        return ver.startswith(vp[:-2])
    if '-' in vp:
        parts = vp.split('-')
        return parts[0].strip() <= ver <= parts[1].strip()
    return vp in ver or ver.startswith(vp)

2.4 Web漏洞检测模块

Web漏洞检测是覆盖面最广的检查模块,包含五大检测能力:

指纹识别:内置15+种CMS的指纹库(WordPress、Joomla、、ThinkPHP、Laravel、Spring等),通过HTTP响应头、HTML正文特征、特定路径探测三种方式综合判断。

敏感路径扫描:检查30+种常见敏感路径,包括 .env.git/HEADphpinfo.php.sql 等。使用多线程并发扫描提高效率。

安全头检查:检查 HSTS、CSP、X-Frame-Options、X-Content-Type-Options、X--Protection 等安全响应头。

默认凭据检测:针对已识别的CMS,尝试其默认登录页面是否存在。

信息泄露检测:检查Server版本泄露、X-Powered-By泄露、错误页面技术细节、HTML注释中的敏感信息。

class WebVulnScanner:
    def scan(self, host, port, service='http'):
        resp = self._http_request(host, port, '/')

        # CMS指纹识别
        cms, version = self._identify_cms(host, port, headers, body)

        # 敏感路径扫描(多线程)
        sensitive_vulns = self._check_sensitive_paths(host, port, base_url)

        # 安全头检查
        header_vulns = self._check_security_headers(base_url, headers)

        # 信息泄露检查
        info_vulns = self._check_info_disclosure(base_url, headers, body)

2.5 SSL/TLS安全检查模块

SSL检查模块覆盖证书验证、协议版本、加密套件和漏洞检测四大方面:

证书检查

  • 有效期检查(过期/即将过期)
  • 域名匹配检查(和SAN)
  • 自签名证书检测

协议版本:检测是否支持不安全的 SSLv2/SSLv3/TLS 1.0/TLS 1.1

加密套件:检测RC4、DES、NULL、EXPORT等弱加密算法

class SSLChecker:
    def check(self, host, port=443):
        cert_info = self._get_certificate(host, port)
        vulns = self._check_certificate(host, port, cert_info)
        vulns.extend(self._check_protocols(host, port))
        vulns.extend(self._check_ciphers(host, port))
        vulns.extend(self._check_heartbleed(host, port))
        return vulns

2.6 SMB安全检查模块

SMB模块的核心亮点是永恒之蓝(MS17-010)检测。检测流程:

  1. 发送 SMB Negotiate Protocol Request
  2. 发送 Session Setup AndX Request(匿名)
  3. 发送 Tree Connect 到 IPC$
  4. 发送 Transaction2 Request
  5. 检查返回的错误码是否为 STATUS_INSUFF_SERVER_RESOURCES (0xC0000205)

此外还检查:

  • SMBv1支持:SMBv1是WannaCry/EternalBlue的攻击面
  • SMB签名:未强制启用SMB签名存在中间人攻击风险

2.7 SSH安全检查模块

SSH检查模块集成 paramiko 库实现弱密码检测:

def _try_ssh_auth(self, host, port, username, password):
    client = paramiko.SSHClient()
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    client.connect(host, port=port, username=username,
                   password=password, timeout=self.timeout,
                   allow_agent=False, look_for_keys=False)
    client.close()
    return True  # 认证成功=弱密码

内置25组常见默认凭据,同时支持加载自定义密码字典(164条弱密码)。

2.8 MySQL安全检查模块

MySQL检查使用 pymysql 库,检测项目包括:

  • 弱密码检测(25组默认凭据)
  • 匿名访问检查
  • 版本过期检测
  • 远程root访问检查
  • secure_file_priv 配置检查
  • 通用查询日志检查

三、报告生成

报告生成模块 report.py 产出专业的HTML报告,特点:

  • 严重性分级:严重(红)、高危(橙)、中危(黄)、低危(蓝)、信息(灰)
  • 比例条:直观显示各级别漏洞占比
  • 漏洞详情:CVE编号、CVSS评分、描述、利用状态、修复建议
  • 端口表格:完整展示开放端口和识别到的服务
  • 响应式设计:支持移动端查看

HTML报告使用纯CSS实现,无外部依赖,单文件可直接在浏览器中打开。

四、命令行接口

主程序 scanner.py 使用 argparse 实现完善的命令行接口:

# 基本扫描
python3 scanner.py --target 192.168.1.1

# 指定端口范围和报告路径
python3 scanner.py -t 192.168.1.0/24 -p top100 -o scan.html -T 100

# 全端口扫描
python3 scanner.py -t 10.0.0.1 --ports full --output full.html

支持的目标格式:

  • 单个IP:192.168.1.1
  • CIDR网段:192.168.1.0/24
  • IP范围:192.168.1.1-10
  • 主机名:example.com
  • 文件路径:targets.txt(每行一个目标)

五、性能与优化

  • 并发模型ThreadPoolExecutor + as_completed,默认50线程
  • 资源控制:连接超时3秒,避免长时间阻塞
  • 进度追踪:实时进度条显示完成百分比、扫描速度、预计剩余时间
  • 错误容错:单个目标失败不影响整体扫描

六、与Nessus的对比

特性 VulnScanner Nessus
价格 免费开源 $3,000+/年
CVE库 500+ 70,000+
部署 pip install 专用安装包
扫描速度 中等
插件系统 丰富的插件
适用场景 个人/小团队 企业级

VulnScanner 定位为个人学习和轻量级安全检查工具,不适合替代企业级扫描方案。

七、使用注意事项

  1. 合法性:仅在授权目标上使用,未授权扫描属于违法行为
  2. 网络影响:大规模扫描可能影响网络性能,建议控制线程数
  3. 误报:自动化工具存在误报可能,需人工验证
  4. 弱密码检测:可能触发账户锁定,谨慎使用
  5. 隐私:扫描报告可能包含敏感信息,妥善保管

八、扩展方向

  • 添加 UDP 扫描支持
  • 引入异步 I/O(asyncio)提升性能
  • 接入 NVD 实时更新漏洞库
  • 添加 Web 管理界面
  • 支持分布式扫描
  • 添加 PoC 验证能力

总结

本文完整实现了一个功能齐全的个人漏洞扫描器,涵盖了安全扫描的核心流程。虽然在漏洞覆盖度和检测深度上远不及商业工具,但作为一个学习项目,它涵盖了网络编程、并发处理、协议分析、安全检测等多个技术领域的实战知识。

完整项目代码约 5800 行 Python,500+ 条CVE特征库,164 条弱密码字典,可直接运行使用。欢迎 Star 和 PR!


本工具仅供安全研究和授权测试使用,使用者需自行承担法律责任。

评论