jkwebsec/NexL-CodingBlocks-Assignments-2

GitHub: jkwebsec/NexL-CodingBlocks-Assignments-2

面向网络安全威胁情报的 AI 语义搜索引擎,利用向量检索取代关键词匹配,解决安全领域术语差异导致的检索遗漏问题。

Stars: 0 | Forks: 0

# NexL ### 面向网络安全情报的 AI 驱动语义搜索引擎 *因为威胁情报没时间去猜关键词。* [![Python](https://img.shields.io/badge/Python-3.12-3776AB?style=for-the-badge&logo=python&logoColor=white)](https://www.python.org/) [![SentenceTransformers](https://img.shields.io/badge/SentenceTransformers-all--MiniLM--L6--v2-FF6600?style=for-the-badge)](https://www.sbert.net/) [![FAISS](https://img.shields.io/badge/FAISS-Vector%20Search-0064A0?style=for-the-badge)](https://faiss.ai/) [![Gradio](https://img.shields.io/badge/Gradio-UI-FF7F3F?style=for-the-badge&logo=gradio&logoColor=white)](https://gradio.app/) [![Platform](https://img.shields.io/badge/Platform-Kaggle-20BEFF?style=for-the-badge&logo=kaggle&logoColor=white)](https://www.kaggle.com/)
## 简介 网络安全分析师每天都要处理海量的威胁情报——CVE、MITRE ATT&CK 技术、事件报告、红队发现、供应商公告。常见的工作流程是关键词搜索:你输入一个词,就会得到包含该词的文档。问题在于?威胁行为者命名技术的方式与你的数据库并不相同。 **NexL** 完全围绕一个不同的理念构建。它不是在匹配字符串,而是理解*含义*。当你询问“攻击者如何绕过端点安全?”时,NexL 不会去寻找这些精确的词——它理解这个概念,并呈现出语义上最相关的文档,无论这些文档使用了“绕过”、“逃避”、“hook”、“syscall”等词,还是完全没有使用这些词。 这个名字来源于*下一层级*情报层的概念——介于原始搜索和完整的 LLM 聊天之间,专为安全工作的操作节奏而设计。 ## 问题陈述 传统的基于关键词的搜索在网络安全领域失效的原因是可以预见的:该领域充斥着因供应商、框架和地区而异的技术术语。一篇关于“进程镂空”的报告和一篇关于“向挂起进程注入代码”的报告描述的是同一件事——而关键词搜索返回的重叠结果为零。 这就是 NexL 要解决的问题。 ## 工作原理——架构概览 ``` flowchart TD A["📄 Cybersecurity Documents\n8 seeded entries + any PDF"] --> B["Text Extraction\nPDF parsed via pypdf\nContent columns flattened"] B --> C["Sentence Transformer\nall-MiniLM-L6-v2\nConverts text → 384-dim vector"] C --> D["L2 Normalization\nfaiss.normalize_L2\nPrepares for cosine similarity"] D --> E["FAISS Index\nIndexFlatIP — Inner Product\nAll vectors stored in-memory"] F["🔍 User Query\nFree-text or PDF-augmented"] --> G["Query Encoding\nSame model, same dimension"] G --> H["L2 Normalization\nQuery vector normalized"] H --> I["FAISS Search\ntop_k nearest neighbors\nby Inner Product = Cosine Sim"] E --> I I --> J["Ranked Results\nTitle / Category / Score / Content"] J --> K["Gradio UI\nMarkdown output with relevance color codes"] style A fill:#0f172a,stroke:#38bdf8,color:#e2e8f0 style B fill:#1e293b,stroke:#818cf8,color:#e2e8f0 style C fill:#1e293b,stroke:#818cf8,color:#e2e8f0 style D fill:#1e293b,stroke:#818cf8,color:#e2e8f0 style E fill:#1e1a4a,stroke:#a78bfa,color:#ede9fe style F fill:#0f172a,stroke:#38bdf8,color:#e2e8f0 style G fill:#1e293b,stroke:#818cf8,color:#e2e8f0 style H fill:#1e293b,stroke:#818cf8,color:#e2e8f0 style I fill:#1e293b,stroke:#facc15,color:#fef9c3 style J fill:#14532d,stroke:#4ade80,color:#dcfce7 style K fill:#0f172a,stroke:#38bdf8,color:#e2e8f0 ``` ## 技术栈 | 组件 | 库 / 工具 | 选择原因 | |-----------|---------------|----------------| | **Embeddings** | `sentence-transformers` — `all-MiniLM-L6-v2` | 384维向量,在 CPU 上运行速度快,语义准确性高 | | **向量存储** | `faiss-cpu` — `IndexFlatIP` | 内存级,零基础设施,支持此规模下的精确搜索 | | **PDF 解析** | `pypdf` | 轻量级,可处理大多数威胁情报 PDF 格式 | | **UI 层** | `gradio` | 无需编写一行 HTML 即可实现浏览器可访问的演示 | | **数据处理** | `pandas`, `numpy` | 标准语料库管理和数组操作 | | **平台** | Kaggle (Python 3.12, CPU) | 无需本地设置,一键复现 | ## 核心概念:为什么选择语义而非关键词 这是 NexL 存在的核心,也是它与文档上的 `Ctrl+F` 的区别所在。 ``` flowchart LR subgraph KW["Keyword Search — Old Way"] direction TB Q1["Query: EDR bypass"] --> M1{"Exact string\nmatch in text?"} M1 -->|"No match"| X1["❌ No results\neven if document\ndescribes the same thing"] M1 -->|"Match"| Y1["✅ Returns document"] end subgraph SM["Semantic Search — NexL"] direction TB Q2["Query: EDR bypass"] --> E2["Encode to vector\n384 dimensions"] E2 --> S2["Cosine similarity\nagainst all doc vectors"] S2 --> R2["✅ Returns documents about\nsyscalls, hooking, injection,\nprocess hollowing — all of it"] end style KW fill:#450a0a,stroke:#f87171,color:#fef2f2 style SM fill:#14532d,stroke:#4ade80,color:#dcfce7 style X1 fill:#450a0a,stroke:#f87171,color:#fef2f2 style Y1 fill:#14532d,stroke:#4ade80,color:#dcfce7 style R2 fill:#14532d,stroke:#4ade80,color:#dcfce7 ``` 当查询和文档都被表示为同一个高维空间中的向量时,该空间中的接近度就等同于概念上的相似性。讨论同一*想法*的两份文档会聚集在一起——即使它们使用的词汇完全不同。 ## 查询处理流水线 当你点击搜索的那一刻实际上发生了什么: ``` flowchart TD IN["User types a query\n(or uploads a PDF)"] --> PDF{"PDF\nattached?"} PDF -->|"Yes"| EX["pypdf extracts text\nfrom all pages"] EX --> TR{"Text > 4000\nchars?"} TR -->|"Yes"| CUT["Smart truncation\nFirst 2000 + Last 2000 chars"] TR -->|"No"| FULL["Use full text"] CUT --> MERGE["Append PDF text\nto original query"] FULL --> MERGE PDF -->|"No"| VAL{"Query\n≥ 5 chars?"} MERGE --> VAL VAL -->|"No"| WARN["⚠️ Warning message\nReturned to user"] VAL -->|"Yes"| ENC["Encode query\nall-MiniLM-L6-v2"] ENC --> NORM["L2 Normalize\nfaiss.normalize_L2"] NORM --> SEARCH["FAISS IndexFlatIP.search\ntop_k = min(5, index.ntotal)"] SEARCH --> SCORE["Cosine similarity scores\n0.0 → 1.0"] SCORE --> FORMAT["Format output\n🟢 >60% | 🟡 >40% | 🔴 below"] FORMAT --> OUT["Markdown rendered\nin Gradio UI"] style IN fill:#0f172a,stroke:#38bdf8,color:#e2e8f0 style EX fill:#1e293b,stroke:#818cf8,color:#e2e8f0 style CUT fill:#713f12,stroke:#fbbf24,color:#fef3c7 style MERGE fill:#1e293b,stroke:#818cf8,color:#e2e8f0 style WARN fill:#450a0a,stroke:#f87171,color:#fef2f2 style ENC fill:#1e1a4a,stroke:#a78bfa,color:#ede9fe style NORM fill:#1e293b,stroke:#818cf8,color:#e2e8f0 style SEARCH fill:#1e293b,stroke:#facc15,color:#fef9c3 style SCORE fill:#1e293b,stroke:#60a5fa,color:#eff6ff style FORMAT fill:#1e293b,stroke:#4ade80,color:#dcfce7 style OUT fill:#0f172a,stroke:#38bdf8,color:#e2e8f0 ``` ## 知识库 NexL 内置了 **8 篇网络安全文档**,涵盖了最常查询的威胁类别。这些不是玩具示例——每一条目都是对真实技术或漏洞的密集且准确的描述。 | # | 标题 | 类别 | |---|-------|----------| | 1 | 使用直接 Syscalls 绕过 EDR | EDR Bypass | | 2 | Log4Shell CVE-2021-44228 分析 | Vulnerability | | 3 | Living Off The Land Binaries (LOLBins) | Defense Evasion | | 4 | 进程注入技术 | Defense Evasion | | 5 | 2024年勒索软件初始访问向量 | Ransomware | | 6 | MFA 疲劳攻击 | Initial Access | | 7 | SQL 注入 (SQLi) | Web Exploitation | | 8 | 鱼叉式网络钓鱼与网络钓鱼 | Social Engineering | 语料库是**有意设计为可扩展的**——在查询时上传 PDF 可以动态扩展搜索上下文,而无需触及索引。正式的 v2 版本将允许分析师将新文档永久添加到 FAISS 索引中。 ## 语义模型——`all-MiniLM-L6-v2` 这个模型不是随意挑选的。它是针对本项目的限制条件经过深思熟虑后选择的: ``` Model: all-MiniLM-L6-v2 Architecture: BERT (6-layer MiniLM, distilled) Output dimensions: 384 Avg encoding speed: ~14,200 sentences/sec (CPU) Model size: ~80MB Semantic accuracy: Strong on short-to-medium paragraphs Training data: 1B+ sentence pairs ``` 在 Kaggle 免费的 CPU 层级上,384 维模型在语义质量和推理速度之间达到了最佳平衡。可以使用更大的模型(768 维,1024 维),但会增加对于演示级工具而言非常明显的延迟。 **为什么使用余弦相似度?** 余弦相似度测量的是两个向量之间的*角度*,而不是它们的大小。这对文本来说很重要,因为探讨同一主题的短文档和长文档应该获得同样高的分数——余弦忽略了长度偏差。L2 归一化加上内积在 FAISS 中高效地实现了这一点。 ## 相关性评分——颜色的含义 每个结果都会返回一个相似度得分和一个颜色指示器: | 颜色 | 得分范围 | 解释 | |-------|------------|----------------| | 🟢 绿色 | > 60% | 强语义匹配——高度相关 | | 🟡 黄色 | 40% – 60% | 中等相关——相关概念 | | 🔴 红色 | < 40% | 弱匹配——仅有表面联系 | 这些阈值是针对 8 篇文档的语料库进行调优的。如果使用更大的索引,你需要重新校准——相关性的衰减与数据集中存在多少语义变化有关。 ## PDF 集成 NexL 更实用的功能之一是能够上传原始威胁情报 PDF 并将其用作搜索上下文。 ``` flowchart LR PDF["Analyst receives\na threat report PDF"] --> UP["Uploads to Gradio\nFile picker"] UP --> PARSE["pypdf reads\nall pages sequentially"] PARSE --> TEXT["Raw text extracted\nfrom each page object"] TEXT --> CHECK{"> 4000 chars?"} CHECK -->|"Yes"| TRUNC["Truncate intelligently\nHead + Tail preserved\nCore context retained"] CHECK -->|"No"| USE["Use as-is"] TRUNC --> AUG["Concatenate with\nuser's text query"] USE --> AUG AUG --> FAISS["Single combined embedding\nsearched against index"] FAISS --> RESULTS["Results surface documents\nrelated to the PDF's content"] style PDF fill:#0f172a,stroke:#38bdf8,color:#e2e8f0 style PARSE fill:#1e293b,stroke:#818cf8,color:#e2e8f0 style CHECK fill:#1e293b,stroke:#facc15,color:#fef9c3 style TRUNC fill:#713f12,stroke:#fbbf24,color:#fef3c7 style AUG fill:#1e293b,stroke:#818cf8,color:#e2e8f0 style FAISS fill:#1e1a4a,stroke:#a78bfa,color:#ede9fe style RESULTS fill:#14532d,stroke:#4ade80,color:#dcfce7 ``` 这让分析师可以放入供应商公告或新的 MITRE ATT&CK 技术文档,并立即在现有知识库中找到与其相关的所有内容——而无需手动阅读两者。 ## Gradio 界面 Gradio UI 保持界面紧凑。两个输入框。一个按钮。几秒钟内得出结果。 ``` +--------------------------------------------------+ | 🛡️ NexL | | AI-Powered Semantic Search for Cybersecurity | +--------------------------------------------------+ | Search Query | | ┌────────────────────────────────────────────┐ | | │ e.g. 'How do hackers bypass endpoint │ | | │ security?' │ | | └────────────────────────────────────────────┘ | | | | Upload Threat Intel PDF (Optional) | | ┌──────────────┐ | | │ Drop PDF │ | | └──────────────┘ | | | | [ 🔍 Search ] [ 🗑️ Clear ] | | | | ── Results ──────────────────────────────────── | | **EDR Bypass using Direct Syscalls** `EDR` | | Relevance: 🟢 78.4% | | Many modern EDRs hook user-mode APIs... | | ───────────────────────────────────────────── | +--------------------------------------------------+ ``` - **无需专业知识**即可使用该工具 - **无需 CSV 或结构化输入**——只需使用自然语言 - **PDF 增强查询**在后台静默处理 - **公共链接**通过 `demo.launch(share=True)` 自动生成 - 直接在 Kaggle 上运行——启用 Internet 访问即可获取可共享的 URL ## 挑战与设计决策 ## 限制 | 限制 | 影响 | v2 中的修复方案 | |------------|--------|-----------| | FAISS 索引仅在内存中 | 重启会清空所有内容 | 使用 `faiss.write_index` 持久化索引 | | 仅 8 篇内置文档 | 存在小众技术的覆盖盲区 | 添加流水线以摄取 MITRE ATT&CK STIX 数据 | | PDF 使用单一组合 embedding | 长 PDF 会丢失中间部分的上下文 | 将 PDF 切分为 512-token 窗口,并分别对每个块进行索引 | | 没有重新排序 | Top-k 顺序仅由原始余弦决定 | 对排名前 5 的结果添加 cross-encoder 重排步骤 | | 没有 MITRE ID 映射 | 结果未链接到 ATT&CK ID | 使用结构化的 MITRE 元数据丰富每个文档 | ## 未来改进 | 优先级 | 改进项 | 解锁的功能 | |----------|------------|----------------| | **高** | **分块 PDF 索引**——将文档切分为重叠的 512-token 窗口 | 从全长威胁报告中实现准确检索 | | **高** | **持久化 FAISS 索引**——在会话之间保存/加载到磁盘 | 支持跨 Kaggle 重启的有状态知识库 | | **中** | **MITRE ATT&CK 摄取**——从 ATT&CK 仓库自动加载 STIX JSON | 索引中包含数千条真实的技术条目 | | **中** | **Cross-encoder 重排序**——使用第二个模型对 top-k 结果重新排序 | 在结果列表顶部实现更高的精度 | | **长期** | **FastAPI 后端 + 独立 Web 应用**——与 Gradio 解耦 | 可生产部署的威胁情报搜索工具 | | **长期** | **查询扩展**——从查询中自动建议相关的 MITRE 技术 ID | 弥合分析师意图与正式分类法之间的差距 | ## 如何运行 ``` # 无需安装脚本 — 所有依赖项在 cell 1 中通过 pip 安装 # sentence-transformers, faiss-cpu, gradio, pypdf, pandas, numpy ``` **步骤:** 1. 在 Kaggle 上打开 notebook 2. 无需附加数据集——语料库直接在代码中植入 3. 将加速器设置为 **None**——CPU 已经绰绰有余 4. 按顺序运行所有单元格(首次运行下载模型大约需要 60 秒) ## 结论 NexL 是一个小型项目,有着清晰的论点:对威胁情报的语义理解不是奢侈品,而是必需品。关键词搜索从来就不是为这样一个领域设计的:在这里,同一种攻击会因为撰写人的不同而有十二个不同的名字。 架构是刻意保持极简的——一个 6 层 transformer、一个内存级向量索引和一个 Gradio 包装器——因为重点是干净利落地证明这个概念,而不是过度工程化。所有重要的东西都可见于同一个 notebook 中。 ``` all-MiniLM-L6-v2 | 384-dim vectors | FAISS IndexFlatIP | 8 seeded docs | ~60s cold start ``` 本项目建立的是基础层。同样的架构,加上分块摄取和真实的语料库,就是分析师真正会使用的合法工具。
## 作者 **JK** 机器学习与网络安全爱好者 *于 Kaggle 构建,2026 年 7 月* *如果你觉得这个项目有用,请在仓库中留下一颗星。*
标签:Python, 人工智能, 向量检索, 威胁情报, 开发者工具, 无后门, 用户模式Hook绕过, 语义搜索, 逆向工具