Tayyabjavedofficial/cybershield

GitHub: Tayyabjavedofficial/cybershield

CyberShield 是一款基于 Flask 的信息安全 Web 应用,提供 AI 钓鱼邮件检测和防御性 Web 漏洞扫描功能。

Stars: 0 | Forks: 0

## title: CyberShield emoji: 🛡️ colorFrom: blue colorTo: indigo sdk: docker app_port: 7860 pinned: false # CyberShield: 基于 AI 的钓鱼邮件检测器与 Web 漏洞扫描器 CyberShield 是一款信息安全 Web 应用,旨在识别社会工程学钓鱼威胁,并扫描目标 Web 系统以发现关键漏洞。 本代码库代表**里程碑 1**:项目的基础框架。 ## 已完成功能(里程碑 1) 1. **模块化架构**:简洁、生产就绪的目录布局,将路由、模型、实用工具、模板和静态资源分离开来。 2. **安全注册与登录**:后端进行自定义验证(检查空字段、格式验证和密码冲突),前端进行动态密码验证检查。 3. **数据库集成与种子数据填充**:使用 SQLAlchemy 自动设置 SQLite 数据库。在首次运行时为默认管理员档案植入数据。 4. **基于角色的访问控制**:路由保护确保只有经过身份验证的用户才能访问用户控制台,并严格阻止非管理员账户加载管理员日志。 5. **现代网络安全 UI**:丰富的深色主题样式,采用毛玻璃效果卡片、发光边框阴影、响应式网格面板和流畅的滑入式微动画。 6. **路线图占位符**:用于扫描器、邮件检测器、报告和日志的可扩展模板骨架。 ## 技术栈 * **语言**:Python 3.x * **Web 框架**:Flask * **数据库与 ORM**:SQLite & SQLAlchemy * **身份验证**:Flask-Login * **密码加密**:Werkzeug 安全密码哈希 (scrypt) * **前端**:HTML5、CSS3(自定义样式)、JavaScript (ES6)、Bootstrap 5(布局网格) ## 安装与设置 在 Windows 终端中按照以下确切步骤在本地设置项目: 1. **克隆或导航**至项目仓库文件夹: cd "d:\UNIVERSITY-STUFF\4TH SEMESTER\INFORMATION SECURITY\SEMESTER PROJECT\Development" 2. **创建虚拟环境**: python -m venv venv 3. **激活虚拟环境**: venv\Scripts\activate 4. **安装所需依赖包**: pip install -r requirements.txt 5. **启动应用**: python app.py 6. 打开浏览器并访问: http://127.0.0.1:5000/ ## 默认管理员访问权限 启动时,如果缺少默认管理员用户,CyberShield 会自动生成该用户: * **邮箱**:`admin@cybershield.com` * **密码**:通过 `ADMIN_PASSWORD` 环境变量设置。如果未设置,将在首次运行时生成并打印一个随机临时的密码到控制台——**请立即更改**。(在里程碑 1 期间植入的旧数据库可能仍在使用旧版 `Admin@123`;在任何实际部署之前请轮换该密码。) ## 里程碑 2 — 基于 AI 的钓鱼邮件检测器 里程碑 2 在里程碑 1 的基础上增加了一个可用的钓鱼检测模块。已登录的用户粘贴可疑的邮件/消息文本,系统会对其进行分析,给出包含原因的透明风险评分,保存结果,并允许用户查看他们的扫描历史。 ### 功能 * **钓鱼检测器页面** (`/phishing-detector`) — 粘贴消息文本以及可选的发件人邮箱,然后点击 **Analyze Email**。 * **基于规则的检测引擎** (`utils/phishing_analyzer.py`) — 关键词、URL、发件人和社会工程学分析。无网络调用,无代码执行,完全可进行单元测试。 * **透明风险评分**,提供 0–100 分的打分和解释性判定。 * **扫描历史** (`/scan-history`) — 每个用户只能看到自己的扫描记录。 * **扫描详情** (`/scan/`) — 完整的明细,受所有权检查保护,因此用户无法通过更改 URL 来读取他人的扫描记录。 * **管理员控制台** — 包含总钓鱼扫描次数、低/中/高/严重风险等级的细分,以及所有用户的最新扫描记录。 * **适配 ML 的结构** (`ml/`) — 占位符预测器和训练脚本骨架,以便日后无需修改路由即可添加模型。 ### 钓鱼检测工作原理 分析器会检查四个方面: 1. **可疑关键词** — 诸如 *"verify your account"*、*"account suspended"*、*"you have won"* 等短语。 2. **URL** — 通过正则表达式提取,然后检查 HTTP(非 HTTPS)、URL 缩短服务(bit.ly、tinyurl.com、t.co 等)、原始 IP 地址主机以及可疑的域名模式(punycode、大量的子域名/连字符/数字)。 3. **发件人邮箱** — 格式有效性、免费邮箱提供商的使用以及可疑的本地部分/域名模式。 4. **社会工程学线索** — 紧迫感/恐惧、奖励诱饵、凭据请求、付款请求和账号关闭威胁。 ### 风险评分 每个指标都会加分(在 `phishing_analyzer.py` 中透明且可调): | 指标 | 分数 | |---|---| | 可疑关键词(每个,上限 40 分) | +10 | | HTTP(不安全)链接 | +15 | | 缩短的 URL | +20 | | IP 地址 URL | +25 | | 凭据请求 | +20 | | 紧迫感/恐惧语言 | +15 | | 付款请求 | +15 | | 奖励/奖品诱饵 | +10 | | 账号关闭威胁 | +15 | | 可疑发件人 | +15 | | 多个 URL | +10 | | 可疑域名模式 | +20 | 总分上限为 **100**,并映射到相应的风险等级: | 分数 | 风险等级 | 分类 | |---|---|---| | 0–30 | 低 | 可能安全 | | 31–60 | 中 | 可疑 | | 61–80 | 高 | 极有可能是钓鱼 | | 81–100 | 严重 | 检测到钓鱼 | ### 新增数据库表:`phishing_scans` | 列 | 描述 | |---|---| | `id` | 主键 | | `user_id` | 外键 → `users.id`(每次扫描属于一个用户) | | `message_preview` | 消息的前 200 个字符(**不**存储全文) | | `sender_email` | 可选发件人地址 | | `extracted_urls` | 找到的 URL 的 JSON 列表 | | `suspicious_keywords` | 匹配关键词的 JSON 列表 | | `risk_score` | 0–100 | | `risk_level` | 低 / 中 / 高 / 严重 | | `classification` | 判定字符串 | | `reasons` | 解释说明的 JSON 列表 | | `recommendation` | 建议文本 | | `created_at` | UTC 时间戳 | 该表会在启动时自动创建(`db.create_all()`);不需要执行迁移命令。 ### 如何测试钓鱼检测器 1. 运行应用并登录(或注册一个新用户)。 2. 从控制台中打开 **Phishing Detector**。 3. 粘贴一条示例消息,然后点击 **Analyze Email**。 4. 查看结果,然后打开 **History** 查看保存的扫描记录。 **示例钓鱼输入**(预期结果:高/严重): ``` Sender: support@paypal-secure12.com Urgent action required: your account will be closed. Verify your account immediately and confirm your identity here: http://bit.ly/abc123 ``` **示例安全输入**(预期结果:低 — 可能安全): ``` Hi Sam, are we still on for the 3pm project sync tomorrow? I pushed the latest slides to our shared drive. Thanks! ``` ### 手动测试用例(里程碑 2) | # | 场景 | 预期结果 | |---|---|---| | 1 | 空消息 | 闪现错误提示,无崩溃 | | 2 | 安全消息 | 低 / 可能安全 | | 3 | 包含可疑关键词的消息 | 分数上升,列出关键词 | | 4 | 包含 HTTP URL 的消息 | 显示“不安全的 HTTP 链接”原因 | | 5 | 包含缩短 URL 的消息 | 显示“缩短的 URL”原因 | | 6 | 包含基于 IP 的 URL 的消息 | 显示“原始 IP 地址”原因 | | 7 | 请求密码/登录的消息 | 显示“凭据/身份”原因 | | 8 | 可疑发件人邮箱 | 发件人被标记,加分 | | 9 | 超长输入(>1万字符) | 被拒绝并闪现提示,无崩溃 | | 10 | 用户查看自己的扫描记录 | 200 正常,显示详情 | | 11 | 用户打开其他用户的扫描 URL | **403 Forbidden**(阻止 IDOR) | | 12 | 管理员控制台 | 显示总计 + 风险细分 + 最新扫描 | ### 本模块的安全注意事项 * 所有钓鱼路由都需要 `login_required`。 * 扫描详情执行**所有权检查**:对于缺失*或*不属于当前用户的扫描记录,将返回 **404**(管理员可以查看任何记录)。对这两种情况都返回 404 可以防止 IDOR *和* 扫描 ID 枚举。 * 用户输入永远不会被执行或 `eval`;输出由 Jinja2 自动转义(无 `|safe`)。提取的 URL 显示为**纯文本,绝不可点击**。 * 仅持久化存储简短的消息预览(≤200 个字符),不存储完整消息。 * 输入有长度限制:消息 ≤ 10,000 个字符,发件人邮箱 ≤ 254 个字符。 * POST 表单包含 CSRF token(Flask-WTF),与里程碑 1 保持一致。 * 分析使用 **Post/Redirect/Get** 模式:成功的扫描会重定向到其详情页,因此刷新结果永远不会重复提交或产生重复的扫描记录。 ### 安全修复与加固(里程碑 2 QA 审计) 在 QA/安全测试期间发现了以下问题,并已修复。 `tests/` 中的回归测试锁定了修正后的行为。 | ID | 严重程度 | 问题 | 修复 | |----|----------|-------|-----| | F1 | 中 | 格式错误的 URL(例如 `http://[[[`)在 `urlparse` 中引发 `ValueError` → 500 崩溃 | 在 `phishing_analyzer._hostname()` 和 `url_guard.validate_scan_url()` 中实现崩溃安全的解析 | | F2 | 中 | 真实的钓鱼样本评分过低(落入*中等*而非*高/严重*) | 已校准:免费提供商冒充发件人、额外的短语变体、奖励+链接组合 | | F3 | 低 | 对于缺失的记录详情路由返回 404,但对于“不属于您”的记录返回 403,泄露了哪些扫描 ID 存在 | 对于缺失和未授权的情况均返回 **404** | | F4 | 低 | 历史记录页加载了所有行(无分页) | `.paginate(per_page=10, error_out=False)` + 可复用的控件 | | N1 | 低-中 | `sender_email` 没有长度限制;100k 字符的地址被接受/存储 | 拒绝大于 254 字符的发件人(RFC 5321);不回显超大的值 | | N2 | 低 | 刷新结果页重新提交表单 → 产生重复扫描 | 对扫描详情页采用 Post/Redirect/Get | **已验证安全防范:** XSS(`` 已转义)、模板注入(`{{7*7}}` 未被求值)、类 SQL 输入(`' OR '1'='1` 通过 ORM 失效)、超大输入以及无效/格式错误的发件人和 URL。已检查电子邮件验证正则表达式是否存在 ReDoS(100k 字符处理耗时约 0.02 秒)。 ### 运行测试 ``` python -m unittest discover -s tests -v ``` 34 项测试覆盖了钓鱼引擎(样本分类、评分边界、关键词/URL 检测、崩溃安全性、误报安全性)和 Web 扫描器(安全态势评级 + SSRF 拒绝)。无需网络访问。 ## 里程碑 3 — Web 漏洞扫描器 一个**安全、防御性、教育性**的 Web 漏洞扫描器。已登录的用户确认授权后,提交一个 URL,应用会安全地获取页面,检查其是否存在常见弱点,对风险进行评分,并保存结果。 ### 功能 * **Web 扫描器页面** (`/web-scanner`) — URL 字段 + **授权复选框**(“我确认我拥有此网站或有权对其进行扫描”) + **Scan Website**。 * **扫描器引擎** (`utils/web_scanner.py`) — 获取 + 分析,与路由分离,无需网络即可进行单元测试。使用 **BeautifulSoup** 进行表单解析。 * **SSRF 保护** — 每个请求(以及每个重定向跳转)都由 `utils/url_guard.py` 验证。私有局域网、链路本地和云元数据地址始终被阻止。**出于本地测试目的,允许访问 Localhost/127.0.0.1(任意端口)**,但仅限首次请求 — 重永远无法到达内部地址。请求具有超时限制、重定向限制和响应大小限制。 * **扫描历史** (`/web-scan-history`) 和 **详情** (`/web-scan/`) — 每个用户只能看到自己的扫描记录;详情路由对于缺失*或*未授权的 ID 返回 **404**(无 IDOR,无枚举)。 * **Post/Redirect/Get** — 成功的扫描会重定向到其详情页,因此刷新永远不会重新扫描或产生重复记录。 * **管理员控制台** — 总 Web 扫描次数、低/中/高/严重风险的细分,以及所有用户的最新扫描记录。 ### 检查项与分数 | 检查项 | 严重程度 | 分数 | |---|---|---| | 无 HTTPS(明文 HTTP) | 高 | +20 | | 缺少 Content-Security-Policy | 中 | +15 | | 缺少 X-Frame-Options | 中 | +10 | | 缺少 X-Content-Type-Options | 低 | +10 | | 缺少 Strict-Transport-Security(在 HTTPS 上) | 中 | +10 | | 缺少 Referrer-Policy | 低 | +5 | | 缺少 Permissions-Policy | 低 | +5 | | 暴露 Server 标头 | 低 | +5 | | 暴露 X-Powered-By | 低 | +10 | | 密码字段通过 HTTP 提供 | 严重 | +25 | | 非 HTTPS 页面上的表单 | 中 | +10 | | SQL 注入风险指标 | 中 | +20 | | XSS 风险指标 | 中 | +20 | | 目录列表("Index of /") | 高 | +25 | 分数上限为 **100**,并映射为:**低**(基本安全)、**中**(需要改进)、**高**(易受攻击)、**严重**(极易受攻击)。 扫描器还会解析表单(数量、方法、密码字段),检查 **SQL 注入风险指标**(响应中的数据库错误字符串、查询参数、登录/文本表单)和 **XSS 风险指标**(反射的查询参数、自由文本表单、缺少 CSP) — 全部为**被动**方式进行,绝不发送 payload。 ### 新增数据库表:`web_scans` `id`、`user_id`(外键)、`target_url`、`final_url`、`https_status`、`status_code`、`missing_headers`(JSON)、`exposed_headers`(JSON)、`forms_found`、`sql_risk_indicators`(JSON)、`xss_risk_indicators`(JSON)、`directory_listing`、`risk_score`、`risk_level`、`classification`、`findings`(包含 {title、severity、detail、recommendation} 的 JSON 列表)、`recommendation`、`created_at`。 启动时自动创建。幂等的启动迁移(`app.py` 中的 `_migrate_web_scans_columns`)会在不丢失数据的情况下将里程碑 3 的列添加到现有数据库中。**永远不会存储完整的 HTML** — 仅存储结构化的发现结果。 ### 如何测试 Web 扫描器 1. 登录并从控制台打开 **Web Scanner**。 2. 勾选授权复选框。 3. 输入您控制或被允许测试的站点,例如 `https://example.com`,或者本地项目如 `http://localhost:5000/` 或 `http://127.0.0.1:8000/`。 4. 查看发现结果/分数,然后在 **History** 下(以及主扫描历史页面的“Recent Web Scans”下)查看它们。 尝试 SSRF 防护:`http://169.254.169.254/`(云元数据)和 `http://192.168.1.50/`(私有局域网)将被拒绝,且永远不会被抓取。如果未勾选授权框,扫描将被拒绝。 ### 手动测试用例(Web 扫描器) | # | 场景 | 预期结果 | |---|---|---| | 1 | 空的 URL | 闪现错误提示,无崩溃 | | 2 | 不带 http(s):// 的 URL | 被拒绝(“必须以 http:// 或 https:// 开头”) | | 3 | 超长 URL(>500 字符) | 被拒绝 | | 4 | `http://169.254.169.254/`(元数据) | 被 SSRF 防护拒绝 | | 5 | `http://192.168.1.50/`(私有局域网) | 被 SSRF 防护拒绝 | | 6 | `http://localhost:5000/` | 被允许(本地测试) | | 7 | 具有良好标头的 HTTPS 站点 | 低 / 基本安全 | | 8 | HTTP 站点 / 缺失标头 / 密码表单 | 高-严重,并附带发现结果 | | 9 | 无法访问的主机 | 友好的“Could not connect”提示信息 | | 10 | 未勾选授权进行扫描 | 被拒绝并伴随闪现消息 | | 11 | XSS / `{{7*7}}` / 类似 SQL 的 URL 输入 | 安全处理,转义,无执行 | | 12 | 打开其他用户的 `/web-scan/` | **404**(无 IDOR/枚举) | | 13 | 未登录用户打开 `/web-scanner` | 重定向至登录页 | ## 未来路线图(里程碑 4+) * **ML 模型集成**:训练 `ml/train_model.py`,放入 `.pkl` 文件,并在 `phishing_analyzer.py` 中已记录的 ML 钩子处混合预测。 * **PDF 报告生成器**:生成静态合规报告。 * **可选的主动扫描器模式**(仅限已授权目标):在明确的同意控制下进行端口/Banner 和更深层次的检查。 ## 当前项目状态 | 领域 | 状态 | |------|--------| | 里程碑 1 — 认证、RBAC、控制台、数据库 | ✅ 完成并已加固 | | 里程碑 2 — 钓鱼邮件检测器 | ✅ 完成,经过 QA 审计(修复了 F1–F4、N1–N2) | | 里程碑 3 — Web 漏洞扫描器 | ✅ 完成(授权网关、表单、SQL/XSS 指标、目录列表) | | 回归测试套件 (`tests/`) | ✅ 40 项测试通过 | | ML 模型 | ⏳ 钩子已建立,尚未训练 | | PDF 报告 | ⏳ 仅占位符页面 | ### 已知的局限性 * **基于规则的检测** — 钓鱼评分是启发式的(目前没有训练过的 ML);它可能会遗漏新颖的措辞,或者偶尔对边界情况打分过高/过低。 * **风险权重是启发式的**,基于样本集进行调优,未通过标记数据集进行统计学验证。 * **Web 扫描器在设计上是被动**的 — 它检查标头、表单和*风险指标*(数据库错误字符串、反射参数);它不发送 payload 或确认可利用性。SQL/XSS 的结果是供审查的线索,而非确凿的证据。 * **Localhost 扫描**由 `SCANNER_ALLOW_LOCAL` 设置控制(出于本地测试目的,默认**开启**)。在任何共享/托管部署上请设置 `SCANNER_ALLOW_LOCAL=False`,以防用户探测主机的 loopback 服务。 私有局域网、链路本地和云元数据地址始终被阻止。 * **DNS 重绑定**通过 IP 绑定得到了缓解:非 loopback 的主机名会被解析并验证一次,然后该 IP 将被绑定到连接中(原始主机名仍用于 TLS SNI/证书验证)。此绑定在单个请求的短暂持续时间内对全进程打补丁修改 `socket.getaddrinfo`,这对于单用户的教育工具来说是可以接受的,但在高并发的服务中需要建立基于单连接的绑定。 * **时间戳以 UTC 格式存储和显示。** * **分析 endpoint 没有速率限制**(通过登录要求有所缓解;`Flask-Limiter` 是后续里程碑的候选方案)。 * **开发环境的 `SECRET_KEY`** 在未设置时会在每次运行时随机生成 — 在任何实际部署中,请在环境中设置 `SECRET_KEY` 以确保会话稳定。
标签:CISA项目, Flask, Python, Splunk, SQLite, 无后门, 请求拦截, 逆向工具, 钓鱼检测