ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

用Python从零构建综合网络安全扫描器:模块化设计与实战解析

用Python从零构建综合网络安全扫描器:模块化设计与实战解析 简介网络安全评估的第一步往往不是寻找漏洞而是完成资产信息收集。通过端口扫描、服务识别、子域名枚举、目录扫描与弱口令检测等手段安全人员能够快速勾勒出目标网络的暴露面为后续渗透测试提供关键依据。Python凭借其丰富的第三方库生态、高效的开发效率以及良好的外部工具集成能力成为构建扫描器的理想语言。基于socket、concurrent.futures与aiohttp等核心模块可以实现稳定且并发的扫描引擎同时结合模块化架构与可插拔设计让每个功能独立解耦、按需启用。本文从工程实践角度出发详细拆解一个综合扫描器的设计思路、关键实现与性能调优经验并探讨在线程调度、超时策略、误报过滤及批量目标处理等方面的避坑技巧帮助开发者和安全从业者构建可靠、合规的资产探测工具从而更高效地完成暴露面检查与攻击面梳理。 做安全的朋友应该都有体会每次拿到一个授权测试或红蓝对抗任务最先要干的往往不是找漏洞而是先把目标网络“摸清楚”。目标开放了哪些端口、跑了什么服务、有哪些子域名、后台路径藏在哪、是否存在弱口令这些信息直接决定了后续的攻击面有多大。我也是出于这个需求用 Python 从零写了一个综合网络安全扫描工具核心模块全部开源这篇文章就把整个设计思路、关键代码和踩坑过程完整拆一遍。这个工具适合三类人一是刚学 Python 想做点实战项目的同学扫描器涉及的 socket 编程、并发调度、HTTP 请求、DNS 解析都是非常典型的技术点二是安全从业者日常做资产梳理、暴露面检查时用它做第一轮信息收集能省不少事三是做运维的偶尔想快速看看自己管理的服务器开了哪些端口、有没有异常服务也能直接用起来。1. 项目整体设计为什么用 Python 写扫描器1.1 扫描器要解决的核心问题很多人对“扫描器”有误解觉得就是拿现成工具跑一下就完事。但真正自己写一遍就会发现这里面的技术点远比想象中密集。一个综合扫描器至少要覆盖五层工作端口探测、服务识别、子域名收集、目录扫描、弱口令检测。每一层都不是简单发个请求就结束背后牵扯到网络协议、并发控制、超时策略、结果去重、误报过滤等一系列问题。我选择用 Python 写核心原因有三个第一Python 的第三方库生态太全了socket、requests、aiohttp、concurrent.futures 这些库拿出来就能用不用自己造轮子第二Python 的开发效率高写一个扫描器的核心逻辑大概只需要几个小时改起来也方便这对一个需要频繁迭代的工具来说非常关键第三Python 的胶水特性让它很容易跟外部工具集成比如调用系统里的 masscan、nmap 来做深度探测。但这并不意味着 Python 没有劣势。Python 的 GIL 锁决定了它在 CPU 密集型任务上表现一般但我们的扫描场景绝大多数是 I/O 密集型——发请求、等响应、收结果这种场景下 Python 的异步和线程池反而能发挥得很好。实测下来用 ThreadPoolExecutor 开 200 个线程做端口扫描对一个 /24 网段的常见端口扫描耗时基本在 3-5 分钟范围内完全够用。1.2 架构选型模块解耦与可插拔设计设计这个扫描器时我给自己定了几条原则第一每个功能模块必须是独立的模块之间只有数据依赖关系不能有代码层面的耦合。比如端口扫描模块扫描结果要传给服务识别模块但它们各自只依赖一个统一的数据结构比如 dict 或 dataclass不能出现互相 import 内部函数的情况。第二所有需要人工指定或配置的参数都通过命令行传入不在代码里硬编码。包括目标地址、端口范围、线程数、超时时间、字典路径、输出格式等。第三每个模块都要有独立的启用开关。默认情况下端口扫描和 HTTP 服务探测是打开的子域名枚举、目录扫描、弱口令检测默认关闭通过命令行参数按需开启。这样设计的好处是用户可以根据自己的场景灵活组合比如只做端口扫描时完全不需要加载弱口令模块既节省时间也降低误报风险。这个设计思路其实借鉴了现在主流扫描器的做法。大家熟知的工具都有类似的参数体系但自己从零实现一遍你会对“为什么默认关闭某些模块”这件事有更深的理解。后面讲弱口令模块时我会专门说这个点。1.3 代码目录结构与核心文件职责实际项目的目录结构如下scanner/ ├── scanner.py # 主入口参数解析、任务调度 ├── modules/ │ ├── __init__.py │ ├── port_scan.py # 端口扫描模块 │ ├── service_detect.py # 服务识别模块 │ ├── subdomain.py # 子域名枚举模块 │ ├── dir_scan.py # 目录扫描模块 │ ├── weak_pass.py # 弱口令检测模块 │ └── report.py # 结果输出模块 ├── dicts/ │ ├── common_ports.txt # 常见端口列表 │ ├── subnames.txt # 子域名字典 │ ├── dirs.txt # 目录字典 │ └── weak_pass.txt # 弱口令字典 └── requirements.txt这个结构很清晰入口文件只负责参数解析和流程编排具体的扫描逻辑全部放在 modules 下面字典文件统一放 dicts 目录。这样后面扩展新模块时只需要在 modules 下新建一个文件然后在主入口加一行路由代码就行。2. 核心功能模块拆解与实现要点2.1 端口扫描模块TCP Connect 与 SYN 扫描的取舍端口扫描是整个工具的地基后面所有模块都依赖它的产出来决定下一步往哪走。我在模块里实现了两种扫描方式TCP Connect 扫描和 SYN 半开扫描默认用 TCP Connect因为在这种场景下它最稳定不需要管理员权限也不会因为依赖特定库而出现兼容性问题。TCP Connect 的扫描原理很简单向目标主机的某个端口发起完整的 TCP 三次握手如果握手成功说明端口开放否则就是关闭或过滤状态。这个用 Python 的 socket 库就能实现代码核心逻辑如下import socket from concurrent.futures import ThreadPoolExecutor def check_port(host: str, port: int, timeout: float 1.0) - bool: sock socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(timeout) try: result sock.connect_ex((host, port)) return result 0 finally: sock.close() def scan_ports(host: str, ports: list, threads: int 100, timeout: float 1.0) - list: open_ports [] with ThreadPoolExecutor(max_workersthreads) as executor: futures {executor.submit(check_port, host, port, timeout): port for port in ports} for future in futures: port futures[future] if future.result(): open_ports.append(port) return sorted(open_ports)这里有个关键点需要说清楚connect_ex() 返回 0 才表示连接成功其他非零值都是失败。很多初学者直接用 connect() 然后捕获异常虽然也能用但 connect_ex() 的语义更直接性能也更好因为它不发异常只是返回一个错误码。SYN 半开扫描的原理不同它只发送 SYN 包收到 SYN-ACK 就认为端口开放然后直接发送 RST 断开不等完整的握手。这种方式快而且目标主机的应用层不会感知到连接隐蔽性更好。但 Python 要实现 SYN 扫描通常需要用到 scapy 库而且要 root 权限跨平台兼容性也差。我在代码里保留了接口但默认不启用。端口范围的选择上我默认读取 dicts/common_ports.txt 里的列表包含大约 100 个常用端口覆盖 Web、数据库、远程管理、邮件等服务。如果有全端口扫描需求也支持用命令行指定 1-65535 全范围但实际使用中我建议按需扫描因为全端口扫描不仅慢而且会产生大量探测流量内网环境还好公网环境很容易触发目标的安全设备告警。2.2 服务识别模块Banner 抓取与特征匹配知道端口开放只是第一步更重要的是知道端口后面跑的是什么服务。服务识别模块的核心思路是先尝试读取目标服务返回的 banner 信息比如版本号、服务指纹如果拿不到 banner 就用 HTTP 请求头、默认端口映射等特征做综合判断。TCP 服务比如 SSH、MySQL、Redis的 banner 抓取比较直接——连接成功后发一个空请求或特定指令等服务端返回特征字符串。这里有一个容易踩坑的地方不同服务的交互协议差异很大SSH 连上后服务端会直接返回版本字符串但很多服务比如某些数据库必须客户端先发数据才会响应。所以我在实现时提供两种模式一种是连上就读一种是发送探针后再读。def grab_banner(host: str, port: int, timeout: float 3.0, send_probe: bool False) - str: try: sock socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(timeout) sock.connect((host, port)) if send_probe: sock.send(b\r\n) banner sock.recv(1024).decode(utf-8, errorsignore).strip() sock.close() return banner[:200] if banner else except Exception: return 拿到 banner 之后用一个正则匹配库去比对特征。比如SSH-2.0-OpenSSH_5.3这种格式一看就知道是 OpenSSH 5.3220 (vsFTPd 3.0.3)就是 vsFTPd 3.0.3。匹配的结果不仅要保存服务名还要保存版本号因为后面做 CVE 匹配时版本信息是核心输入。HTTP/HTTPS 服务的识别是另一套逻辑。需要发 GET / 请求然后从响应头里提取 Server 字段、X-Powered-By 字段再结合响应体的 title、headers 结构判断 Web 服务类型和中间件信息。这里我注意到一点很多 Web 服务器的默认错误页和 404 页面特征差异很明显可以用来辅助判断。2.3 子域名枚举模块DNS 解析与并发请求子域名枚举在资产收集里的价值极高因为很多企业只对主域名做了防护子域名往往才是真正的薄弱点。这个模块的实现逻辑不复杂读入一个子域名字典把每个词拼接到主域名前面然后做 DNS 解析能解析出的就记录下来。但问题是效率。逐条用 socket.getaddrinfo() 解析太慢了一个几万词的字典可能要跑很久。我改用异步 HTTP 方式 公共 DNS 服务器批量查询用 aiohttp 并发请求速度提升非常明显。一个一万词的字典配置 100 并发大概 30 秒内能完成全部探测。import aiohttp import asyncio async def check_subdomain(session: aiohttp.ClientSession, sub: str, domain: str) - str | None: fqdn f{sub}.{domain} url fhttps://{fqdn} try: async with session.get(url, timeout5) as resp: if resp.status 500: return fqdn except Exception: pass return None async def enum_subdomains(domain: str, wordlist_path: str, concurrency: int 100) - list: with open(wordlist_path, r) as f: words [line.strip() for line in f if line.strip()] found [] connector aiohttp.TCPConnector(limitconcurrency, sslFalse) async with aiohttp.ClientSession(connectorconnector) as session: tasks [check_subdomain(session, w, domain) for w in words] results await asyncio.gather(*tasks) found [r for r in results if r] return found这里有个实用的技巧先做一次主域名的连通性测试如果主域名本身都无法访问比如 DNS 解析失败、防火墙拦截那整个子域名枚举基本没有意义直接跳过节省时间。另外用 HTTP 探测而不是纯 DNS 解析的好处是有些子域名虽然 DNS 有记录但服务器已经下线了或者没有对应站点这类“假资产”可以通过 HTTP 状态码直接过滤掉一部分。但要注意有些子域名只开了非 443/80 端口是纯内网服务不会被这个模块发现这部分就需要结合端口扫描的结果来综合分析。2.4 目录扫描模块状态码过滤与响应大小判断目录扫描的目的是发现 Web 应用下的隐藏路径、备份文件、后台入口等。实现思路是发送 HTTP 请求到每个字典路径根据响应状态码和页面大小判断这个路径是否存在。实际开发过程中我发现最容易出问题的地方是“怎样区分 404 和存在的页面”——很多站点的 404 页面会返回 200 状态码而很多真实页面又可能因为 WAF 拦截返回 403。我的处理办法是用三层判断第一层看状态码200/301/302/401/403 都先标记为候选第二层看响应大小如果请求路径返回的内容和 404 页面大小完全相同就认为是 404即使状态码是 200第三层看响应内容的特征词比如 404 页面一般包含 Page Not Found、不存在 等关键词如果命中就直接过滤掉。def check_dir(session: requests.Session, base_url: str, path: str) - dict | None: url urljoin(base_url, path) try: resp session.get(url, timeout5, allow_redirectsFalse) content_length len(resp.content) if resp.status_code in [200, 301, 302, 401, 403]: return { url: url, status: resp.status_code, length: content_length, title: extract_title(resp.text) } except Exception: pass return None字典质量直接决定目录扫描的产出率。我自己用的字典经过多次调整分为几个层次第一层是手工整理的 20 个高频路径比如/admin、/.git/、/backup.zip、/phpinfo.php等适合快速探测第二层是常见开发框架的默认路径比如 ThinkPHP 的/index.php、Spring Boot 的/actuator第三层是完整的通用大字典路径数在两万以上跑一轮比较慢但比较全。实际使用中我建议先跑第一层快速拿结果再根据目标框架类型选择性地跑第二层或第三层。2.5 弱口令检测模块默认关闭与授权边界说实话弱口令检测模块是我整写过程中最谨慎的部分。它的技术实现不复杂本质就是向目标服务发起多次登录尝试。但这里涉及两个层面的问题一是合法性二是技术上的误报控制。技术实现上我把弱口令检测做成了通用框架支持扩展不同的服务类型。以 SSH 为例用 paramiko 库尝试建立 SSH 连接账号密码都匹配则连接成功否则失败以 FTP 为例用 ftplib 库尝试登录。代码接口统一新增一种服务只需要实现一个 login() 函数即可。def check_ssh(host: str, port: int, username: str, password: str, timeout: float 10.0) - bool: import paramiko client paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) try: client.connect(host, portport, usernameusername, passwordpassword, timeouttimeout, allow_agentFalse, look_for_keysFalse) client.close() return True except Exception: return False但我做了两个硬性设计第一该模块默认关闭必须显式加--weak-pass参数才会启用第二启用时必须有授权标识参数比如输入授权文件路径否则直接报错退出。这不是形式主义而是为了避免工具被滥用。之前看到不少因为弱口令扫描引发法律纠纷的案例所以想在代码层面做一点约束。另外在字典选择上我只保留了比较常规的测试组合刻意过滤掉了一些有破坏性的账号密码组合限制在合理安全评估范围内。3. 工程落地调度、并发与结果输出3.1 线程池与任务编排方案扫描器的主流程其实是一个流水线先跑端口扫描拿到存活主机和开放端口然后根据端口类型调用对应的服务识别模块如果启用了子域名枚举则在端口扫描之前并行启动在确认 Web 服务存在后启动目录扫描最后按需运行弱口令检测。我用一个简单的步骤管理器来编排这些流程同时维护一个任务队列把每次扫描的任务状态记录下来。端口扫描和子域名枚举是并行的服务识别依赖端口扫描结果目录扫描依赖服务识别结果弱口令检测则进一步依赖前两者的结果。这种依赖关系在代码里体现为递增的 stage 标记每个模块执行结束后更新 stage下一个模块启动前检查前置 stage 是否完成。并发控制是整个工具最容易出性能问题的部分。我用 ThreadPoolExecutor 做线程池管理每个模块有独立的线程数配置。端口扫描默认 200 个线程、子域名枚举用 asyncio 做 100 并发、目录扫描用 50 个线程。为什么不统一用一个超大并发因为在实践中发现过高的并发会导致本地连接数耗尽、目标防火墙触发封禁、甚至出现大量超时导致结果不可靠。合理的并发数取决于网络环境内网可以用高一点的并发公网建议保守一点。3.2 多格式结果输出终端、CSV 与 HTML 报告扫描结果如果只打印到终端基本等于白扫——端口几百个你要一个一个去翻所以我把结果输出做成了三层终端彩色输出、CSV 数据导出、HTML 可视化报告。终端输出用 ANSI 转义码做颜色标记开放端口用绿色、高风险服务用红色、可疑状态用黄色。这不算什么高深技术但确实让使用体验好了不少尤其是在大段扫描日志里快速定位关键信息。CSV 输出比较简单每一行是一条扫描记录字段包括目标 IP、端口、服务名、版本、状态、扫描时间。这份文件可以直接喂给 Excel 或 Python pandas 做后续分析处理。HTML 报告则是把扫描结果整理成结构化页面包含统计概览、端口列表、服务识别情况、子域名列表、目录扫描结果、弱口令检测结果等。实现上不依赖 flask 这些框架直接用字符串模板拼接把结果渲染成 HTML 文件方便分享给团队或存档。下面是我用的模板片段def generate_html_report(results: dict, output_path: str) - None: html_template !DOCTYPE html html headmeta charsetutf-8titleScan Report/title/head body h1Scan Report/h1 h2Target: {target}/h2 h3Open Ports/h3 table border1 trthPort/ththService/ththVersion/th/tr {port_rows} /table /body /html rows for item in results.get(services, []): rows ftrtd{item[port]}/tdtd{item[name]}/tdtd{item[version]}/td/tr html html_template.format(targetresults[target], port_rowsrows) with open(output_path, w, encodingutf-8) as f: f.write(html)这里虽然没有做复杂的图表可视化但胜在轻量不用装额外依赖而且结构清晰后续要扩展图表库也不难。3.3 命令行参数与配置文件设计工具的使用方式决定了它的可达性。我设计了一组简单但完整的命令行参数python scanner.py -t 192.168.1.0/24 -p common -o report.html --threads 200 --timeout 2各参数含义如下-t指定目标支持单个 IP、IP 段、域名-p指定端口范围可选 common、full 或自定义-o指定输出文件名--threads控制并发线程数--timeout控制超时时间--subdomain开启子域名枚举--dir-scan开启目录扫描--weak-pass开启弱口令检测。配置文件我用了标准的 configparser 格式把代理设置、线程数、超时时间、字典路径等写进 config.ini这样用户不用每次敲命令都带一长串参数只需要修改配置文件即可。命令行参数的优先级高于配置文件这个逻辑用常规的 argparse 就能实现逻辑简单但很实用。4. 性能调优与避坑经验4.1 并发数、超时时间怎么调才合理这块经验是我在真实环境中一次一次试出来的。先说线程数。端口扫描用 200 个线程看起来很多但实际上每个线程大部分时间都阻塞在 socket 连接上等待远程响应。真正的瓶颈往往不在 CPU 或线程而在本地网络连接的可用性——Linux 下默认的文件描述符限制是 1024如果你把线程数调到 500每个线程又开了 socket 连接很快就超出限制了这时会报Too many open files错误。解决方法是调整文件描述符上限ulimit -n 65535但我不建议无脑调高线程数还要考虑目标网络环境。我实测过对公网目标开 500 线程做全端口扫描很快就会被目标机房的防火墙拦截之后的探测全部超时。内网环境相对宽松但也要看目标网络有没有 IDS/IPS。合理策略是先用低并发比如 50 线程试跑一小段端口确认网络通畅后再按需提高。超时时间同样需要谨慎设置。太短可能误报存活端口太长扫描总耗时直线上升。常用的经验值是局域网内 0.5-1 秒公网 2-3 秒跨大洲网络 5 秒。我在代码里把超时时间设成一个可配置参数用户按需调整而不是硬编码。4.2 误报与漏报为什么扫描结果不能全信扫描器本身只是一台“手电筒”照到的地方不一定就是真相。我把误报、漏报的排查归纳为四种常见情况。第一种是状态码误判。很多 Web 框架对不存在的路径也返回 200比如 SPA 应用的前端路由。我之前扫描一个 Vue 开发的站点几乎所有目录路径都返回 200渲染出来的内容却都是同一个首页。后来加了响应内容比对把与首页相同 size 的结果全部过滤一下子就没那么多假数据了。第二种是端口状态与真实服务不匹配。有时候端口开放了但前端防火墙直接把连接转移到蜜罐上你看到的 banner 是伪造的。这属于对抗场景暂时没有完美的自动化方案只能靠经验判断——如果某个端口 banner 特别标准、响应速度异常快就要多留个心眼。第三种是 DNS 解析的超时。子域名枚举时有些 DNS 服务器对不存在的域名返回 NXDOMAIN 很快有些却要等超时。如果异步请求并发太高DNS 服务器可能直接限流导致大量超时结果就是漏报很多真实存在的子域名。我的经验是把 DNS 查询分散到多个公共 DNS 上同时控制并发量保证单个 DNS 服务器不被压垮。第四种是依赖库环境差异。比如 Windows 官方 Python 安装包自带的 SSL 库版本较低某些 HTTPS 站点握手会失败导致目录扫描输出大量异常结果。这个问题在换机器后尤其容易遇到建议在 requirements.txt 里固定依赖库的版本避免因为升级导致行为不一致。4.3 目标多了怎么办批量扫描与结果归一化实际工作中很少只扫一台机器更多时候是扫一个网段甚至多个网段。工具需要支持批量目标的编排。我把“目标列表”做成两种输入方式一种是命令行直接传递一个网段另一种是从文本文件读取 IP 和域名列表。批量扫描时我按主机为单位拆分任务每台主机单独执行完整的扫描流水线结果统一归集到内存数据库用 Python 的 sqlite3 标准库最终生成一份汇总报告。这样设计的好处是即使某台主机在扫描过程中因为网络波动出现异常也不影响其他主机的扫描结果。同时任务状态可以持久化支持断点续扫——上次跑到一半中断下次启动时跳过已完成的记录。5. 常见问题与排查技巧实录5.1 依赖安装与跨平台兼容问题这个项目依赖的第三方库主要有 requests、aiohttp、paramiko、python-nmap可选、beautifulsoup4可选。安装很简单pip install -r requirements.txt但这里有几个容易踩的坑。首先是 aiohttp 在 Windows 下的事件循环选择问题如果安装了 uvloopLinux 下常用在 Windows 上会导入失败。我的处理方式是在代码里强制使用 ProactorEventLoopif sys.platform win32: asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy())其次 paramiko 库在部分 Linux 发行版上需要编译依赖如果安装失败可以试着先安装对应的系统级依赖或者直接使用官方提供的二进制 wheel 包。另外如果你想用 python-nmap 做深度探测需要本机安装了 Nmap这个在 Ubuntu 上是apt install nmap在 macOS 上是brew install nmapWindows 下要去官网下载安装包。5.2 扫描结果为空或全部超时的原因排查如果跑完一轮扫描结果全是空的不要急着怀疑工具先按下面顺序排查第一步确认目标可达性。用ping或curl手动访问一下目标排除网络不通的情况。注意很多服务器禁 ping所以 ping 不通不代表目标挂了用 tcping 或直接访问端口更可靠。第二步检查端口扫描的超时设置。如果目标在海外或者网络延迟高默认的超时时间可能不够试着提高--timeout参数。第三步检查是否被本机防火墙拦截。如果你本机开了严格模式防火墙比如 Windows Defender 防火墙的默认配置Python 发起的出站 TCP 连接可能被部分阻断尤其是非标准端口。这个可以临时关闭防火墙测试一下确认后记得改回来。第四步看看是不是把域名解析成 IPv6 了而目标网络没有 IPv6 路由。这种情况在部分家庭宽带上很常见解决方案是在 socket 连接时强制指定 AF_INETsocket.getaddrinfo(host, port, socket.AF_INET)5.3 扫描速度慢的优化方向全端口扫描 65535 个端口即使 200 线程并行在公网环境下也需要十几二十分钟。如果你想提速有几个方向可以考虑。第一使用 SYN 半开扫描替代 TCP Connect。前面说过 SYN 扫描不需要完整握手理论上快很多代价是需要 root 权限和一些网络底层库。用 scapy 实现 SYN 扫描实测对公网目标速度能提升 5-10 倍但这需要你对 scapy 的用法有一定了解不是开箱即用的。第二采用异步 I/O 替代线程池。线程池在高并发下线程切换开销还是比较大的改用 asyncio socket 的异步连接模式用协程模拟海量并发能把单机并发数拉到几千。代码复杂度会增加但性能提升也是实实在在的。我尝试过用 asyncio 重写端口扫描模块对局域网目标开 3000 并发跑 1-1024 端口只需要几秒钟。第三分段扫描策略。先用低并发扫一遍高频端口快速拿到存活主机列表再对存活主机做全端口扫描。这个策略在实际工作中非常高效因为大部分目标服务器的高危端口都集中在 22、80、443、3306、6379 等少数几个端口上第一轮就能发现大量有价值的信息。经验总结与后续扩展方向写这个工具的过程中我对 Python 网络编程的理解比之前加深了一个层次。最直观的体会是并发没那么神秘本质就是管理“同时等待很多个 I/O 操作”的能力超时不是随便设的不同网络环境下的最优值差很多只有实际跑过才有体感扫描器不是一个能做一次就完事的活而是要根据目标反馈不断调整参数、完善过滤逻辑。后续我打算往几个方向继续扩展一是做一个基于 FastAPI 的 Web 管理端把扫描结果持久化到数据库支持历史任务查询和对比二是接入更多指纹识别的规则库提高服务识别、框架识别的准确率三是把 Web 漏洞探测比如常见命令执行、SQL 注入的轻量检测做成一个可选模块当然这会进一步加强授权校验确保工具不会被滥用。最后分享一个实用的小技巧无论做什么扫描第一步永远是把目标范围、时间窗口、授权信息写清楚存成配置文件。等结果有争议时这份记录就是你最大的底气。工具本身是死的怎么把它用对、用合规才是每个安全从业者真正要修炼的功课。本文还有配套的精品资源点击获取
返回列表