Amit-Cohen10/Credential-Stuffing-Attack-Detection

GitHub: Amit-Cohen10/Credential-Stuffing-Attack-Detection

基于53万条真实登录数据的凭据填充攻击检测分析项目,综合运用启发式规则与统计异常检测方法(z-分数、IQR、Shannon熵),通过分层置信度评分识别恶意流量并导出泄露凭据列表。

Stars: 0 | Forks: 0

# HW1 — 凭据填充攻击检测 **课程:** 3917 — 恶意软件检测中的 AI 技术 **学期:** 2 / 2026 **学生:** Amit Cohen (318556016) · Sagi Levhar (206590457) ## 本次作业的内容 我们获得了一个包含约 53 万次登录尝试的真实数据集,这些数据是在活跃的 凭据填充攻击期间捕获的。目标是: 1. 通过探索性分析理解数据 (A 部分) 2. 为 IP、电子邮件、工具和网络构建特征表 (B 部分) 3. 设计我们自己的启发式检测规则,并将每一行标记为恶意/合法 (C 部分) 4. 应用统计异常检测——z-分数、IQR 围栏、Shannon 熵——并 将它们组合成分层置信度分数 (D 部分) 5. 撰写一份安全团队可以实际阅读的简短攻击分析报告 (E 部分) 6. 三项附加分析:时间突发检测、国家×工具热力图、创新特征 (附加题) ## 本次提交的文件 | 文件 | 说明 | |---|---| | `HW1_Credential_Stuffing.ipynb` | 主 notebook——包含所有代码、图表和书面回答 | | `helpers.py` | 被 notebook 导入的共享辅助函数(熵、z-分数、IQR、绘图工具) | | `assignment_labeled.csv` | 添加了两个新列的原始数据集:`is_malicious` (C 部分) 和 `is_malicious_refined` (D 部分) | | `compromised_credentials.csv` | 至少有一次成功登录(状态 200)且被标记为恶意的电子邮件——“泄露凭据”列表 | | `figures/` | 保存为 PNG 格式的全部 23 张图表(运行 notebook 时自动创建) | ## 如何运行 ``` pip install pandas numpy matplotlib seaborn scipy upsetplot ``` 然后在 Jupyter 中打开 `HW1_Credential_Stuffing.ipynb` 并执行: **Kernel → Restart & Run All** 在运行之前,请确保 `assignment.csv` 与 notebook 位于同一文件夹中。 在普通笔记本电脑上的总运行时间约为 30 秒。 一切都是可复现的——`RANDOM_STATE = 42` 在 notebook 和 `helpers.py` 的顶部均已设置,并传递给每个接受它的操作。 ## 关键结果(简要总结) | 指标 | 值 | |---|---| | 总登录尝试次数 | 530,816 | | 标记为恶意的(C 部分启发式) | 323,614 (61.0 %) | | 精炼后的恶意标签(D 部分分层) | 308,487 (58.1 %) | | 独立攻击 IP 数 | 见 notebook 中的 E.1 | | 发现的泄露凭据 | 22,813 个电子邮件账户 | `risk_indication` 供应商标签将大约 59% 的流量标记为有风险,这个比例太高了, 无法作为真实的基准数据使用。这正是我们在 C 部分构建自己的检测器, 并在 D 部分通过统计学方法对其进行交叉验证的原因。 ## 问题索引 —— PDF 中每个问题的解答位置 使用此表可直接跳转到任何答案。每个答案在 notebook 中都有一个类似 `**Answer to X.Y QZ —` 的标题,因此也可以使用 Ctrl+F 进行查找。 | PDF 问题 | 问题内容 | Notebook 章节 | 要查找的单元格/标题 | |---|---|---|---| | **A.1 Q3** | 每个 HTTP 状态码可能代表什么 | Part A → A.1 | `A1_status_dist` + 其下方的 markdown | | **A.2 Q1** | 数据集的准确时间范围 | Part A → A.2 | `A2_time_range` + markdown | | **A.2 Q2** | 是否存在流量突发?(>2× 中位速率) | Part A → A.2 | `A2_per_minute` + markdown | | **A.2 Q3** | `risk_indication` 的划分说明了什么? | Part A → A.2 | `A2_per_minute_split` + markdown | | **A.3 Q1** | 哪些国家看起来可疑以及原因 | Part A → A.3 | `A3_countries` + markdown | | **A.3 Q2** | 哪些工具具有接近 100% 的风险率 | Part A → A.3 | `A3_tools` + markdown | | **A.3 Q3** | 每个 IP 邮件数阈值的合理性依据 | Part A → A.3 | `A3_emails_per_ip` + markdown | | **B.1 Q** | 为什么需要 IP 级别特征?何时会失效? | Part B → B.1 | `B1_ip_features` 之后的 markdown 单元格 | | **B.4 Q2** | 我们如何处理缺失的 `network_type`(77% 缺失) | Part B → B.4 | `B4_merge` 之后的 markdown | | **B.4 Q3** | 为什么对 network_type 使用独热编码,对其他使用频率编码 | Part B → B.4 | 同一个 markdown 单元格 | | **C.1 Q1–Q3** | 标签质量:标记率、按状态的交叉表、按工具的细分 | Part C → C.1 | `C1_label_quality`, `C1_tool_risk_bar` | | **C.1 Q4** | 即使供应商标签是完美的,为什么还要构建自己的检测器 | Part C → C.1 | Markdown "Answer to C.1 Q4" | | **C.2 Q1** | 4 条带有阈值及其合理性依据的检测规则 | Part C → C.2 | Markdown "Answer to C.2 Q1" | | **C.2 Q2** | 应用规则 → 生成 `is_malicious` 列 | Part C → C.2 | `C2_apply` | | **C.2 Q3** | 将我们的标签与 `risk_indication` 进行比较,差异分析 | Part C → C.2 | `C2_compare` + `C2_disagree` + markdown | | **C.2 Q4** | 规则重叠可视化(UpSet 图) | Part C → C.2 | `C2_upset` | | **D.1 Q1–Q4** | Z-分数计算,z>2 和 z>3 时的计数 | Part D → D.1 | `D1_zscores`, `D1_zscore_histograms` | | **D.1 Q5** | 这些分布真的是正态分布吗? | Part D → D.1 | Markdown "Answer to D.1 Q5" | | **D.2 Q1–Q3** | IQR 上限围栏,异常值计数,3 选 2 规则 | Part D → D.2 | `D2_iqr` | | **D.2 Q4** | 为什么在偏态数据上 IQR 比 z-分数更鲁棒 | Part D → D.2 | Markdown "Answer to D.2 Q4" | | **D.3 Q1–Q4** | 每个 IP 的 Shannon 熵,散点图,阈值选择 | Part D → D.3 | `D3_entropy`, `D3_scatter` | | **D.3 Q2** | 高邮件熵/状态熵意味着什么 | Part D → D.3 | Markdown "Answer to D.3 Q2" | | **D.3 Q5** | 重试 3 次的用户会被误认为攻击者吗? | Part D → D.3 | 同一个 markdown 单元格 | | **D.4 Q1–Q5** | 分层置信度分数 + 精炼标签 | Part D → D.4 | `D4_layered`, `D4_plots` | | **D.4 Q4** | 通过精炼去除了多少 FP / 引入了多少 FN | Part D → D.4 | Markdown "Answer to D.4 Q4" | | **D.4 Q6** | 为什么分层检测比任何单一方法更可靠 | Part D → D.4 | Markdown "Answer to D.4 Q6" | | **E.1** | 攻击汇总表 + 时间线 + 攻击量最大的 IP | Part E → E.1 | `E1_summary`, `E1_timeline`, `E1_top_attackers` | | **E.2** | 按国家、网络类型和工具划分的来源分析 | Part E → E.2 | `E2_country`, `E2_network_type`, `E2_tool_attack_rate` | | **E.3** | 泄露凭据:前 20 名表 + CSV 导出 | Part E → E.3 | `E3_compromised` | | **Bonus 1** | 使用到达时间间隔 + CV 的时间突发检测 | 附加题部分 | `BONUS_1_burst`, `BONUS_1_scatter` | | **Bonus 2** | 国家 × 工具攻击率热力图 | 附加题部分 | `BONUS_2_heatmap` | | **Bonus 3** | 三个创新特征(时间、邮件熵 KDE、工具×国家交互作用) | 附加题部分 | `BONUS_3_creative` | ## 代码结构 该 notebook 被划分为与作业评分标准相同的部分(A → E + 附加题)。 所有可复用的逻辑都存放在 `helpers.py` 中,因此没有在多个单元格间进行复制粘贴: ``` helpers.py ├── shannon_entropy(series) # Shannon entropy of a categorical Series (bits) ├── zscore(series) # Population z-score, NaN-safe ├── iqr_upper_fence(series, k=1.5) # Tukey upper fence Q3 + k*IQR ├── coefficient_of_variation(arr) # std/mean, safe for empty/zero-mean arrays ├── styled_hist(series, ax, ...) # Consistent histogram style across all plots ├── annotate_thresholds(ax, ...) # Draws labelled vertical threshold lines ├── savefig(name) # Saves to ./figures/{name}.png at 150 dpi ├── pretty_print_section(name) # Section banner in notebook output └── apply_heuristic_rules(df, ...) # Applies R1–R4 detection rules, returns df + is_malicious ``` 该 notebook 在顶部的设置单元格中使用 `from helpers import *` 导入所有内容。 ## AI 披露 **使用的工具:** Claude (Anthropic),通过 Claude Code,2026 年 4 月;OpenAI Codex, 2026 年 4 月 25 日,用于提交前的验证和小修复。 ### 我们使用的提示词(按顺序) **提示词 1 —— 在编写任何代码之前了解数据集:** **提示词 2 —— 特征工程设计:** **提示词 3 —— 启发式检测规则:** **提示词 4 —— 统计异常检测:** **提示词 5 —— 分层检测与精炼标签:** **提示词 6 —— 附加题:时间突发检测:** **提示词 7 —— 使用 OpenAI Codex 进行提交前验证:** ### 工作过程 我们阅读了作业 PDF,并将其分解为与评分标准相同的部分(A → E + 附加题)。 在最终的 Codex 验证阶段,我们检查了 ZIP 文件的完整性、notebook 的有效性、 从全新解压开始的复现性、CSV 的形状/标签,以及与 PDF 可交付成果的对齐情况。 我们根据 EDA 直方图(30 封电子邮件/IP 的拐点、1 次请求/秒的速率阈值、 大于 4 比特的熵截断值)自行设计了阈值,并使用 Claude 来搭建 辅助函数的框架、编写 matplotlib 样板代码,以及仔细检查 pandas 聚合语法的正确性。 每个阈值都针对实际的数据分布进行了验证——我们没有在没有首先运行图表 并确认经验断点的情况下接受任何“魔法数字”。 对每个 PDF 问题的 markdown 回答是由我们在运行单元格 并阅读输出后撰写的。 ### 我们学到的东西 早期让我们感到惊讶的一件事是,z-分数在这类数据上的表现有多么糟糕。 我们原以为它们能将攻击者与普通用户干净利落地分开,但由于极少数 非常活跃的机器人抬高了均值和标准差,导致阈值随之上升,许多中等活跃的攻击者 成为了漏网之鱼。切换到 IQR(Q1 和 Q3)立刻解决了这个问题—— 这些百分位数不受尾部极端值的影响,而这正是你在寻找“异常值”时 所期望的特性。 对熵的洞察则花了更长的时间才被领悟。起初我们尝试纯粹通过邮件熵来标记 IP, 但随后我们注意到一些合法的共享 IP(比如:大学 Wi-Fi 网关)同样具有很高的 邮件熵,仅仅是因为许多真实用户通过同一个出口节点登录。解决方法是将熵 与请求量结合起来:真正的攻击者同时具有高熵和高请求量, 而共享网关虽然具有高熵,但每个独立用户只贡献少量请求。一旦我们加入了 请求量门槛,误报率就显著下降了。 关于检测技术,我们学到的最重要的一点是,没有任何单一方法是独立可靠的。 我们的启发式规则(C 部分)抓住了明显的攻击者,却遗漏了隐蔽的攻击者。 z-分数标记了统计异常,但在偏态数据上失效了。 IQR 更加鲁棒,但可能会错过微小的系统性偏移。熵抓住了高扇出特征, 但对低频攻击者视而不见。分层方法——要求 4 种方法中至少有 2 种达成一致—— 结果比任何单一方法都要强大得多,因为误报率是相乘而不是相加的。 如果每种方法独立地将合法 IP 误标的几率为 5%,那么两种方法同时误标的几率仅为 0.05 × 0.05 = 0.25%。这就是现实安全系统中集成和分层检测背后的核心直觉。 最后,关于供应商标签(`risk_indication`)的令人大开眼界。它将 约 59% 的流量标记为“有风险”,这显然不能作为可用的真实基准——这 本质上是噪音。构建我们自己的检测器,然后将其与供应商标签进行对比, 向我们确切地展示了它们在哪里存在分歧以及为什么。这是我们没有预料到 能在这个作业中练习的技能,但它可能是我们学到的最实用的一课。
标签:Apex, BSD, IQR, Matplotlib, NoSQL, NumPy, Python, SciPy, Seaborn, Z-Score, 人工智能, 代码示例, 凭证填充, 启发式规则, 威胁情报, 开发者工具, 异常检测, 撞库检测, 数据分析, 数据挖掘, 无后门, 机器学习, 用户模式Hook绕过, 统计特征, 网络安全, 逆向工具, 隐私保护, 香农熵