ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Django自动化漏洞扫描系统源码解析与二次开发实战

Django自动化漏洞扫描系统源码解析与二次开发实战 简介这是一套面向网络安全初学者与渗透测试人员的Web漏洞扫描与安全评估系统源码基于Python与Django开发用于对Web应用进行自动化深度扫描与风险发现。系统集成爬虫引擎与自定义规则库可遍历页面链接、模拟攻击行为并支持按需扩展扫描规则同时提供任务管理、结果查看与评估报告生成界面。压缩包共202个文件约1.16MB以118个py源码文件为核心辅以20个html模板、9个js与7个css前端资源另含sql建表脚本、dic字典、sqlite3数据库及使用说明文档结构完整便于二次开发。目前已有91人学习下载。读者可从中获取一套可运行的漏洞扫描项目理解爬虫调度、规则匹配与报告输出的实现思路并参考其模块化设计进行功能扩展或集成到自有安全测试流程中。1. 从一份 Django 漏洞扫描系统源码说起它能替你省掉哪些手工活很多做 Web 安全的同行都有过这种体验甲方丢过来一个站要求两天内出一份安全评估报告你打开 Burp 挂上代理一边点功能一边记请求扫完还得手动整理漏洞清单、补上复现步骤和修复建议。真正耗时间的不是发现漏洞而是把发现过程标准化、把结果整理成能交付的文档。这份基于 Python 与 Django 构建的自动化 Web 应用漏洞扫描与安全检测系统瞄准的正是这段重复劳动——它把爬虫引擎、漏洞检测逻辑、自定义规则库和 Web 管理界面打包成一个可部署的完整项目你拿到手就能跑起来对目标站点做一轮深度扫描并输出结构化结果。它适合三类人一是刚接触 Web 安全、想通过读源码理解扫描器工作原理的 Python 学习者二是需要给内部系统做定期安全自查的运维或后端开发三是手里有检测需求、想基于现成框架二次开发自己规则的安全从业者。整套系统用 Django 做后端与展示层爬虫负责页面发现和表单识别规则库决定检测哪些漏洞类型三者解耦改起来不牵一发动全身。下面按「先跑通、再拆解、后避坑」的顺序把这份源码包从部署到二次开发讲透。2. 环境搭建与项目启动把 Django 扫描器在本机跑起来拿到一份 Django 项目源码第一件事不是急着读代码而是先让它在本机跑起来确认依赖完整、数据库能建、页面能开。这一步跑通后面读代码才有参照物。这份系统的技术栈是 Python Django常见做法是配 MySQL 或 SQLite爬虫部分依赖 requests 和 BeautifulSoup 这类库。下面按顺序走一遍。2.1 Python 与 Django 版本选择Django 对 Python 版本有硬性要求选错版本会在pip install阶段就报错。这份项目正文没有写明具体版本号我一般会先看requirements.txt或settings.py里的写法来判断。稳妥起见用 Python 3.83.10 配 Django 3.2 LTS 是兼容性最好的组合Django 3.2 是长期支持版第三方库适配也最全。# 查看本机 Python 版本建议 3.8 以上 python3 --version # 创建独立虚拟环境避免污染全局包 python3 -m venv venv # 激活虚拟环境Linux/macOS source venv/bin/activate # 激活虚拟环境Windows venv\Scripts\activate # 安装 Django指定 LTS 版本 pip install django3.2.20 # 安装爬虫与解析依赖 pip install requests beautifulsoup4 lxml这里几个参数值得说清楚。python3 -m venv venv创建的是一个隔离目录里面有自己的site-packages装什么库都不会影响系统 Python这是避免「装了一堆库结果互相冲突」的标准做法。django3.2.20用双等号锁定小版本防止pip自动拉到不兼容的新版。lxml是 BeautifulSoup 的高性能解析器比默认的html.parser快不少爬虫解析大量页面时差别明显。提示如果pip install lxml在 Windows 上编译失败直接装预编译轮子pip install lxml --only-binary :all:省去配编译环境的麻烦。2.2 数据库配置与迁移Django 默认用 SQLite开箱即用适合本地跑通和演示。如果要做成多人使用的扫描平台换成 MySQL 更稳。配置集中在settings.py的DATABASES段。# settings.py 数据库配置片段 DATABASES { default: { # 本地快速验证用 sqlite3生产环境换 mysql ENGINE: django.db.backends.sqlite3, NAME: BASE_DIR / db.sqlite3, } } # 若改用 MySQL替换为下面这段 # DATABASES { # default: { # ENGINE: django.db.backends.mysql, # NAME: vulnscan, # 数据库名 # USER: root, # 用户名 # PASSWORD: your_pass, # 密码 # HOST: 127.0.0.1, # 数据库地址 # PORT: 3306, # 端口 # OPTIONS: {charset: utf8mb4}, # 支持中文和特殊字符 # } # }ENGINE决定用哪个数据库后端SQLite 不需要额外服务文件即数据库适合先跑通。OPTIONS里的utf8mb4很关键扫描结果里经常出现中文路径或特殊符号用默认字符集可能写入报错。改完配置后执行迁移Django 会根据模型文件自动建表。# 生成迁移文件检测模型变化 python manage.py makemigrations # 执行迁移真正在数据库建表 python manage.py migrate # 创建后台管理员账号用于登录管理界面 python manage.py createsuperusermakemigrations只生成描述变更的 Python 文件不动数据库migrate才真正执行 SQL。两步分开是为了让你在改表结构前能 review 迁移文件避免误操作。createsuperuser会让你输入用户名、邮箱和密码这个账号用来登录 Django 自带的后台也是扫描任务管理的入口。2.3 启动服务与首次访问数据库建好后直接起开发服务器验证。# 启动开发服务器0.0.0.0 允许局域网访问 python manage.py runserver 0.0.0.0:80000.0.0.0:8000表示监听所有网卡的 8000 端口同网段的其他机器也能访问方便你把扫描器部署在一台机器上、从另一台发起测试。如果只想本机访问用默认的python manage.py runserver即可。浏览器打开http://127.0.0.1:8000能看到登录页或首页说明项目骨架已经跑通。这一步如果报ModuleNotFoundError基本是依赖没装全对照requirements.txt逐个补如果报数据库连接错误回头检查settings.py的账号密码和数据库服务状态。3. 爬虫引擎与规则库扫描逻辑是怎么串起来的项目跑起来只是第一步真正决定这套系统好不好用的是它的扫描内核。这份源码把「爬虫发现目标」和「规则匹配漏洞」拆成两个独立环节理解这个分工你才知道该改哪里、加什么。下面从爬虫工作流和规则库结构两个角度拆。3.1 爬虫引擎的页面发现与表单识别爬虫的任务不是简单地把页面抓下来而是尽可能完整地枚举出可访问的 URL 和可提交的表单因为漏洞往往藏在参数和输入点里。常见做法是从一个种子 URL 出发解析页面里的a标签提取新链接解析form标签提取提交地址、方法和字段然后递归下去直到没有新链接或达到深度上限。import requests from bs4 import BeautifulSoup from urllib.parse import urljoin, urlparse def crawl(start_url, max_depth3): 从起始 URL 出发广度优先抓取同域链接和表单 visited set() # 已访问 URL防止死循环 queue [(start_url, 0)] # (url, 当前深度) results [] # 收集到的页面与表单信息 while queue: url, depth queue.pop(0) if url in visited or depth max_depth: continue visited.add(url) try: # 设置超时避免卡在无响应页面 resp requests.get(url, timeout5) resp.encoding resp.apparent_encoding except requests.RequestException: continue # 单个页面失败不影响整体 soup BeautifulSoup(resp.text, lxml) forms [] for form in soup.find_all(form): forms.append({ action: urljoin(url, form.get(action, )), method: form.get(method, get).lower(), inputs: [i.get(name) for i in form.find_all(input) if i.get(name)], }) results.append({url: url, forms: forms}) # 提取同域链接加入队列 for a in soup.find_all(a, hrefTrue): link urljoin(url, a[href]) if urlparse(link).netloc urlparse(start_url).netloc: queue.append((link, depth 1)) return results这段代码有几个参数直接决定扫描效果。max_depth3控制爬取深度太浅会漏页面太深会指数级膨胀实际项目里通常做成可配置项。timeout5是单请求超时没有它遇到一个挂起的页面整个扫描就卡死。urlparse(link).netloc urlparse(start_url).netloc这行做同域限制只爬目标站自己的链接避免爬虫跑到外站去这既是效率考虑也是合规边界。resp.apparent_encoding让 requests 根据内容猜编码比默认的 ISO-8859-1 靠谱中文页面不会乱码。注意爬虫的请求频率要控制生产环境里加个time.sleep(0.5)或令牌桶限速否则容易把目标站打挂也可能触发对方的防护机制。3.2 自定义规则库的结构与扩展方式规则库是这套系统的灵魂它决定「扫什么漏洞、怎么判断」。常见做法是把每条规则写成一个独立配置包含匹配位置、匹配模式、危害等级和修复建议。规则和扫描引擎分离加新规则不用改引擎代码。字段含义示例rule_id规则唯一编号R001name漏洞名称SQL 注入location检测位置url 参数 / 表单字段 / 响应头pattern匹配特征报错关键字、正则severity危害等级高 / 中 / 低suggestion修复建议参数化查询# rules.py 规则库示例结构 RULES [ { rule_id: R001, name: SQL 注入疑似, location: param, payload: OR 11, # 注入测试载荷 pattern: r(SQL syntax|mysql_fetch|ORA-\d{5}), # 响应特征 severity: high, suggestion: 使用参数化查询过滤用户输入, }, { rule_id: R002, name: 反射型 XSS 疑似, location: param, payload: scriptalert(1)/script, pattern: rscriptalert\(1\)/script, # 载荷原样回显 severity: medium, suggestion: 对输出做 HTML 实体编码, }, ]payload是发出去的测试内容pattern是判断漏洞是否存在的响应特征。SQL 注入规则里如果响应里出现数据库报错关键字就说明载荷可能被带进了 SQL 语句。XSS 规则更直接载荷原样出现在响应里就判定为反射型。severity用于结果排序和报告分级suggestion直接进报告省去你手写修复建议的时间。扩展时只要往RULES列表里加字典引擎遍历执行即可这是这套设计最实用的地方。3.3 扫描任务调度与结果落库爬虫拿到 URL 和表单规则库提供检测逻辑中间需要一个调度层把两者串起来并把结果写进数据库供页面展示。Django 的模型层天然适合干这个。# models.py 扫描结果模型 from django.db import models class ScanTask(models.Model): target models.URLField() # 扫描目标 created_at models.DateTimeField(auto_now_addTrue) status models.CharField(max_length20, defaultpending) # 任务状态 class VulnResult(models.Model): task models.ForeignKey(ScanTask, on_deletemodels.CASCADE) # 关联任务 rule_id models.CharField(max_length20) url models.URLField() severity models.CharField(max_length10) detail models.TextField()ForeignKey把漏洞结果挂到扫描任务下一个任务对应多条结果删任务时结果级联删除不会留孤儿数据。status字段跟踪任务进度前端可以轮询展示「进行中 / 已完成」。调度时遍历爬虫结果对每个参数位置套用规则库里的 payload发请求、匹配 pattern、命中就写一条VulnResult。这套流程跑通后你在页面上点一次扫描后台就自动完成发现、检测、入库、展示的闭环。4. 避坑与常见问题跑扫描器时最容易翻车的几处源码能跑起来不代表能稳定出结果实际部署和扫描过程中有几类问题反复出现。下面按「现象 → 原因 → 解决」整理都是我在类似项目里踩过的。现象一扫描任务一直卡在「进行中」页面不更新。原因通常是爬虫遇到死循环或某个请求没有超时线程被挂住。递归爬取时如果 URL 规范化没做好/a和/a/会被当成两个页面反复入队。 解决给所有requests请求加timeoutURL 入队前做归一化去掉末尾斜杠、统一小写并设置最大访问数量上限超过就停。现象二明明有漏洞扫描结果却是空的。原因多半是规则里的pattern写得太死或者目标站返回的编码和预期不一致导致匹配失败。比如报错信息被 HTML 实体转义了正则匹配不到。 解决匹配前先对响应做一次html.unescape正则尽量用宽松的关键字而非完整句子并在调试时把响应原文打印出来对照。现象三扫描把目标站拖慢甚至打挂。原因是并发太高或没有限速短时间发大量请求。 解决加请求间隔把并发数压到个位数生产环境扫描前先和站点负责人确认时间窗口。这既是技术问题也是职业素养问题。现象四Django 迁移时报「No changes detected」。原因是你改了模型但 app 没注册到INSTALLED_APPSDjango 根本没扫描到你的模型文件。 解决检查settings.py的INSTALLED_APPS把应用名加进去再重新makemigrations。现象五中文扫描结果在页面上显示成乱码。原因是数据库字符集或响应编码没处理对。 解决MySQL 用utf8mb4Python 侧统一用resp.apparent_encoding解码模板输出时确认没有二次转义。提示调试扫描逻辑时先用一个你自己搭的测试站比如 DVWA 这类靶场验证规则命中率别直接拿生产站试出了误报或漏报都不好收场。5. 二次开发与验证把规则库改成你自己的检测清单跑通默认规则之后这套系统真正的价值在于你能按自己的需求扩展。我一般会先做一件事拿一个已知有漏洞的靶场跑一遍看哪些规则命中了、哪些漏了然后针对性补规则。下面说两个具体技巧。第一个是给规则加「验证请求」字段降低误报。默认规则只发一次 payload 看响应特征容易把正常报错当成注入。改进做法是命中后再发一次无害请求做对比两次响应差异明显才判定为漏洞。def verify_sql_injection(url, param, payload): 对比正常请求与注入请求的响应差异降低误报 normal requests.get(url, params{param: normal_value}, timeout5) attack requests.get(url, params{param: payload}, timeout5) # 正常请求无报错、注入请求有报错才判定命中 error_kw [SQL syntax, mysql_fetch, ORA-] normal_has_err any(k in normal.text for k in error_kw) attack_has_err any(k in attack.text for k in error_kw) return attack_has_err and not normal_has_errnormal请求用无害值attack请求用注入载荷只有「正常无报错、注入有报错」才返回 True。这个对比逻辑能把大部分因为页面本身带报错关键字导致的误报过滤掉。参数error_kw按目标数据库类型调整MySQL、Oracle、SQL Server 的报错关键字各不相同。第二个技巧是用 Django 的管理命令批量跑扫描而不是只在页面上点。这样能挂到定时任务里做定期自查。# 自定义管理命令批量扫描配置好的目标列表 python manage.py scan_targets --file targets.txt --output report.json--file指定目标清单--output指定结果导出路径方便接入 CI 或定时脚本。写这个命令时把扫描逻辑封装成可复用函数命令里只做参数解析和循环调用逻辑和入口分离后面改起来不牵连。验证规则是否有效最直接的办法是准备一组「已知答案」的测试用例哪些 URL 有注入、哪些有 XSS跑完看命中率。命中率低就调 pattern误报高就加验证请求。这套流程走顺之后你手里就不只是一个下载来的源码包而是一份能持续维护的检测清单。从那以后我每次拿到新的扫描类项目都强制先用靶场跑一轮基线确认规则命中率再上真实目标这个习惯帮我省掉了不少返工。希望帮到你。本文还有配套的精品资源点击获取
返回列表