ARTICLE DETAIL

资讯详情

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

Django自动化Web漏洞扫描系统:从部署到自定义规则库实战

Django自动化Web漏洞扫描系统:从部署到自定义规则库实战 简介这是一套面向网络安全初学者与渗透测试人员的Web漏洞扫描系统源码基于Python与Django开发集成爬虫引擎与自定义规则库可对静态页面和动态交互式Web应用进行深度安全扫描、漏洞发现与风险评估。资源包共202个文件约1.16MB以118个Python源码文件为核心配合20个HTML模板、9个JavaScript脚本与7个CSS样式构建前端界面另含3个SQL脚本、sqlite3数据库、pem证书及dic字典文件并附漏扫使用说明文档便于快速部署与二次开发。系统提供任务管理、结果查看与安全评估报告生成功能支持自定义扫描规则、扫描速度与频率控制及身份验证机制模块化设计便于扩展和与其他安全工具集成。目前已有91人学习下载适合用于课程设计、毕业设计或安全测试实践参考。1. 从一份 Django 扫描器源码包说起它能替你跑完哪些安全巡检很多做 Web 开发的朋友都有过这种经历项目上线前心里没底手工点一遍登录、表单、参数测出来的问题全靠记忆下次换个项目又得重来。这份基于 Python 与 Django 构建的自动化 Web 应用漏洞扫描与安全检测系统解决的正是这个重复劳动问题。它把爬虫引擎、漏洞检测模块和自定义规则库打包成一个可运行的 Web 平台你部署起来后输入目标站点地址它就能自动抓取页面、识别参数入口、按规则匹配常见风险最后把结果汇总成报告。适合谁用一是需要做内部安全自查的后端和运维二是想学 Django 实战又不想只写博客 demo 的人三是安全方向的学生拿来做课程设计或毕业设计。它不是一个商业级扫描器但胜在结构清晰、规则可改、代码可读你能顺着它的流程把「扫描」这件事拆明白。下面我按实际拆包和跑通的顺序把这份资源从部署到改规则再到排错讲一遍。2. 环境搭建与项目启动把 Django 扫描器跑起来2.1 依赖清单与 Python 版本选择拿到源码包后第一件事不是急着runserver而是先确认 Python 版本和依赖。这类 Django 项目通常对版本有隐性要求用错版本会出现ImportError或者数据库迁移失败。我一般会先看requirements.txt和manage.py里的语法特征判断它大概是什么年代的项目。常见做法是建一个独立虚拟环境避免污染系统 Python。如果你机器上还没有 Python装 3.8 到 3.10 之间比较稳妥太新的 3.12 有时会让老版本 Django 的某些依赖编译不过。# 创建虚拟环境python3 -m venv 是标准做法 python3 -m venv venv # 激活虚拟环境Linux/macOS 用 sourceWindows 用 venv\Scripts\activate source venv/bin/activate # 升级 pip避免装包时因 pip 过旧报错 pip install --upgrade pip # 安装项目依赖-r 指定依赖文件 pip install -r requirements.txt这里venv是虚拟环境目录名你可以改成任何名字。requirements.txt里一般会列出 Django、requests、beautifulsoup4、lxml 这类包爬虫引擎依赖 requests 发请求、BeautifulSoup 或 lxml 解析 HTML。如果安装过程中卡在某个包编译上多半是缺少系统级依赖比如 lxml 需要 libxml2 开发库Ubuntu 下补一句sudo apt install libxml2-dev libxslt-dev即可。提示不要用pip install django单独装最新版覆盖依赖文件里的版本版本不一致是后面很多玄学报错的根源。2.2 数据库配置与迁移Django 项目默认用 SQLite这对扫描器来说够用因为扫描结果数据量不会特别大。但如果你打算长期跑、存大量扫描记录换成 MySQL 或 PostgreSQL 更稳。配置在settings.py的DATABASES段。# settings.py 片段SQLite 配置 DATABASES { default: { ENGINE: django.db.backends.sqlite3, # 数据库引擎 NAME: BASE_DIR / db.sqlite3, # 数据库文件路径 } }如果换 MySQL把 ENGINE 改成django.db.backends.mysql再补上 NAME、USER、PASSWORD、HOST、PORT 五个字段同时确保装了mysqlclient或pymysql。改完配置后执行迁移# 生成迁移文件--noinput 表示不交互 python manage.py makemigrations --noinput # 应用迁移创建数据库表结构 python manage.py migrate # 创建后台管理员账号用于登录 Django admin 查看扫描记录 python manage.py createsuperusermakemigrations负责把模型类翻译成数据库变更脚本migrate才真正执行。如果这一步报No changes detected说明模型没被正确注册到 app 的models.py检查一下 app 是否加进了INSTALLED_APPS。createsuperuser会让你输入用户名、邮箱和密码这个账号后面登录扫描平台后台用得上。2.3 启动服务与首次访问迁移完成后就可以启动开发服务器# 0.0.0.0 让局域网内其他机器也能访问8000 是端口 python manage.py runserver 0.0.0.0:8000浏览器打开http://127.0.0.1:8000正常会看到扫描平台的首页或登录页。如果页面报TemplateDoesNotExist说明模板目录没配好检查settings.py里的TEMPLATES配置和DIRS路径。如果静态文件 404开发模式下需要在settings.py里确认DEBUG True生产环境则要配STATIC_ROOT并跑collectstatic。首次访问建议先登录 admin 后台看看有没有预置的规则库数据。很多这类项目会把规则以 fixture 或初始数据的形式提供如果没有就需要手动导入或通过后台添加。规则库是扫描器的核心下一章专门讲。3. 爬虫引擎与规则库扫描流程的核心机制3.1 爬虫引擎是怎么抓取目标站点的这份资源的爬虫引擎不是简单的requests.get循环它一般包含 URL 去重、深度控制、表单解析和链接提取几个部分。理解它的工作方式你才能知道为什么有些页面扫不到、有些参数识别不出来。典型流程是从起始 URL 入队取出一个 URL 发请求解析 HTML提取其中的a链接和form表单把新链接去重后入队直到队列空或达到最大深度。表单解析尤其关键因为漏洞检测大多针对输入参数爬虫必须把表单的 action、method 和所有 input 字段名提取出来才能构造检测请求。# 爬虫核心逻辑示意基于 requests BeautifulSoup import requests from bs4 import BeautifulSoup from urllib.parse import urljoin, urlparse def crawl(start_url, max_depth3): visited set() # 已访问 URL 集合用于去重 queue [(start_url, 0)] # 队列元素为 (url, 当前深度) forms [] # 收集到的表单信息 while queue: url, depth queue.pop(0) if url in visited or depth max_depth: continue visited.add(url) try: # timeout 防止目标站点不响应导致卡死 resp requests.get(url, timeout5) except requests.RequestException: continue soup BeautifulSoup(resp.text, lxml) # 提取表单记录 action 和所有 input 的 name for form in soup.find_all(form): 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)] forms.append({action: action, method: method, inputs: inputs}) # 提取链接并入队 for a in soup.find_all(a, hrefTrue): next_url urljoin(url, a[href]) # 只抓同域链接避免爬到外站 if urlparse(next_url).netloc urlparse(start_url).netloc: queue.append((next_url, depth 1)) return formsmax_depth控制爬取深度设太大容易在大型站点上跑很久设太小又可能漏掉深层页面一般 3 层够用。timeout5是必须的否则遇到不响应的站点整个扫描会挂住。urljoin负责把相对链接拼成绝对链接urlparse用来判断是否同域。这段逻辑和项目里的爬虫模块思路一致你可以对照源码看它多了哪些处理比如是否支持 POST 表单提交、是否处理 JavaScript 渲染的链接。3.2 自定义规则库的结构与匹配方式规则库决定了扫描器能发现哪些问题。这类项目通常把规则存成数据库记录或 JSON 文件每条规则包含匹配位置、匹配模式、风险等级和描述。匹配位置可能是响应体、响应头或 URL 参数匹配模式多是正则表达式。一个典型的规则结构长这样字段含义示例name规则名称SQL 注入特征检测location检测位置body / header / urlpattern正则匹配模式(union\sselectseverity风险等级high / medium / lowdescription风险说明响应中出现 SQL 注入特征规则匹配的代码逻辑一般是在爬虫拿到响应后遍历规则库对指定位置做正则搜索import re def match_rules(response_text, rules): findings [] for rule in rules: # re.IGNORECASE 让匹配不区分大小写 if re.search(rule[pattern], response_text, re.IGNORECASE): findings.append({ rule: rule[name], severity: rule[severity], description: rule[description] }) return findingsre.IGNORECASE很重要因为很多注入特征的写法大小写混杂。规则库的扩展性就体现在这里你不需要改扫描引擎代码只要往规则表里加一条记录扫描器下次运行就会用上新规则。这也是这份资源比固定规则扫描器更实用的地方。3.3 扫描任务的下发与结果落库在 Django 里扫描任务通常由一个视图函数接收表单提交的目标 URL然后调用爬虫和规则匹配模块最后把结果写入数据库。为了不阻塞 Web 请求常见做法是用 Celery 异步执行但简单版本可能直接同步跑。# views.py 中的扫描视图示意 from django.shortcuts import render from .models import ScanResult from .crawler import crawl from .scanner import match_rules def scan_view(request): if request.method POST: target request.POST.get(target_url) forms crawl(target) # 爬取目标站点 rules load_rules_from_db() # 从数据库加载规则 results [] for form in forms: resp send_test_request(form) # 对表单发起检测请求 findings match_rules(resp.text, rules) results.extend(findings) # 批量写入数据库减少 IO 次数 ScanResult.objects.bulk_create([ ScanResult(targettarget, rule_namer[rule], severityr[severity], descriptionr[description]) for r in results ]) return render(request, result.html, {results: results}) return render(request, scan.html)bulk_create比逐条save()快很多扫描结果多的时候差别明显。load_rules_from_db每次扫描都重新加载规则保证你新加的规则立即生效。结果页一般会按风险等级排序high 在前方便你先处理严重问题。4. 避坑与排查跑扫描器时最容易翻车的几个地方4.1 扫描目标无响应导致任务卡死现象点了开始扫描后页面一直转圈后台日志停在某条请求上不动。原因爬虫发请求时没设超时或者目标站点响应极慢。解决给所有requests调用加timeout参数并在爬虫循环里加异常捕获单条请求失败就跳过不要让整个任务挂掉。我一般还会加一个总耗时上限超过就主动终止。4.2 规则误报太多把真实问题淹没现象扫描结果里几百条 low 风险翻半天找不到真正要紧的。原因规则 pattern 写得太宽泛比如用error这种词做匹配正常页面也会命中。解决收紧正则尽量匹配具体特征组合同时给规则分级结果页默认只展示 medium 以上。定期回顾误报规则该删就删。4.3 数据库迁移报 no such table现象migrate显示成功但访问页面报no such table: scanner_scanresult。原因模型所在的 app 没加入INSTALLED_APPSDjango 根本没为它生成迁移。解决检查settings.py的INSTALLED_APPS把 app 名加进去重新makemigrations和migrate。如果之前已经生成过错误的迁移文件先删掉 app 下migrations目录里除__init__.py外的文件再重来。4.4 爬虫陷入无限循环现象扫描任务跑很久不结束日志里同一个 URL 反复出现。原因URL 去重没做好或者站点通过参数生成无限多相似页面。解决用visited集合严格去重同时对 URL 做规范化处理比如去掉末尾斜杠、统一大小写、过滤掉 session id 这类无意义参数。深度限制也要设别让它无限爬下去。4.5 静态文件 404 导致页面样式全丢现象功能能用但页面没样式控制台一堆 404。原因DEBUG False时 Django 不再自动服务静态文件。解决开发阶段保持DEBUG True部署时配好STATIC_ROOT跑python manage.py collectstatic再由 Nginx 或 WhiteNoise 托管静态文件。5. 进阶玩法把规则库和扫描流程改成你自己的跑通默认流程只是开始这份资源真正的价值在于你能按自己的需求改。我一般会从两个方向下手一是扩充规则库二是把扫描结果接到现有工作流里。扩充规则库最直接的方式是往数据库或规则文件里加记录。比如你想检测响应头里是否缺少X-Frame-Options可以加一条 location 为 header、pattern 匹配缺失特征的规则。更灵活的做法是写一个规则生成脚本把常见的安全基线批量导入# 批量导入安全基线规则的脚本示意 import json from scanner.models import Rule baseline_rules [ { name: 缺失 X-Frame-Options, location: header, pattern: r^(?!.*X-Frame-Options).*$, # 负向匹配头里没有该字段 severity: medium, description: 响应头未设置 X-Frame-Options存在点击劫持风险 }, { name: 缺失 Content-Security-Policy, location: header, pattern: r^(?!.*Content-Security-Policy).*$, severity: medium, description: 未设置 CSPXSS 防护不足 }, ] for r in baseline_rules: Rule.objects.get_or_create(namer[name], defaultsr)get_or_create保证重复执行不会插入重复规则defaults里的字段只在新建时使用。负向匹配^(?!.*X-Frame-Options).*$的意思是整段文本里不包含该字段就命中用来检测缺失项。这类规则补进去后扫描器就不只是找注入特征还能做基础的安全配置检查。另一个进阶方向是把扫描结果导出成 JSON 或 CSV接到 CI 流程里。比如每次上线前自动跑一次扫描发现 high 风险就阻断发布。实现上可以在扫描视图里加一个导出接口或者写一个管理命令python manage.py scan_and_report --target https://example.com在流水线里调用。管理命令的好处是不依赖 Web 界面适合自动化。验证扫描器是否靠谱我的习惯是搭一个故意有漏洞的测试靶站比如本地跑一个包含 SQL 注入点和缺失安全头的页面看扫描器能不能稳定命中。如果靶站都扫不出来说明规则或爬虫有问题先修这个再上真实站点。从那以后我每次改完规则都强制拿靶站跑一遍回归确认没有把已有检测能力改坏。希望帮到你。本文还有配套的精品资源点击获取
返回列表