前言
在企业安全建设中,Nessus 作为商业漏洞扫描器的标杆,几乎是安全团队的标配工具。然而其高昂的商业授权费用让很多个人开发者和小型团队望而却步。本文将手把手带你用 Python 从零实现一个功能完备的个人主机漏洞扫描器——VulnScanner,覆盖端口扫描、服务识别、CVE漏洞匹配、Web漏洞检测、SSL/TLS检查、SMB/SSH/MySQL专项检查等核心功能,最终生成专业的HTML报告。
项目完整代码已开源,总计 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 # SSH检查(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也会主动发送
data = 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+ 条目的漏洞特征库,覆盖:
- OpenSSH:30+ CVE,覆盖 5.1 到 9.5 版本
- Apache HTTP Server:20+ CVE,覆盖 2.4.1 到 2.4.55
- Nginx: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 # CRITICAL
cvss: float # 9.8
description: str # Apache路径遍历+RCE
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漏洞检测是覆盖面最广的检查模块,包含五大检测能力:
CMS指纹识别:内置15+种CMS的指纹库(WordPress、Joomla、Drupal、ThinkPHP、Laravel、Spring等),通过HTTP响应头、HTML正文特征、特定路径探测三种方式综合判断。
敏感路径扫描:检查30+种常见敏感路径,包括 .env、.git/HEAD、phpinfo.php、backup.sql 等。使用多线程并发扫描提高效率。
安全头检查:检查 HSTS、CSP、X-Frame-Options、X-Content-Type-Options、X-XSS-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检查模块覆盖证书验证、协议版本、加密套件和漏洞检测四大方面:
证书检查:
- 有效期检查(过期/即将过期)
- 域名匹配检查(CN和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)检测。检测流程:
- 发送 SMB Negotiate Protocol Request
- 发送 Session Setup AndX Request(匿名)
- 发送 Tree Connect 到 IPC$
- 发送 Transaction2 Request
- 检查返回的错误码是否为
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 定位为个人学习和轻量级安全检查工具,不适合替代企业级扫描方案。
七、使用注意事项
- 合法性:仅在授权目标上使用,未授权扫描属于违法行为
- 网络影响:大规模扫描可能影响网络性能,建议控制线程数
- 误报:自动化工具存在误报可能,需人工验证
- 弱密码检测:可能触发账户锁定,谨慎使用
- 隐私:扫描报告可能包含敏感信息,妥善保管
八、扩展方向
- 添加 UDP 扫描支持
- 引入异步 I/O(asyncio)提升性能
- 接入 NVD API 实时更新漏洞库
- 添加 Web 管理界面
- 支持分布式扫描
- 添加 PoC 验证能力
总结
本文完整实现了一个功能齐全的个人漏洞扫描器,涵盖了安全扫描的核心流程。虽然在漏洞覆盖度和检测深度上远不及商业工具,但作为一个学习项目,它涵盖了网络编程、并发处理、协议分析、安全检测等多个技术领域的实战知识。
完整项目代码约 5800 行 Python,500+ 条CVE特征库,164 条弱密码字典,可直接运行使用。欢迎 Star 和 PR!
本工具仅供安全研究和授权测试使用,使用者需自行承担法律责任。
评论