向量與嵌入弱點評估 是做什麼的?
僅限授權使用: 這些測試會與您擁有或獲授權評估的 RAG 系統中的向量儲存和嵌入模型進行互動。對您無法控制的系統進行嵌入反轉和跨租戶探測,可能會暴露第三方資料,未經授權禁止此操作。
概述
檢索增強生成 (RAG) 系統會將文件轉換為嵌入向量,儲存在向量資料庫(Pinecone、Qdrant、Weaviate、Chroma、pgvector、FAISS)中,並檢索最接近的向量來為 LLM 回應提供基礎。OWASP LLM08:2025 向量與嵌入弱點 涵蓋了此層特有的安全風險:
- 嵌入反轉 — 嵌入並非單向。訓練好的反轉模型(或黑箱重建攻擊)可以從其向量中還原大量原始文字,導致來源文件外洩(對應 MITRE ATLAS AML.T0024.001 反轉 ML 模型)。
- 成員推斷 — 查詢特定記錄是否貢獻給語料庫(AML.T0024.000)。
- 跨租戶 / 多租戶洩漏 — 當命名空間/集合共用或過濾器隔離缺失時,一個租戶會檢索到另一個租戶的區塊。
- 知識庫投毒 — 能夠寫入語料庫的攻擊者插入精心製作的區塊,這些區塊能主導檢索(與預期查詢的餘弦相似度很高)並攜帶間接提示注入負載。
- 檢索操控 — 針對許多不相關查詢最佳化檢索結果的對抗性文件(「檢索劫持」)。
上層技術為 AML.T0024 — 透過 ML 推論 API 外洩:攻擊者利用合法的推論/查詢存取權限來外洩資料(透過反轉、成員推斷或模型萃取的方式取得原始文字)。此技能提供了針對所有五種弱點類別的可重複評估。
使用時機
- 在任何 RAG / 向量搜尋應用程式的安全性評估期間(涵蓋 OWASP LLM08)。
- 當向量儲存為多租戶且您必須證明命名空間/元資料隔離時。
- 當語料庫接受使用者提供或第三方文件時(投毒攻擊面)。
- 當嵌入端點可從外部存取時(反轉/成員推斷攻擊面)。
- 在上線前驗證檢索過濾控制項時。
先決條件
- 取得針對目標嵌入端點和向量儲存的授權與範圍。
- Python 3.10+。
- 對測試集合的讀取(以及用於投毒測試的寫入)權限 — 絕不可用於正式環境的語料庫。
# 向量資料庫客戶端 + 嵌入 + 相似度工具
python -m pip install numpy scikit-learn sentence-transformers
python -m pip install qdrant-client chromadb pinecone-client weaviate-client
# (可選)文字嵌入反轉研究基線
python -m pip install vec2text
目標
- 測量目標嵌入模型上的嵌入反轉暴露程度。
- 針對語料庫執行成員推斷探測。
- 測試多租戶隔離(命名空間、元資料過濾器、RBAC)是否存在跨租戶洩漏。
- 將良性投毒區塊注入測試集合,並測量其檢索主導性。
- 偵測檢索區塊中殘留的間接提示注入內容。
- 建議控制項:租戶範圍過濾器、內容驗證、嵌入存取限制。
MITRE ATT&CK 對應
| ID | 戰術 | 官方技術名稱 | 在本技能中的角色 |
|---|---|---|---|
| AML.T0024 | ATLAS: 外洩 | 透過 ML 推論 API 外洩 | 利用查詢/嵌入存取權限來外洩來源資料 |
| AML.T0024.000 | ATLAS: 外洩 | 推斷訓練資料成員資格 | 針對語料庫的成員推斷探測 |
| AML.T0024.001 | ATLAS: 外洩 | 反轉 ML 模型 | 來源文字的嵌入反轉重建 |
| AML.T0020 | ATLAS: 資源開發 | 訓練資料投毒 | 對語料庫的知識庫投毒 |
| AML.T0051.001 | ATLAS: 初始存取 | LLM 提示注入:間接 | 嵌入在檢索區塊中的注入負載 |
工作流程
步驟 1:清查 RAG 管線
記錄嵌入模型 + 維度、向量儲存及其租戶模型、分塊策略、檢索 top_k 和相似度度量(餘弦/點積/L2),以及查詢時套用的任何元資料過濾器。
# 範例:檢查 Qdrant 集合
from qdrant_client import QdrantClient
client = QdrantClient(url="http://localhost:6333")
info = client.get_collection("docs")
print(info.config.params.vectors) # 大小 + 距離度量
print(client.count("docs")) # 語料庫大小
步驟 2:測試嵌入反轉暴露程度
相似文字的嵌入在空間中接近;攻擊者擁有嵌入端點時,可以迭代重建文字,使其嵌入與目標向量匹配。透過計算候選重建與目標之間的餘弦相似度,衡量嵌入空間中最鄰近的還原程度。
import numpy as np
from sentence_transformers import SentenceTransformer
from sklearn.metrics.pairwise import cosine_similarity
model = SentenceTransformer("all-MiniLM-L6-v2")
secret = "Patient John Doe, MRN 553120, diagnosed with hypertension."
target_vec = model.encode([secret])
# 攻擊者只有 target_vec 和嵌入端點。爬山法尋找候選文字。
candidates = [
"Patient name and medical record number with a diagnosis.",
"John Doe medical record hypertension diagnosis",
"Patient John Doe MRN diagnosed hypertension",
]
cand_vecs = model.encode(candidates)
sims = cosine_similarity(target_vec, cand_vecs)[0]
for c, s in sorted(zip(candidates, sims), key=lambda x: -x[1]):
print(f"{s:.3f} {c}")
# 對近似逐字猜測的相似度很高 => 此模型的反轉風險確實存在。
對於研究級重建基線,可針對相容的嵌入模型使用 vec2text,以示範全文還原。
步驟 3:成員推斷
透過測量精確引用查詢的 top-1 檢索相似度,判斷特定文件是否存在於語料庫中:語料庫內的項目會回傳明顯高於對照組的最大相似度。
def membership_score(client, collection, embed, text):
vec = embed([text])[0].tolist()
hits = client.search(collection_name=collection, query_vector=vec, limit=1)
return hits[0].score if hits else 0.0
in_corpus = membership_score(client, "docs", model.encode, "<已知區塊中的確切引用>")
control = membership_score(client, "docs", model.encode, "一個不相關的隨機句子。")
print(f"in-corpus={in_corpus:.3f} control={control:.3f} delta={in_corpus-control:.3f}")
# 正 delta 值很大表示該項目存在於語料庫中(成員身分洩漏)。
步驟 4:測試多租戶隔離
確認租戶 B 無法檢索租戶 A 的區塊。發送租戶 B 已驗證的查詢應經過過濾,並驗證結果中未出現租戶 A 的 tenant_id。
# 以租戶 B 身分查詢;預期僅回傳 tenant_id == "B" 的結果。
from qdrant_client.models import Filter, FieldCondition, MatchValue
vec = model.encode(["confidential salary information"])[0].tolist()
hits = client.search(
collection_name="docs",
query_vector=vec,
limit=10,
query_filter=Filter(must=[FieldCondition(key="tenant_id", match=MatchValue(value="B"))]),
)
leaked = [h for h in hits if h.payload.get("tenant_id") != "B"]
print("CROSS-TENANT LEAK" if leaked else "isolation OK", "->", len(leaked), "foreign rows")
# 關鍵測試:重複執行但不使用過濾器,確認伺服器(而非客戶端)強制執行隔離。
# 如果未過濾的查詢回傳了租戶 A 的資料,則隔離僅在客戶端生效。
hits_nofilter = client.search(collection_name="docs", query_vector=vec, limit=10)
print("server-side isolation FAILS" if any(h.payload.get("tenant_id") != "B" for h in hits_nofilter) else "OK")
步驟 5:知識庫投毒(僅限測試集合)
插入一個良性的投毒區塊,使其能被許多不相關的查詢檢索到,然後測量其在 top_k 中出現的頻率。
from qdrant_client.models import PointStruct
# 良性標記負載(無實際注入),用於測量檢索主導性。
poison = "POISON-CANARY. " + " ".join(
["password reset billing refund account login support error help"] * 8
)
client.upsert("docs_test", points=[
PointStruct(id=999999, vector=model.encode([poison])[0].tolist(),
payload={"tenant_id": "B", "source": "poison-test"})
])
queries = ["how do I get a refund", "reset my password", "what is the weather"]
for q in queries:
hits = client.search("docs_test", model.encode([q])[0].tolist(), limit=5)
dominated = any(h.payload.get("source") == "poison-test" for h in hits)
print(f"{'POISON in top5' if dominated else 'clean'}: {q}")
步驟 6:偵測檢索結果中的間接提示注入
在檢索到的區塊文字串接至提示詞之前,掃描其中的注入標記。
import re
INJECTION_PATTERNS = [
r"ignore (all|previous|the above) instructions",
r"system prompt", r"you are now", r"disregard", r"</?(system|instructions)>",
]
def chunk_is_injection(text):
low = text.lower()
return [p for p in INJECTION_PATTERNS if re.search(p, low)]
for hit in client.search("docs", model.encode(["help"])[0].tolist(), limit=10):
flags = chunk_is_injection(hit.payload.get("text", ""))
if flags:
print("INDIRECT INJECTION in chunk", hit.id, flags)
步驟 7:報告與修復
- 反轉/成員推斷: 對嵌入端點進行速率限制和驗證;避免回傳原始相似度分數;限制誰可以查詢嵌入。
- 跨租戶: 在伺服器端強制執行租戶過濾器(若可行,為每個租戶使用獨立的集合/命名空間);切勿依賴客戶端提供的過濾器。
- 投毒: 驗證每個攝入區塊的來源並加上標記;掃描輸入內容是否有注入;限制任何單一來源在檢索結果中的佔比。
- 間接注入: 清理檢索到的區塊並套用輸出護欄(請參閱
defending-llms-with-guardrails)。
工具與資源
| 工具 | 用途 | 主要來源 |
|---|---|---|
| OWASP LLM08 | 向量與嵌入弱點指南 | https://genai.owasp.org/llmrisk/llm082025-vector-and-embedding-weaknesses/ |
| sentence-transformers | 用於測試的嵌入生成 | https://www.sbert.net/ |
| Qdrant client | 向量儲存 + 過濾搜尋 | https://qdrant.tech/documentation/ |
| Chroma / Weaviate / Pinecone | 替代向量儲存 | https://docs.trychroma.com/ |
| vec2text | 嵌入反轉研究基線 | https://github.com/jxmorris12/vec2text |
| MITRE ATLAS | AML.T0024 透過 ML 推論 API 外洩 | https://atlas.mitre.org/ |
驗證標準
- 清查 RAG 管線(嵌入模型、儲存、租戶模型、度量、top_k、過濾器)。
- 測量並評估嵌入反轉暴露程度。
- 計算語料庫內項目與對照組的成員推斷 delta 值。
- 測試多租戶隔離,包含使用與不使用客戶端過濾器兩種情況(確認伺服器端強制執行)。
- 僅在測試集合中測量投毒主導性。
- 掃描檢索區塊中是否有間接注入內容。
- 針對每個弱點類別提出發現與修復建議。
- 評估期間未修改正式環境語料庫。