AyaanB-DotCom/Threat-Intel-Matrix

GitHub: AyaanB-DotCom/Threat-Intel-Matrix

面向 SOC 分析师的本地优先 RAG 管线,支持在不泄露内部遥测数据的前提下查询事件响应 playbook 与 MITRE ATT&CK 信息。

Stars: 0 | Forks: 0

``` ████████╗██╗ ██╗██████╗ ███████╗ █████╗ ████████╗ ██╗███╗ ██╗████████╗███████╗██╗ ╚══██╔══╝██║ ██║██╔══██╗██╔════╝██╔══██╗╚══██╔══╝ ██║████╗ ██║╚══██╔══╝██╔════╝██║ ██║ ███████║██████╔╝█████╗ ███████║ ██║ ██║██╔██╗ ██║ ██║ █████╗ ██║ ██║ ██╔══██║██╔══██╗██╔══╝ ██╔══██║ ██║ ██║██║╚██╗██║ ██║ ██╔══╝ ██║ ██║ ██║ ██║██║ ██║███████╗██║ ██║ ██║ ██║██║ ╚████║ ██║ ███████╗███████╗ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═══╝ ╚═╝ ╚══════╝╚══════╝ ███╗ ███╗ █████╗ ████████╗██████╗ ██╗██╗ ██╗ ████╗ ████║██╔══██╗╚══██╔══╝██╔══██╗██║╚██╗██╔╝ ██╔████╔██║███████║ ██║ ██████╔╝██║ ╚███╔╝ ██║╚██╔╝██║██╔══██║ ██║ ██╔══██╗██║ ██╔██╗ ██║ ╚═╝ ██║██║ ██║ ██║ ██║ ██║██║██╔╝ ██╗ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚═╝╚═╝ ╚═╝ ```
### 专为事件响应、威胁情报与日志分类设计的本地优先 RAG ##### 完全在 Google Colab notebook 中运行 — 无需本地安装 [![Python](https://img.shields.io/badge/Python-3.10%2B-3776AB?style=flat-square&logo=python&logoColor=white)](https://www.python.org/) [![Google Colab](https://img.shields.io/badge/Runtime-Google_Colab-F9AB00?style=flat-square&logo=googlecolab&logoColor=white)](https://colab.research.google.com/) [![LangChain](https://img.shields.io/badge/LangChain-RAG_Pipeline-1C3C3C?style=flat-square&logo=langchain&logoColor=white)](https://www.langchain.com/) [![FAISS](https://img.shields.io/badge/FAISS-Vector_Store-0467DF?style=flat-square)](https://github.com/facebookresearch/faiss) [![Gradio](https://img.shields.io/badge/Gradio-6.0-F97316?style=flat-square&logo=gradio&logoColor=white)](https://www.gradio.app/) [![MITRE ATT&CK](https://img.shields.io/badge/MITRE-ATT%26CK-D4183D?style=flat-square)](https://attack.mitre.org/) [![License](https://img.shields.io/badge/License-MIT-black?style=flat-square)](#license)
## 概述 **Threat Intel Matrix** 是一个本地化、注重隐私保护的检索增强生成(RAG) pipeline,专为 **Tier 3 SOC 分析师**、**事件响应人员**和**渗透测试人员**打造。 它的存在是为了解决一个特定问题:分析师经常需要对事件响应 playbook、MITRE ATT&CK 技术数据和原始系统日志进行推理分析 —— 但如果将这些材料粘贴到公开的 AI 聊天机器人中,就意味着敏感的基础设施细节、内部程序或活跃的事件数据会泄露到组织控制范围之外。 Threat Intel Matrix 将检索层隔离在 Google Colab notebook 环境中。Playbook 和 MITRE ATT&CK 数据会被嵌入并索引到本地的 FAISS 向量数据库中;原始日志会在查询时通过 prompt 传入,而不是被永久写入索引中。分析师可以获得基于事实、带引用且具备 MITRE 意识的回答,而他们的日志或 playbook 绝不会离开其操作环境(推理 API 调用本身除外)。 ## 核心功能 ### 模型与 Embedding 层 - **LLM:** `Qwen/Qwen2.5-72B-Instruct`,通过 `ChatOpenAI` 兼容的 endpoint 封装器,经由 Hugging Face Serverless Inference API 进行路由。 - **Embeddings:** 通过 `HuggingFaceEmbeddings` 使用 `sentence-transformers/all-MiniLM-L6-v2`。 - **向量数据库:** 本地 `FAISS` 索引,保存在 Colab runtime 内存中 — 无需依赖外部向量数据库。 ### 数据接入 Pipeline - **事件响应 Playbook** — 使用带有 `UnstructuredMarkdownLoader` 的 `DirectoryLoader` 从 `./incident-response-playbooks` 递归加载。根目录下的 `README.md` 会在向量化之前被自动剔除,以防止非 playbook 内容污染索引。 - **MITRE ATT&CK 框架** — 实时获取官方的 STIX 企业级攻击数据集(`enterprise-attack.json`),解析以提取 `attack-pattern` 对象,并将其名称/描述直接映射为向量块,与 playbook 语料库并列。 - **粘贴的日志接入** — 双变量 prompt schema(`context`, `logs`, `question`)允许在 runtime 期间直接通过查询接口提交原始的 JSON/EVTX 日志数据,而无需将这些日志数据永久写入 FAISS 索引。 ### 启发式护栏与推理协议 - **主要事实依据** — 模型被要求首先严格根据检索到的 playbook 和 MITRE 数据进行回答。 - **尽力推导** — 当不存在完全匹配的 playbook 时,模型不会直接返回“数据不足”,而是根据检索上下文中关联最密切的概念进行有限的逻辑推理。 - **强制透明度标记** — 回答中任何依赖推理而非直接检索的部分,都会明确添加 `[WARNING: INFERRED STRATEGY]` 前缀,以便分析师能立即区分来源于事实的指导与推导出的指导。 ### 1-Bit 复古终端界面 (Gradio 6.0) - 使用 `gr.Blocks` 构建双栏布局:左侧为原始系统日志输入,右侧为聊天终端输出。 - 通过注入 CSS 实现定制化的单色 CRT 美学 — 采用 `Press Start 2P`、`VT323` 和 `Share Tech Mono` Google 字体,零 border-radius,硬反转按钮悬停状态,以及 ASCII 条码区域分割线。 - 基於 Gradio 6.0+ 事件循环构建,使用基于字典的聊天记录(`role` / `content` schema)。 ## 架构数据流 ``` ┌────────────────────────────┐ │ INGESTION (build-time) │ └──────────────┬───────────────┘ │ ┌──────────────────────────────┼──────────────────────────────┐ │ │ │ ▼ ▼ │ ┌─────────────────────┐ ┌──────────────────────────┐ │ │ IR Playbooks (.md) │ │ MITRE ATT&CK STIX JSON │ │ │ ./incident-response- │ │ enterprise-attack.json │ │ │ playbooks/ │ │ (fetched live) │ │ └──────────┬────────────┘ └──────────────┬────────────┘ │ │ DirectoryLoader + │ Parse attack-pattern │ │ UnstructuredMarkdownLoader │ objects → Document() │ │ (root README.md pruned) │ │ ▼ ▼ │ ┌────────────────────────────────────────────────────────┐ │ │ RecursiveCharacterTextSplitter (chunking) │ │ └───────────────────────────┬────────────────────────────┘ │ ▼ │ ┌────────────────────────────────────────────────────────┐ │ │ HuggingFaceEmbeddings (all-MiniLM-L6-v2) → FAISS Index │◄──────────────────┘ └───────────────────────────┬────────────────────────────┘ │ ▼ ┌──────────────────┐ │ FAISS Retriever │ │ (k = 3 chunks) │ └────────┬─────────┘ │ ┌─────────────────────────────────────────────┐ │ QUERY TIME (per request) │ └─────────────────────────────────────────────┘ │ User Query ──────────────►│ Pasted Logs (optional) ──►│ RunnableParallel │ { context, question, logs } ▼ ┌────────────────────────┐ │ PromptTemplate │ │ + Reasoning Protocol │ │ + Transparency Rules │ └────────────┬─────────────┘ ▼ ┌────────────────────────┐ │ Qwen2.5-72B-Instruct │ │ (HF Router / ChatOpenAI)│ └────────────┬─────────────┘ ▼ ┌────────────────────────┐ │ StrOutputParser │ └────────────┬─────────────┘ ▼ ┌────────────────────────┐ │ Gradio Terminal UI │ │ (grounded / [INFERRED]) │ └────────────────────────┘ ``` ## 环境要求与部署 本项目专门为在 **Google Colab notebook 环境**中部署和执行而设计,无需本地桌面环境的依赖。 - 拥有可访问 [Google Colab](https://colab.research.google.com/) 的 Google 账号 - 拥有有效 [API token](https://huggingface.co/settings/tokens) 的 Hugging Face 账号(需要 Serverless Inference API 访问权限) ## 安装说明 (Google Colab 设置) 1. 打开一个新的 Google Colab notebook。 2. 安全地存储您的 Hugging Face API 密钥:点击左侧边栏的 **Secrets**(钥匙图标),添加一个名为 `HUGGINGFACEHUB_API_TOKEN` 的新 secret,将您的密钥粘贴作为值,并启用 **Notebook access**。 3. 创建一个新的代码块并运行以下命令,以安装依赖并拉取 playbook 仓库: ``` # 静默安装依赖 !pip install -q langchain langchain-community langchain-core langchain-text-splitters langchain-huggingface langchain-openai faiss-cpu sentence-transformers unstructured markdown # Clone the playbooks repository (忽略已克隆时的错误) !git clone https://github.com/LetsDefend/incident-response-playbooks.git || true # 清理 root README 以防止 vector database 污染 !rm -f incident-response-playbooks/README.md ``` ## 使用说明 将完整的实现代码(如下)粘贴到您的 Colab notebook 中的新代码块并执行。Gradio 6.0 界面将直接在 notebook 的代码块下方启动。 - **左侧面板** — 粘贴与您当前调查相关的原始 JSON/EVTX 系统日志(可选)。 - **右侧面板** — 终端聊天窗口。输入自然语言查询,按下 `EXECUTE` 或敲击回车键。 - 基于您的 playbook 或 MITRE ATT&CK 数据生成的回答将被直接返回。 - 任何在检索上下文之外依赖模型推理的回答片段,都会被明确标记为 `[WARNING: INFERRED STRATEGY]`。 ## 实现代码
点击展开完整源码 ``` # ========================================== # 1. 设置与数据摄取 # ========================================== import os import getpass import requests from langchain_community.document_loaders import DirectoryLoader, UnstructuredMarkdownLoader from langchain_text_splitters import RecursiveCharacterTextSplitter from langchain_community.vectorstores import FAISS from langchain_huggingface import HuggingFaceEmbeddings from langchain_openai import ChatOpenAI from langchain_core.prompts import PromptTemplate from langchain_core.runnables import RunnableParallel, RunnablePassthrough from langchain_core.output_parsers import StrOutputParser from langchain_core.documents import Document from google.colab import userdata # 从 Colab Secrets 安全地设置 Token hf_token = userdata.get("HUGGINGFACEHUB_API_TOKEN") os.environ["HUGGINGFACEHUB_API_TOKEN"] = hf_token # 初始化 Embeddings embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2") # 摄取 IR Playbooks playbook_loader = DirectoryLoader( './incident-response-playbooks', glob="**/*.md", loader_cls=UnstructuredMarkdownLoader ) playbook_docs = playbook_loader.load() text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=150) playbook_chunks = text_splitter.split_documents(playbook_docs) vector_store = FAISS.from_documents(playbook_chunks, embeddings) # 获取 MITRE ATT&CK Framework mitre_url = "https://raw.githubusercontent.com/mitre-attack/attack-stix-data/master/enterprise-attack/enterprise-attack.json" response = requests.get(mitre_url) mitre_data = response.json() mitre_documents = [] for obj in mitre_data.get('objects', []): if obj.get('type') == 'attack-pattern': name = obj.get('name', 'Unknown') description = obj.get('description', 'No description available.') mitre_documents.append( Document(page_content=f"MITRE Technique: {name}\nDescription: {description}") ) mitre_chunks = text_splitter.split_documents(mitre_documents) vector_store.add_documents(mitre_chunks) retriever = vector_store.as_retriever(search_kwargs={"k": 3}) # 初始化 LLM llm = ChatOpenAI( model="Qwen/Qwen2.5-72B-Instruct", api_key=hf_token, base_url="https://router.huggingface.co/v1", max_tokens=512, temperature=0.1 ) # 带有 Deduction Protocol 的 System Prompt template = """You are an expert Tier 3 SOC Analyst and Incident Responder. You will be provided with retrieved security playbooks and raw system logs. SECURITY GUARDRAILS & REASONING PROTOCOL: 1. Primary Grounding: Always attempt to answer the question using ONLY the provided playbooks and logs first. 2. Best-Effort Deduction: If the provided context lacks an exact match or is incomplete, DO NOT output "INSUFFICIENT DATA." Instead, use logical deduction to find the closest related concept in the context, and synthesize the most accurate, actionable recommendation possible. 3. Mandatory Transparency: If you are relying on logical deduction, partial matches, or outside cybersecurity knowledge to bridge gaps in the provided context, you MUST begin that specific recommendation with: "[WARNING: INFERRED STRATEGY]". 4. Log Analysis: If analyzing logs, explicitly cite the timestamp, host, user, and command. === RETRIEVED PLAYBOOKS & INTEL === {context} === RAW SYSTEM LOGS (USER PROVIDED) === {logs} === QUESTION === {question} Answer:""" def format_docs(docs): return "\n\n".join(doc.page_content for doc in docs) def get_query(x): return x.get("question", "") if isinstance(x, dict) else str(x) def get_logs(x): return x.get("logs", "No logs provided.") if isinstance(x, dict) else "No logs provided." rag_chain = ( RunnableParallel( context=lambda x: format_docs(retriever.invoke(get_query(x))), question=get_query, logs=get_logs, ) | PromptTemplate.from_template(template) | llm | StrOutputParser() ) # ========================================== # 2. GRADIO 6.0 MONOCHROME TERMINAL UI # ========================================== import gradio as gr custom_css = """ @import url('https://fonts.googleapis.com/css2?family=Press+Start+2P&family=VT323&family=Share+Tech+Mono&display=swap'); :root { --background-fill-primary: #000000 !important; --background-fill-secondary: #000000 !important; --text-color: #ffffff !important; --border-color-primary: #ffffff !important; --body-text-color: #ffffff !important; } body, .gradio-container { background-color: #000000 !important; color: #ffffff !important; font-family: 'Share Tech Mono', monospace !important; } * { border-radius: 0px !important; box-shadow: none !important; } h1, h2, h3 { font-family: 'Press Start 2P', monospace !important; text-transform: uppercase; color: #ffffff !important; text-align: center; letter-spacing: 2px; } textarea, input, .gr-box, .gr-chatbot { font-family: 'VT323', monospace !important; font-size: 1.3rem !important; border: 1px solid #ffffff !important; background-color: #000000 !important; color: #ffffff !important; } .message, [data-testid="user"], [data-testid="bot"], .message-wrap { background-color: #000000 !important; background: #000000 !important; border: 1px solid #ffffff !important; color: #ffffff !important; } .message p { color: #ffffff !important; } button { font-family: 'Press Start 2P', monospace !important; font-size: 0.7rem !important; border: 1px solid #ffffff !important; background-color: #000000 !important; color: #ffffff !important; transition: none !important; } button:hover { background-color: #ffffff !important; color: #000000 !important; cursor: pointer; } .barcode { font-family: 'VT323', monospace; letter-spacing: -2px; font-size: 1.5rem; text-align: center; user-select: none; color: #ffffff; margin: 15px 0; } """ with gr.Blocks() as demo: gr.Markdown("# THREAT INTEL MATRIX") gr.Markdown("
||||| ||| || |||| ||||| ||| || |||| ||||| |||
") with gr.Row(): with gr.Column(scale=1): gr.Markdown("### SYSTEM LOGS") logs_input = gr.Textbox( lines=18, show_label=False, placeholder="[+] PASTE RAW JSON/EVTX LOGS HERE...\n[+] LEAVE BLANK FOR GENERAL QUERIES..." ) with gr.Column(scale=2): gr.Markdown("### TERMINAL") chatbot = gr.Chatbot(height=410, show_label=False) with gr.Row(): query_input = gr.Textbox(lines=1, show_label=False, placeholder="[+] ENTER QUERY...", scale=4) submit_btn = gr.Button("EXECUTE", scale=1) gr.Markdown("
||||| ||| || |||| ||||| ||| || |||| ||||| |||
") def chat_logic(user_query, logs, history): if not user_query: return "", history dict_input = { "question": user_query, "logs": logs if logs.strip() else "No logs provided." } history.append({"role": "user", "content": user_query}) history.append({"role": "assistant", "content": "Processing query against local vectors..."}) yield "", history response = rag_chain.invoke(dict_input) history[-1]["content"] = response yield "", history submit_btn.click(fn=chat_logic, inputs=[query_input, logs_input, chatbot], outputs=[query_input, chatbot]) query_input.submit(fn=chat_logic, inputs=[query_input, logs_input, chatbot], outputs=[query_input, chatbot]) demo.launch(debug=True, css=custom_css, theme=gr.themes.Monochrome()) ```
## 路线图 计划中的未来增强功能 — **尚未实现**: | # | 功能 | 描述 | |---|---------|--------------| | 1 | **持续自动化日志接入** | 一个目录监控 pipeline,用来自动检测并解析新的 `.json` / `.evtx` 日志转储,无需手动粘贴即可将遥测数据提取为自然语言文档。 | | 2 | **Agentic 工具调用** | 当在提交的日志中识别出可疑工件时,能够进行实时外部查询(例如 VirusTotal 哈希检查、AlienVault OTX IP 信誉查询)的自主 LangChain agent。 | | 3 | **语义查询路由** | 一个路由层,用于在非安全或无关查询到达向量检索之前对其进行过滤,从而减少 token 开销和响应延迟。 | | 4 | **自动化基准评估** | 集成 `RAGAS` 框架,以通过编程方式对 Faithfulness、Answer Relevance 和 Context Recall 进行评分 — 旨在实现零未标记幻觉。 | ## 许可证 基于 [MIT License](#license) 发布。
`[ SYSTEM READY ]`   •   专为无法将事件数据粘贴到公开模型中的分析师而构建。
标签:IaC 扫描, RAG, 人工智能, 安全运营, 库, 应急响应, 扫描框架, 本地部署, 用户模式Hook绕过, 网络安全, 逆向工具, 隐私保护