首页 / 资讯中心 / 文章详情

Python漏洞扫描系统毕设源码复现:端口扫描与漏洞特征匹配实战

Python漏洞扫描系统毕设源码复现:端口扫描与漏洞特征匹配实战 ★ FEATURED ARTICLE
简介这是一套面向高校计算机相关专业毕业设计的完整项目资料主题为基于Python实现的漏洞扫描系统适合正在准备毕设、需要可运行源码与配套文档的本科生或初学者参考。资源包共380个文件压缩后约84.69MB包含26个py源码文件、15个tmpl模板、26个css与53个js前端资源以及大量gif、jpg、png界面截图和woff、ttf等字体文件另附sql数据库脚本、doc说明文档与pptx演示文稿覆盖系统运行所需的代码、数据与文档。内容围绕网络安全概述、安全漏洞扫描技术、系统设计目标与可行性分析展开并展示用户登录、扫描首页、端口扫描模块与扫描列表模块等实现成果可帮助读者理解漏洞扫描系统的整体架构与开发流程。目前已有3163人学习下载适合作为毕设选题参考、代码复现与文档撰写模板。1. 从一份毕设源码说起Python 漏洞扫描系统到底能跑出什么结果很多安全方向的同学做毕业设计时最头疼的不是写论文而是找不到一套能跑通、有界面、有数据库、还能写进论文的完整系统。这份基于 Python 的漏洞扫描系统包含源码、数据库文件和说明文档正好卡在这个需求点上。它的核心能力是端口扫描加漏洞特征匹配配合用户登录、扫描列表管理、结果展示几个模块构成一个闭环的 Web 应用。适合两类人一是需要快速搭出毕设原型的安全专业学生二是想拿一套现成代码研究扫描器架构的初级开发。我拿到这份资源后第一件事不是看论文而是把源码目录翻了一遍确认它用的是 nikto 的配置文件和特征库前端是 layui 加 bootstrap 的混合风格数据库大概率是 SQLite 或 MySQL。下面按实际复现路径拆开讲。2. 环境搭建与依赖安装把 Python 版本和数据库选型先定死2.1 Python 版本与虚拟环境的选择理由这份源码没有在文档里写死 Python 版本但从它引用的库和代码风格判断Python 3.8 到 3.10 之间最稳。我一般不会直接用系统自带的 Python因为很多 Linux 发行版预装的是 3.6 甚至 2.7跑起来会报一堆语法错误。常见做法是用 venv 建一个隔离环境把依赖锁在项目目录里避免污染全局。# 创建虚拟环境指定 Python 3.9 为例 python3.9 -m venv venv # 激活虚拟环境Linux/macOS source venv/bin/activate # 激活虚拟环境Windows venv\Scripts\activate # 升级 pip 并安装依赖 pip install --upgrade pip pip install -r requirements.txt这里的关键参数是-m venv它会在当前目录生成一个 venv 文件夹里面包含独立的 Python 解释器和 pip。激活后命令行前面会出现(venv)标识所有 pip 安装的包都只在这个环境里生效。如果 requirements.txt 里没有锁版本号建议手动补上Flask2.0.3、requests2.27.1这类常见组合避免最新版 API 变动导致启动失败。2.2 数据库初始化SQLite 和 MySQL 的取舍源码包里带了数据库文件从文件扩展名看大概率是.db结尾的 SQLite 文件。SQLite 的好处是零配置直接用一个文件存数据适合毕设演示和单机运行。但如果你论文里要写“高并发”或“多用户同时扫描”那就得换成 MySQL。我一般会先按 SQLite 跑通确认业务逻辑没问题后再迁移。# 常见的数据库连接配置片段以 SQLite 为例 import sqlite3 # 连接数据库如果文件不存在会自动创建 conn sqlite3.connect(scanner.db) # 创建游标对象 cursor conn.cursor() # 创建用户表字段根据源码文档推测 cursor.execute( CREATE TABLE IF NOT EXISTS users ( id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT NOT NULL UNIQUE, password TEXT NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) ) # 创建扫描任务表 cursor.execute( CREATE TABLE IF NOT EXISTS scan_tasks ( id INTEGER PRIMARY KEY AUTOINCREMENT, target_ip TEXT NOT NULL, port_range TEXT, status TEXT DEFAULT pending, result TEXT, user_id INTEGER, FOREIGN KEY (user_id) REFERENCES users(id) ) ) conn.commit() conn.close()这段代码做了两件事建用户表和扫描任务表。AUTOINCREMENT保证主键自增UNIQUE约束防止用户名重复FOREIGN KEY把任务和用户关联起来。如果你用的是 MySQL把sqlite3.connect换成pymysql.connect(hostlocalhost, userroot, passwordxxx, databasescanner)即可建表语句里的AUTOINCREMENT要改成AUTO_INCREMENT。注意 SQLite 默认不允许外键约束生效需要额外执行PRAGMA foreign_keys ON;。2.3 依赖库安装中的常见报错处理requirements.txt 里通常包含 Flask、requests、python-nmap 或 socket 相关库。安装时最容易翻车的是python-nmap因为它依赖系统级的 nmap 命令。如果只 pip 安装而不装 nmap 二进制运行时会报nmap program was not found in path。解决办法是先装系统包# Ubuntu/Debian 系统 sudo apt-get install nmap # CentOS/RHEL 系统 sudo yum install nmap # macOS 用 Homebrew brew install nmap装完后在 Python 里执行import nmap并实例化nmap.PortScanner()如果没报错就说明环境通了。另一个常见问题是cv2相关依赖有些扫描器会用 OpenCV 做验证码识别但这份源码从目录结构看没有涉及图像处理如果 requirements.txt 里意外包含了opencv-python可以直接删掉能省掉几百 MB 的下载量。3. 核心模块拆解端口扫描与漏洞特征匹配怎么落地3.1 端口扫描模块的实现逻辑与参数调优端口扫描是整个系统的入口。从源码目录里的 nikto 配置文件来看它可能借用了 nikto 的特征库但扫描动作本身大概率是用 Python 的 socket 或 nmap 库完成的。我一般会先用 socket 写一个轻量级扫描器因为不依赖外部命令部署更简单。import socket from concurrent.futures import ThreadPoolExecutor def scan_port(ip, port, timeout1): 扫描单个端口是否开放 :param ip: 目标 IP :param port: 端口号 :param timeout: 超时时间单位秒 :return: (port, is_open) try: # 创建 TCP socket sock socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 设置超时避免长时间阻塞 sock.settimeout(timeout) # 尝试连接 result sock.connect_ex((ip, port)) sock.close() # connect_ex 返回 0 表示端口开放 return (port, result 0) except Exception as e: return (port, False) def scan_ports(ip, ports, max_workers100): 多线程扫描多个端口 :param ip: 目标 IP :param ports: 端口列表 :param max_workers: 线程池大小 :return: 开放端口列表 open_ports [] with ThreadPoolExecutor(max_workersmax_workers) as executor: # 提交所有扫描任务 futures [executor.submit(scan_port, ip, port) for port in ports] for future in futures: port, is_open future.result() if is_open: open_ports.append(port) return open_ports # 调用示例扫描常见 100 个端口 common_ports [21, 22, 23, 25, 53, 80, 110, 135, 139, 143, 443, 445, 993, 995, 1433, 1521, 3306, 3389, 5432, 6379, 8080, 8443] result scan_ports(192.168.1.1, common_ports) print(f开放端口: {result})settimeout(1)是平衡速度和准确率的关键。设太长扫 1000 个端口要等很久设太短网络延迟高的目标会误判为关闭。我一般对内网目标用 0.5 秒对公网目标用 1 到 2 秒。max_workers100也不是越大越好线程太多会导致系统文件描述符耗尽报Too many open files。如果扫描大量目标建议降到 50 并配合队列分批处理。3.2 漏洞特征匹配从 nikto 配置到 Python 规则引擎目录里的nikto.conf和nikto.1说明这套系统参考了 nikto 的扫描规则。nikto 本身是 Perl 写的但它的配置文件里定义了大量的漏洞特征比如特定路径返回特定状态码、响应头里缺少安全字段等。在 Python 里复现这套逻辑核心是维护一个规则列表每条规则包含匹配条件和漏洞描述。import requests # 漏洞规则库模拟 nikto 的配置结构 VULN_RULES [ { id: VULN-001, path: /admin/, method: GET, match_type: status_code, match_value: 200, description: 后台管理页面可未授权访问 }, { id: VULN-002, path: /.git/config, method: GET, match_type: status_code, match_value: 200, description: Git 配置文件泄露 }, { id: VULN-003, path: /, method: GET, match_type: header_missing, match_value: X-Frame-Options, description: 缺少 X-Frame-Options 响应头存在点击劫持风险 } ] def check_vulnerability(base_url, rule, timeout5): 根据单条规则检测漏洞 :param base_url: 目标基础 URL :param rule: 规则字典 :param timeout: 请求超时 :return: 漏洞详情或 None url base_url.rstrip(/) rule[path] try: resp requests.request( methodrule[method], urlurl, timeouttimeout, allow_redirectsFalse, verifyFalse # 忽略 SSL 证书错误方便测试 ) # 状态码匹配 if rule[match_type] status_code: if resp.status_code rule[match_value]: return { id: rule[id], url: url, description: rule[description], evidence: f状态码 {resp.status_code} } # 响应头缺失匹配 elif rule[match_type] header_missing: if rule[match_value] not in resp.headers: return { id: rule[id], url: url, description: rule[description], evidence: f缺少响应头 {rule[match_value]} } except requests.RequestException as e: # 请求失败不视为漏洞记录日志即可 pass return None def scan_vulnerabilities(base_url): 遍历所有规则扫描目标 findings [] for rule in VULN_RULES: result check_vulnerability(base_url, rule) if result: findings.append(result) return findings # 调用示例 vulns scan_vulnerabilities(http://192.168.1.100) for v in vulns: print(f[{v[id]}] {v[description]} - {v[url]})这段代码把 nikto 的配置思路翻译成了 Python 字典。match_type支持状态码匹配和响应头缺失匹配实际项目中还可以扩展正则匹配响应体内容。verifyFalse是为了跳过自签名证书的校验在测试环境里很常见但生产环境千万别这么干。allow_redirectsFalse也很关键否则 302 跳转后拿到的是最终页面的状态码会漏掉重定向型漏洞。3.3 扫描结果入库与前端展示的数据流扫描完成后结果要写进数据库并在前端页面展示。从说明文档的目录看系统有“扫描列表模块”和“首页”说明结果是以列表形式呈现的。我一般会把每次扫描任务和对应的漏洞详情分开存方便按任务查询。import sqlite3 import json def save_scan_result(task_id, target_ip, open_ports, vulnerabilities): 将扫描结果写入数据库 :param task_id: 任务 ID :param target_ip: 目标 IP :param open_ports: 开放端口列表 :param vulnerabilities: 漏洞列表 conn sqlite3.connect(scanner.db) cursor conn.cursor() # 更新任务状态为已完成 cursor.execute( UPDATE scan_tasks SET status completed, result ? WHERE id ? , (json.dumps({ open_ports: open_ports, vulnerabilities: vulnerabilities }, ensure_asciiFalse), task_id)) conn.commit() conn.close() def get_scan_list(user_id): 查询指定用户的扫描任务列表 conn sqlite3.connect(scanner.db) cursor conn.cursor() cursor.execute( SELECT id, target_ip, port_range, status, result FROM scan_tasks WHERE user_id ? ORDER BY id DESC , (user_id,)) rows cursor.fetchall() conn.close() return rowsjson.dumps把端口和漏洞列表序列化成字符串存进result字段取出来时用json.loads反序列化。这样做的好处是表结构简单不用为端口和漏洞各建一张表。缺点是没法用 SQL 直接筛选“包含某个漏洞的任务”如果论文里要写复杂查询建议拆成三张表任务表、端口表、漏洞表。前端展示时layui 的表格组件可以直接接收 JSON 数组把result字段解析后渲染成两列开放端口和漏洞列表。4. 避坑与排查这套源码跑不起来时先查这五个地方4.1 启动报 ModuleNotFoundError现象是运行python app.py后直接抛异常提示某个模块找不到。原因通常是依赖没装全或者虚拟环境没激活。解决方法是先确认命令行前面有(venv)标识然后执行pip list看关键库是否存在。如果 requirements.txt 里漏了某个库根据报错信息单独pip install即可。注意有些库的导入名和安装名不一样比如python-nmap装完后导入的是nmapPyMySQL导入的是pymysql。4.2 数据库连接失败或表不存在现象是登录页面提交后报 500 错误日志里显示no such table: users。原因是数据库文件没初始化或者路径写错了。解决方法是找到源码里的建表脚本通常在init_db.py或models.py里手动执行一遍。如果用的是 SQLite确认.db文件在项目根目录下并且 Python 进程有读写权限。如果用的是 MySQL检查host、port、user、password四个参数是否和本地环境一致。4.3 端口扫描结果全是关闭现象是扫描 192.168.1.1 的 80 端口明明浏览器能打开但程序返回关闭。原因是目标机器开了防火墙或者 socket 超时设得太短。解决方法是先用telnet 192.168.1.1 80或nc -zv 192.168.1.1 80确认端口确实开放然后把settimeout调到 3 秒再试。如果目标在外网还要确认本机网络没有限制出站连接。另外注意connect_ex返回 0 才是开放返回 111 是连接被拒绝返回 110 是超时。4.4 漏洞扫描模块请求超时或报 SSL 错误现象是扫描 HTTPS 站点时程序卡住或者抛SSLError。原因是requests默认验证 SSL 证书而测试目标往往用的是自签名证书。解决方法是在请求参数里加verifyFalse同时用urllib3.disable_warnings()屏蔽警告。如果目标响应很慢把timeout从 5 秒调到 10 秒并加上try...except捕获超时异常避免单个请求失败导致整个扫描中断。4.5 前端页面样式错乱或表格不显示数据现象是登录后首页一片空白或者表格里没有数据。原因是静态文件路径配置不对或者后端返回的 JSON 格式和 layui 表格要求的格式不匹配。解决方法是打开浏览器开发者工具看 Network 面板里 CSS 和 JS 文件是否 404。如果 404检查 Flask 的static_folder和template_folder配置。如果接口返回了数据但表格不渲染确认返回的 JSON 里code字段是否为 0msg是否为空data是否为数组。layui 表格默认要求{code: 0, msg: , data: [...]}这种结构。5. 进阶技巧把扫描器改造成可扩展的插件式架构这套源码目前的规则是硬编码在 Python 文件里的加一条新规则就得改代码、重启服务。如果你想让论文里的“系统设计”部分更有说服力可以把它改成插件式架构把每条漏洞规则写成一个独立的 JSON 文件放在rules/目录下程序启动时自动加载。这样新增漏洞只需要加文件不用动核心代码。import os import json def load_rules_from_dir(rules_dirrules): 从指定目录加载所有 JSON 规则文件 :param rules_dir: 规则目录路径 :return: 规则列表 all_rules [] if not os.path.isdir(rules_dir): return all_rules # 遍历目录下所有 .json 文件 for filename in os.listdir(rules_dir): if filename.endswith(.json): filepath os.path.join(rules_dir, filename) with open(filepath, r, encodingutf-8) as f: try: rule_data json.load(f) # 支持单个规则或规则数组 if isinstance(rule_data, list): all_rules.extend(rule_data) else: all_rules.append(rule_data) except json.JSONDecodeError as e: print(f规则文件 {filename} 解析失败: {e}) return all_rules # 调用示例 rules load_rules_from_dir(rules) print(f共加载 {len(rules)} 条规则)对应的规则文件rules/git_leak.json内容如下{ id: VULN-002, path: /.git/config, method: GET, match_type: status_code, match_value: 200, description: Git 配置文件泄露 }这样改造后扫描引擎只负责遍历规则并执行匹配规则本身完全数据化。你可以在论文里画一张架构图说明“规则引擎与规则库分离”的设计模式。验证方法也很简单往rules/目录里丢一个新 JSON 文件重启服务后看日志里加载的规则数量是否增加。我一般会写一个单元测试用assert len(load_rules_from_dir(rules)) 预期数量来确保加载逻辑没被改坏。还有一个实用技巧是给扫描任务加一个“并发限制”参数。默认的ThreadPoolExecutor如果不限制队列长度提交一万个任务会瞬间吃满内存。可以在scan_ports函数里加一个max_queue参数用executor._work_queue.maxsize控制或者直接用semaphore限制同时进行的扫描数量。这些细节写进论文的“性能优化”小节比空谈“高效扫描”要实在得多。从那以后我每次拿到一套毕设源码都强制先跑一遍数据库初始化脚本再手动扫一个本地端口验证核心链路最后才去调前端样式。这套流程帮我省掉了至少三次“代码没问题但就是跑不起来”的玄学排查。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站