[OWASP] 002 AI Agent 安全開發指南:OWASP 九大風險與八大防護實踐(OWASP AI Agent Security Cheat Sheet)
AI Agent 安全開發指南
基於 OWASP AI Agent Security Cheat Sheet
前言:為什麼 AI Agent 安全至關重要
AI Agent 是由大型語言模型(LLM)驅動的自主系統,能夠進行推理、規劃、使用工具、維護記憶,並採取行動來達成目標。這種擴展的能力引入了超越傳統 LLM 提示注入的獨特安全風險。
隨著 AI Agent 在企業應用中的普及,開發者必須了解並防範這些新興威脅。本指南將幫助您建立安全的 AI Agent 架構,最小化攻擊面。
主要安全風險
在開發 AI Agent 時,您需要特別關注以下九大風險類別:
1. 提示注入攻擊(Prompt Injection)
惡意指令通過使用者輸入或外部資料來源(網站、文件、電子郵件)注入,劫持 Agent 行為。這包括:
- 直接注入:使用者直接在輸入中嵌入惡意指令
- 間接注入:通過 Agent 讀取的外部資料(如網頁、文件)注入惡意指令
2. 工具濫用與權限提升(Tool Abuse & Privilege Escalation)
Agent 利用權限過大的工具執行非預期的操作或存取未授權的資源。攻擊者可能誘導 Agent 使用工具來:
- 存取敏感檔案系統
- 執行未授權的資料庫操作
- 呼叫受限的 API
3. 資料外洩(Data Exfiltration)
敏感資訊通過以下管道洩露:
- 工具呼叫參數
- API 請求
- Agent 輸出回應
- 日誌記錄
4. 記憶體污染(Memory Poisoning)
惡意資料持久化到 Agent 記憶體中,可能:
- 影響未來的會話
- 影響其他使用者
- 建立持久的後門
5. 目標劫持(Goal Hijacking)
操縱 Agent 目標使其服務於攻擊者目的,同時看起來合法。Agent 可能被誘導:
- 執行與原始任務無關的操作
- 優先處理攻擊者的指令
- 忽略安全限制
6. 過度自主(Excessive Autonomy)
Agent 在沒有適當人工監督的情況下執行高影響操作,可能導致:
- 不可逆的資料變更
- 財務損失
- 聲譽損害
7. 級聯故障(Cascading Failures)
多 Agent 系統中被入侵的 Agent 將攻擊傳播到其他 Agent,造成:
- 系統性安全漏洞
- 大規模資料洩露
- 服務中斷
8. 錢包拒絕服務(Denial of Wallet, DoW)
通過無限制的 Agent 迴圈造成過高的 API/運算成本的攻擊:
- 無限迴圈消耗 Token
- 大量不必要的工具呼叫
- 惡意觸發昂貴的運算操作
9. 敏感資料暴露(Sensitive Data Exposure)
個人識別資訊(PII)、憑證或機密資料意外包含在:
- Agent 上下文
- 日誌記錄
- 錯誤訊息
- 除錯輸出
最佳安全實踐
1. 工具安全與最小權限原則
這是 AI Agent 安全的第一道防線。確保每個 Agent 只能存取完成其特定任務所需的最少工具和權限。
核心原則:
- 只授予 Agent 特定任務所需的最少工具
- 實施每個工具的權限範圍(唯讀 vs. 寫入、特定資源)
- 對不同信任等級使用不同的工具集(例如:內部 vs. 面向使用者的 Agent)
- 敏感操作需要明確的工具授權
❌ 錯誤示範:權限過大的工具配置
# 危險:Agent 具有無限制的 shell 存取權限
tools = [
{
"name": "execute_command",
"description": "Execute any shell command",
"allowed_commands": "*" # 無限制!
}
]
✅ 正確示範:使用允許清單限制範圍
# 安全:限制為特定、安全的操作
tools = [
{
"name": "file_reader",
"description": "Read files from the reports directory",
"allowed_paths": ["/app/reports/*"],
"allowed_operations": ["read"],
"blocked_patterns": ["*.env", "*.key", "*.pem", "*secret*"]
}
]
工具授權中介軟體範例
from functools import wraps
SENSITIVE_TOOLS = ["send_email", "execute_code", "database_write", "file_delete"]
def require_confirmation(func):
@wraps(func)
async def wrapper(tool_name, params, context):
if tool_name in SENSITIVE_TOOLS:
if not context.get("user_confirmed"):
return {
"status": "pending_confirmation",
"message": f"Action '{tool_name}' requires user approval",
"params": sanitize_for_display(params)
}
return await func(tool_name, params, context)
return wrapper
2. 輸入驗證與提示注入防禦
所有外部資料都應被視為不可信任,必須在納入 Agent 上下文之前進行驗證和清理。
核心原則:
- 將所有外部資料視為不可信任(使用者訊息、檢索的文件、API 回應、電子郵件)
- 在將外部內容納入 Agent 上下文之前實施輸入清理
- 使用分隔符號和清晰的邊界區分指令和資料
- 對已知的注入模式套用內容過濾
- 考慮使用獨立的 LLM 呼叫來驗證/摘要不可信任的內容
建議的防禦層級:
┌─────────────────────────────────────────┐
│ 使用者輸入 / 外部資料 │
└─────────────────┬───────────────────────┘
▼
┌─────────────────────────────────────────┐
│ 第一層:格式驗證與清理 │
│ - 長度限制 │
│ - 特殊字元過濾 │
│ - 編碼驗證 │
└─────────────────┬───────────────────────┘
▼
┌─────────────────────────────────────────┐
│ 第二層:注入模式偵測 │
│ - 已知攻擊模式比對 │
│ - 指令分隔符號偵測 │
│ - 異常內容標記 │
└─────────────────┬───────────────────────┘
▼
┌─────────────────────────────────────────┐
│ 第三層:上下文隔離 │
│ - 明確的資料/指令邊界 │
│ - 信任等級標記 │
│ - 獨立的驗證 LLM 呼叫 │
└─────────────────┬───────────────────────┘
▼
┌─────────────────────────────────────────┐
│ Agent 上下文 │
└─────────────────────────────────────────┘
3. 記憶體與上下文安全
Agent 的記憶體系統可能成為攻擊者的目標,用於持久化惡意資料或竊取敏感資訊。
核心原則:
- 在儲存到 Agent 記憶體之前驗證和清理資料
- 在使用者/會話之間實施記憶體隔離
- 設定記憶體過期時間和大小限制
- 在持久化之前審核記憶體內容是否有敏感資料
- 對長期記憶使用加密完整性檢查
❌ 錯誤示範:未驗證的記憶體儲存
# 危險:將任意使用者輸入儲存到持久記憶體
def save_memory(agent, user_message, assistant_response):
agent.memory.add({
"user": user_message, # 可能包含注入 payload
"assistant": assistant_response,
"timestamp": datetime.now()
})
✅ 正確示範:經過驗證和隔離的記憶體
import hashlib
from datetime import datetime, timedelta
class SecureAgentMemory:
MAX_MEMORY_ITEMS = 100
MAX_ITEM_LENGTH = 5000
MEMORY_TTL_HOURS = 24
def __init__(self, user_id: str, encryption_key: bytes):
self.user_id = user_id
self.encryption_key = encryption_key
self.memories = []
def add(self, content: str, memory_type: str = "conversation"):
# 驗證內容
if len(content) > self.MAX_ITEM_LENGTH:
content = content[:self.MAX_ITEM_LENGTH]
# 掃描敏感資料模式
if self._contains_sensitive_data(content):
content = self._redact_sensitive_data(content)
# 掃描注入模式
content = self._sanitize_injection_attempts(content)
# 建立具有完整性檢查的記憶體項目
entry = {
"content": content,
"type": memory_type,
"timestamp": datetime.utcnow().isoformat(),
"user_id": self.user_id,
"checksum": self._compute_checksum(content)
}
self.memories.append(entry)
self._enforce_limits()
def _contains_sensitive_data(self, content: str) -> bool:
sensitive_patterns = [
r'\b\d{3}-\d{2}-\d{4}\b', # SSN
r'\b\d{16}\b', # 信用卡
r'password\s*[:=]\s*\S+', # 密碼
r'api[_-]?key\s*[:=]\s*\S+' # API 金鑰
]
return any(re.search(p, content, re.I) for p in sensitive_patterns)
def _compute_checksum(self, content: str) -> str:
return hashlib.sha256(
(content + self.user_id).encode() + self.encryption_key
).hexdigest()[:16]
4. 人機協作控制(Human-in-the-Loop)
對於高影響或不可逆的操作,必須確保有人工審核和批准的機制。
核心原則:
- 高影響或不可逆操作需要明確批准
- 在執行前實施操作預覽
- 根據操作風險等級設定自主權邊界
- 提供 Agent 決策和操作的清晰稽核軌跡
- 允許使用者中斷和回滾 Agent 操作
風險等級分類
| 風險等級 | 操作類型 | 處理方式 |
|---|---|---|
| 低(LOW) | 讀取操作、安全查詢 | 自動批准 |
| 中(MEDIUM) | 寫入操作、API 呼叫 | 記錄並監控 |
| 高(HIGH) | 財務、刪除、外部通訊 | 需要人工審核 |
| 嚴重(CRITICAL) | 不可逆、安全敏感操作 | 強制人工批准 |
操作分類與批准流程範例
from enum import Enum
from dataclasses import dataclass
class RiskLevel(Enum):
LOW = "low" # 讀取操作、安全查詢
MEDIUM = "medium" # 寫入操作、API 呼叫
HIGH = "high" # 財務、刪除、外部通訊
CRITICAL = "critical" # 不可逆、安全敏感
ACTION_RISK_MAPPING = {
"search_documents": RiskLevel.LOW,
"read_file": RiskLevel.LOW,
"write_file": RiskLevel.MEDIUM,
"send_email": RiskLevel.HIGH,
"execute_code": RiskLevel.HIGH,
"database_delete": RiskLevel.CRITICAL,
"transfer_funds": RiskLevel.CRITICAL,
}
@dataclass
class PendingAction:
action_id: str
tool_name: str
parameters: dict
risk_level: RiskLevel
explanation: str
class HumanInTheLoopController:
def __init__(self, auto_approve_threshold: RiskLevel = RiskLevel.LOW):
self.auto_approve_threshold = auto_approve_threshold
self.pending_actions = {}
async def request_action(self, tool_name: str, params: dict,
explanation: str) -> dict:
risk_level = ACTION_RISK_MAPPING.get(tool_name, RiskLevel.HIGH)
# 自動批准低風險操作
if risk_level.value <= self.auto_approve_threshold.value:
return {"approved": True, "auto": True}
# 排隊等待人工審核
action = PendingAction(
action_id=generate_uuid(),
tool_name=tool_name,
parameters=self._sanitize_params_for_display(params),
risk_level=risk_level,
explanation=explanation
)
self.pending_actions[action.action_id] = action
return {
"approved": False,
"pending": True,
"action_id": action.action_id,
"requires": "human_approval",
"risk_level": risk_level.value,
"preview": self._generate_action_preview(action)
}
5. 輸出驗證與防護欄
Agent 的輸出必須經過驗證,以防止敏感資料洩露和惡意操作執行。
核心原則:
- 在執行或顯示前驗證 Agent 輸出
- 實施敏感資料洩露的輸出過濾
- 盡可能使用具有 schema 驗證的結構化輸出
- 設定輸出操作的邊界(速率限制、範圍限制)
- 對生成的回應套用內容安全過濾器
輸出驗證管道範例
from pydantic import BaseModel, validator
from typing import Optional, List
class AgentToolCall(BaseModel):
tool_name: str
parameters: dict
reasoning: Optional[str]
@validator('tool_name')
def validate_tool_allowed(cls, v):
allowed_tools = ["search", "read_file", "calculator", "get_weather"]
if v not in allowed_tools:
raise ValueError(f"Tool '{v}' is not in allowed list")
return v
@validator('parameters')
def validate_no_sensitive_data(cls, v):
sensitive_patterns = [
r'api[_-]?key', r'password', r'secret', r'token',
r'credential', r'private[_-]?key'
]
params_str = json.dumps(v).lower()
for pattern in sensitive_patterns:
if re.search(pattern, params_str):
raise ValueError("Parameters contain potentially sensitive data")
return v
class OutputGuardrails:
def __init__(self):
self.pii_patterns = self._load_pii_patterns()
self.rate_limiter = RateLimiter(max_calls=100, window_seconds=60)
async def validate_output(self, agent_output: dict) -> dict:
# 檢查速率限制
if not self.rate_limiter.allow():
raise RateLimitExceeded("Agent action rate limit exceeded")
# 驗證結構
if "tool_calls" in agent_output:
for call in agent_output["tool_calls"]:
validated = AgentToolCall(**call)
# 從回應中過濾 PII
if "response" in agent_output:
agent_output["response"] = self._filter_pii(agent_output["response"])
# 檢查資料外洩模式
if self._detect_exfiltration_attempt(agent_output):
raise SecurityViolation("Potential data exfiltration detected")
return agent_output
def _detect_exfiltration_attempt(self, output: dict) -> bool:
"""偵測通過工具呼叫外洩資料的嘗試"""
suspicious_patterns = [
# 在 URL 中編碼敏感資料
lambda o: "http" in str(o) and any(
p in str(o).lower() for p in ["base64", "encode", "password"]
),
# webhook/API 呼叫中的大量資料
lambda o: o.get("tool_name") in ["http_request", "webhook"] and
len(str(o.get("parameters", ""))) > 10000,
]
return any(pattern(output) for pattern in suspicious_patterns)
6. 監控與可觀測性
全面的監控系統是偵測和回應安全事件的關鍵。
核心原則:
- 記錄所有 Agent 決策、工具呼叫和結果
- 實施異常行為的異常偵測
- 追蹤每個會話/使用者的 Token 使用量和成本
- 設定安全相關事件的警報
- 維護合規和鑑識的稽核軌跡
建議的異常偵測閾值
| 指標 | 建議閾值 |
|---|---|
| 每分鐘工具呼叫次數 | 30 |
| 失敗的工具呼叫次數 | 5 |
| 注入嘗試次數 | 1(立即警報) |
| 敏感資料存取次數 | 3 |
| 每會話成本(美元) | $10.00 |
Agent 監控範例
import structlog
from dataclasses import dataclass
from typing import Dict, Any, Optional
from datetime import datetime
logger = structlog.get_logger()
@dataclass
class AgentSecurityEvent:
event_type: str
severity: str # INFO, WARNING, CRITICAL
agent_id: str
session_id: str
user_id: str
timestamp: datetime
details: Dict[str, Any]
tool_name: Optional[str] = None
class AgentMonitor:
ANOMALY_THRESHOLDS = {
"tool_calls_per_minute": 30,
"failed_tool_calls": 5,
"injection_attempts": 1,
"sensitive_data_access": 3,
"cost_per_session_usd": 10.0,
}
def __init__(self, agent_id: str):
self.agent_id = agent_id
self.session_metrics = {}
self.alert_handlers = []
async def log_tool_call(self, session_id: str, tool_name: str,
params: dict, result: dict, user_id: str):
# 記錄前遮蔽敏感資料
safe_params = self._redact_sensitive(params)
safe_result = self._redact_sensitive(result)
event = AgentSecurityEvent(
event_type="tool_call",
severity="INFO",
agent_id=self.agent_id,
session_id=session_id,
user_id=user_id,
timestamp=datetime.utcnow(),
tool_name=tool_name,
details={
"parameters": safe_params,
"result_status": result.get("status"),
"execution_time_ms": result.get("execution_time_ms"),
}
)
await self._emit_event(event)
await self._check_anomalies(session_id, event)
def _redact_sensitive(self, data: dict) -> dict:
"""從日誌資料中遮蔽敏感欄位"""
sensitive_keys = {"password", "api_key", "token", "secret", "credential"}
def redact(obj):
if isinstance(obj, dict):
return {
k: "***REDACTED***" if k.lower() in sensitive_keys else redact(v)
for k, v in obj.items()
}
elif isinstance(obj, list):
return [redact(i) for i in obj]
return obj
return redact(data)
7. 多 Agent 系統安全
當多個 Agent 協作時,需要特別注意防止攻擊在 Agent 之間傳播。
核心原則:
- 在 Agent 之間實施信任邊界
- 驗證和清理 Agent 間通訊
- 防止通過 Agent 鏈的權限提升
- 隔離 Agent 執行環境
- 套用熔斷器以防止級聯故障
Agent 信任等級定義
| 信任等級 | 說明 |
|---|---|
| UNTRUSTED (0) | 不受信任的外部 Agent,需要完全驗證 |
| INTERNAL (1) | 內部 Agent,有基本存取權限 |
| PRIVILEGED (2) | 具有提升權限的 Agent |
| SYSTEM (3) | 系統級 Agent,具有完全存取權限 |
安全的多 Agent 通訊範例
from typing import Optional, List
import jwt
from datetime import datetime, timedelta
from enum import Enum
class AgentTrustLevel(Enum):
UNTRUSTED = 0
INTERNAL = 1
PRIVILEGED = 2
SYSTEM = 3
class SecureAgentBus:
"""多 Agent 系統的安全通訊層"""
def __init__(self, signing_key: bytes):
self.signing_key = signing_key
self.agent_registry = {}
self.circuit_breakers = {}
def register_agent(self, agent_id: str, trust_level: AgentTrustLevel,
allowed_recipients: List[str]):
self.agent_registry[agent_id] = {
"trust_level": trust_level,
"allowed_recipients": allowed_recipients,
"allowed_message_types": self._get_allowed_types(trust_level)
}
self.circuit_breakers[agent_id] = CircuitBreaker(
failure_threshold=5,
recovery_timeout=60
)
async def send_message(self, sender_id: str, recipient_id: str,
message_type: str, payload: dict) -> dict:
# 驗證發送者
sender = self.agent_registry.get(sender_id)
if not sender:
raise SecurityViolation(f"Unknown sender agent: {sender_id}")
# 檢查熔斷器
if self.circuit_breakers[sender_id].is_open:
raise CircuitBreakerOpen(f"Agent {sender_id} is temporarily blocked")
# 驗證接收者授權
if recipient_id not in sender["allowed_recipients"]:
raise SecurityViolation("Sender not authorized to message recipient")
# 清理 payload
sanitized_payload = self._sanitize_payload(payload, sender["trust_level"])
# 建立簽署的訊息
signed_message = {
"sender": sender_id,
"recipient": recipient_id,
"type": message_type,
"payload": sanitized_payload,
"timestamp": datetime.utcnow().isoformat(),
"signature": self._sign_message(sender_id, recipient_id,
message_type, sanitized_payload)
}
return signed_message
async def receive_message(self, recipient_id: str, message: dict) -> dict:
# 驗證簽章
if not self._verify_signature(message):
raise SecurityViolation("Invalid message signature")
# 檢查訊息新鮮度(防止重播攻擊)
msg_time = datetime.fromisoformat(message["timestamp"])
if (datetime.utcnow() - msg_time) > timedelta(minutes=5):
raise SecurityViolation("Message expired (possible replay attack)")
return message["payload"]
8. 資料保護與隱私
遵循資料最小化原則,確保敏感資料得到適當保護。
核心原則:
- 最小化 Agent 上下文中的敏感資料
- 實施資料分類和處理規則
- 對靜態和傳輸中的資料套用加密
- 執行資料保留和刪除政策
- 符合隱私法規(GDPR、CCPA 等)
資料分類與處理建議
| 分類 | 範例 | 處理方式 |
|---|---|---|
| RESTRICTED | SSN、信用卡、健康資料 | 完全遮蔽 |
| CONFIDENTIAL | 薪資、API 金鑰、密碼 | 部分遮蔽 |
| INTERNAL | 內部文件、草稿 | 正常處理,記錄時遮蔽 |
| PUBLIC | 公開資訊 | 正常處理 |
資料分類與處理範例
from enum import Enum
import re
class DataClassification(Enum):
PUBLIC = "public"
INTERNAL = "internal"
CONFIDENTIAL = "confidential"
RESTRICTED = "restricted" # PII、財務、健康
class DataProtectionPolicy:
def __init__(self):
self.classification_rules = []
self.handling_rules = {}
def classify_data(self, data: str, context: dict) -> DataClassification:
"""根據內容模式自動分類資料"""
patterns = {
DataClassification.RESTRICTED: [
r'\b\d{3}-\d{2}-\d{4}\b', # SSN
r'\b\d{16}\b', # 信用卡
r'\b[A-Z]{2}\d{6,9}\b', # 護照
r'diagnosis|prescription|patient', # 健康
],
DataClassification.CONFIDENTIAL: [
r'salary|compensation|bonus',
r'api[_-]?key|password|secret',
r'confidential|internal only',
],
DataClassification.INTERNAL: [
r'@company\.com',
r'internal|draft|not for distribution',
]
}
for classification, pattern_list in patterns.items():
if any(re.search(p, data, re.I) for p in pattern_list):
return classification
return DataClassification.PUBLIC
def apply_protection(self, data: str, classification: DataClassification,
operation: str) -> str:
"""根據分類套用適當的保護"""
handlers = {
DataClassification.RESTRICTED: {
"include_in_context": self._redact_fully,
"log": self._redact_fully,
"output": self._redact_fully,
},
DataClassification.CONFIDENTIAL: {
"include_in_context": self._mask_partially,
"log": self._redact_fully,
"output": self._mask_partially,
},
DataClassification.INTERNAL: {
"include_in_context": lambda x: x,
"log": self._mask_partially,
"output": lambda x: x,
},
}
handler = handlers.get(classification, {}).get(operation, lambda x: x)
return handler(data)
def _redact_fully(self, data: str) -> str:
return "[REDACTED]"
def _mask_partially(self, data: str) -> str:
if len(data) <= 4:
return "****"
return data[:2] + "*" * (len(data) - 4) + data[-2:]
應該做與不應該做的事
✅ 應該做
- 對所有 Agent 工具和權限套用最小權限原則
- 驗證和清理所有外部輸入(使用者訊息、文件、API 回應)
- 對高風險操作實施人機協作控制
- 在使用者/會話之間隔離記憶體和上下文
- 監控 Agent 行為並設定異常偵測
- 使用具有 schema 驗證的結構化輸出
- 簽署和驗證 Agent 間通訊
- 分類資料並套用適當的保護
❌ 不應該做
- 給予 Agent 無限制的工具存取或萬用字元權限
- 信任來自外部來源的內容(網站、電子郵件、文件)
- 允許 Agent 在沒有沙箱的情況下執行任意程式碼
- 在 Agent 記憶體中儲存敏感資料而不加密/遮蔽
- 讓 Agent 在沒有人工監督的情況下做出高影響決策
- 忽略成本控制(無限迴圈可能導致錢包拒絕服務)
- 在多 Agent 系統中傳遞未清理的資料
- 以明文記錄敏感資料(PII、憑證)
安全實施檢查清單
在部署 AI Agent 之前,請確保完成以下檢查項目:
工具安全
- [ ] 已實施最小權限原則
- [ ] 所有工具都有允許清單/阻擋清單
輸入驗證
- [ ] 已實施輸入清理
- [ ] 已設定注入模式過濾
記憶體安全
- [ ] 已實施使用者/會話隔離
- [ ] 已設定記憶體過期和大小限制
人機協作
- [ ] 高風險操作需要人工批准
- [ ] 已實施操作預覽功能
輸出驗證
- [ ] 已實施敏感資料過濾
- [ ] 已設定速率限制
監控
- [ ] 已記錄所有 Agent 操作
- [ ] 已設定異常偵測警報
多 Agent 安全
- [ ] 已實施 Agent 間信任邊界
- [ ] 已驗證 Agent 間通訊
資料保護
- [ ] 已實施資料分類
- [ ] 敏感資料已加密
參考資源
以下資源可幫助您深入了解 AI Agent 安全:
- OWASP LLM Top 10
- OWASP AI Agent Security Cheat Sheet
- OWASP LLM Prompt Injection Prevention Cheat Sheet
- NIST AI Risk Management Framework
- OpenAI Safety Best Practices
- Google Secure AI Framework (SAIF)
本文件基於 OWASP AI Agent Security Cheat Sheet 編譯
建議定期檢視並更新安全實踐以應對新興威脅
[NIST] 002 NIST CSF 2.0 完整指南:用夜市攤販的角度理解企業資安框架
前言:為什麼你需要認識 NIST CSF?
想像一下,你在饒河夜市經營一個滷味攤。你會擔心什麼?
- 有人偷走你的獨家滷汁配方(機密性)
- 有人偷偷在你的滷汁裡加料(完整性)
- 攤位突然停電無法營業(可用性)
企業的資訊安全,其實就跟你守護滷味攤一樣!而 NIST CSF(Cybersecurity Framework,網路安全框架) 就是美國國家標準暨技術研究院(NIST)提供的一套「攤位防護指南」,告訴你應該從哪些面向來保護你的數位資產。
💡 小知識:NIST CSF 2.0 於 2024 年 2 月發布,是自 2014 年首版以來最重大的更新,新增了「治理(GOVERN)」功能,強調資安不只是 IT 部門的事,而是整個組織的責任。
什麼是 NIST CSF?
NIST CSF 是一套高階的網路安全成果分類架構,幫助任何組織——不論規模大小、產業類型或資安成熟度——都能夠:
- 理解 自身的資安風險
- 評估 目前的資安狀態
- 排序 應該優先處理的事項
- 溝通 內外部的資安需求
CSF 的三大核心元件
| 元件 | 說明 | 夜市比喻 |
|---|---|---|
| CSF Core(核心) | 六大功能、類別、子類別的分類架構 | 攤位經營的六大守則 |
| CSF Profile(組織概況) | 描述組織目前/目標的資安狀態 | 你的攤位現在做到哪些?目標要做到哪些? |
| CSF Tiers(成熟度層級) | 評估資安治理與管理的嚴謹程度 | 從路邊攤到連鎖品牌的進化等級 |
CSF 核心:六大功能詳解
NIST CSF 2.0 將資安工作分成六大功能(Functions),就像經營攤位的六個面向:
🎯 功能一覽圖
┌─────────┐
│ 治理 GV │ ← 新增!在中心統籌一切
└────┬────┘
│
┌────────┼────────┐
│ │ │
┌───▼───┐ ┌──▼──┐ ┌──▼───┐
│識別 ID│ │保護 │ │偵測 │
│ │ │ PR │ │ DE │
└───────┘ └─────┘ └──────┘
│ │ │
└────────┼────────┘
│
┌────────┼────────┐
│ │
┌───▼───┐ ┌──▼───┐
│回應 RS│ │復原 │
│ │ │ RC │
└───────┘ └──────┘
1️⃣ 治理 GOVERN(GV)- 老闆的經營哲學
定義:建立、溝通並監控組織的資安風險管理策略、期望與政策。
這是 CSF 2.0 新增的功能,強調資安必須從高層開始重視。
夜市比喻:
- 老闆決定「食安第一」的經營理念
- 規定所有員工都要戴手套、圍裙
- 定期檢查是否有人違規
包含類別:
| 類別代碼 | 類別名稱 | 說明 |
|---|---|---|
| GV.OC | 組織脈絡 | 了解組織的使命、利害關係人期望 |
| GV.RM | 風險管理策略 | 建立風險容忍度與處理方式 |
| GV.RR | 角色、責任與權限 | 誰負責什麼? |
| GV.PO | 政策 | 書面的資安規定 |
| GV.OV | 監督 | 確保策略有被執行 |
| GV.SC | 供應鏈風險管理 | 管理供應商帶來的風險 |
2️⃣ 識別 IDENTIFY(ID)- 盤點你的家當
定義:了解組織目前的資安風險。
夜市比喻:
- 列出攤位有什麼值錢的東西(食材、設備、秘方)
- 了解誰是供應商、誰是常客
- 評估可能遇到的風險(小偷、食安問題、天災)
包含類別:
| 類別代碼 | 類別名稱 | 實例 |
|---|---|---|
| ID.AM | 資產管理 | 伺服器清單、軟體清單、資料分類 |
| ID.RA | 風險評估 | 弱點掃描、威脅分析 |
| ID.IM | 改善 | 從經驗中學習、持續優化 |
3️⃣ 保護 PROTECT(PR)- 裝好門鎖和監視器
定義:使用防護措施來管理組織的資安風險。
夜市比喻:
- 裝鐵門、監視器
- 員工訓練:怎麼辨識假鈔、怎麼處理可疑人物
- 把秘方鎖在保險箱
包含類別:
| 類別代碼 | 類別名稱 | 實例 |
|---|---|---|
| PR.AA | 身分管理與存取控制 | MFA、權限管理 |
| PR.AT | 意識與訓練 | 資安教育訓練 |
| PR.DS | 資料安全 | 加密、備份 |
| PR.PS | 平台安全 | 系統更新、組態管理 |
| PR.IR | 技術基礎架構韌性 | 網路隔離、容錯設計 |
4️⃣ 偵測 DETECT(DE)- 發現小偷來了
定義:發現並分析可能的資安攻擊與入侵。
夜市比喻:
- 監視器發現有人在攤位外徘徊
- 收銀機發現異常交易
- 員工回報可疑情況
包含類別:
| 類別代碼 | 類別名稱 | 實例 |
|---|---|---|
| DE.CM | 持續監控 | SIEM、SOC、異常偵測 |
| DE.AE | 異常事件分析 | 事件關聯、威脅情資整合 |
5️⃣ 回應 RESPOND(RS)- 抓到小偷怎麼辦
定義:對已偵測到的資安事件採取行動。
夜市比喻:
- 抓住小偷、報警
- 通知其他攤販注意
- 清點損失
包含類別:
| 類別代碼 | 類別名稱 | 實例 |
|---|---|---|
| RS.MA | 事件管理 | 啟動應變計畫、分類事件 |
| RS.AN | 事件分析 | 根因分析、鑑識調查 |
| RS.CO | 事件通報與溝通 | 通知主管機關、利害關係人 |
| RS.MI | 事件緩解 | 隔離受感染系統、清除威脅 |
6️⃣ 復原 RECOVER(RC)- 重新開張營業
定義:恢復受資安事件影響的資產與營運。
夜市比喻:
- 修復被破壞的設備
- 補充被偷的食材
- 告訴客人「我們已經恢復營業」
包含類別:
| 類別代碼 | 類別名稱 | 實例 |
|---|---|---|
| RC.RP | 事件復原計畫執行 | 系統還原、資料復原 |
| RC.CO | 事件復原溝通 | 對外公告復原進度 |
CSF 組織概況(Profile):你的資安健檢報告
組織概況(Profile) 是用 CSF Core 的成果來描述組織資安狀態的工具。
兩種概況類型
| 類型 | 說明 | 用途 |
|---|---|---|
| 現況概況(Current Profile) | 目前達成哪些 CSF 成果 | 了解現在在哪裡 |
| 目標概況(Target Profile) | 想要達成哪些 CSF 成果 | 設定未來要去哪裡 |
建立組織概況的五步驟
步驟 1:界定範圍
↓
步驟 2:蒐集資訊
↓
步驟 3:建立概況
↓
步驟 4:分析差距並建立行動計畫
↓
步驟 5:執行計畫並更新概況
↓
(重複循環)
💡 實務建議:可以參考 NIST 提供的「社群概況(Community Profile)」,這是針對特定產業或情境預先建立的概況範本,例如製造業、醫療業等。
CSF 成熟度層級(Tiers):你的攤位等級
成熟度層級 用來描述組織資安風險治理與管理的嚴謹程度。
四個層級說明
| 層級 | 名稱 | 夜市比喻 | 特徵 |
|---|---|---|---|
| Tier 1 | 部分的(Partial) | 路邊攤,隨緣經營 | 沒有正式流程,靠經驗隨機應變 |
| Tier 2 | 風險知情的(Risk Informed) | 有固定攤位,開始有規矩 | 有風險意識但沒有全面落實 |
| Tier 3 | 可重複的(Repeatable) | 連鎖攤位,有 SOP | 有正式政策且持續執行 |
| Tier 4 | 自適應的(Adaptive) | 品牌企業,持續進化 | 能即時應變、持續改善 |
⚠️ 注意:層級不是「分數」,不是每個組織都需要達到 Tier 4。應該根據組織的風險狀況與成本效益來選擇適當的層級。
NIST CSF 與 SSDF 的關係:從「經營攤位」到「製作滷汁」
前面我們用「經營夜市攤位」來比喻 NIST CSF,它關注的是整體營運的資安。
但如果你是自己開發滷汁配方的攤販呢?這時候就需要另一套指南——NIST SSDF(Secure Software Development Framework,安全軟體開發框架)。
兩者的比較
| 面向 | NIST CSF 2.0 | NIST SSDF 1.1 |
|---|---|---|
| 關注焦點 | 組織整體的資安風險管理 | 軟體開發過程的安全性 |
| 適用對象 | 所有組織 | 軟體開發者、採購者 |
| 比喻 | 經營攤位的守則 | 製作滷汁的配方安全 |
| 主要架構 | 6 大功能 | 4 大實務群組 |
SSDF 的四大實務群組
| 群組 | 代碼 | 說明 | 與 CSF 的關聯 |
|---|---|---|---|
| 準備組織 | PO | 確保人員、流程、技術準備好進行安全開發 | 對應 GOVERN、IDENTIFY |
| 保護軟體 | PS | 保護程式碼不被竄改或未授權存取 | 對應 PROTECT |
| 產出安全軟體 | PW | 在開發過程中減少弱點 | 對應 PROTECT |
| 回應弱點 | RV | 識別並修復已發布軟體的弱點 | 對應 DETECT、RESPOND、RECOVER |
在 CSF 中如何整合 SSDF?
CSF 2.0 的 PR.PS-06 子類別明確提到:
「安全軟體開發實務已整合,且其效能在整個軟體開發生命週期中受到監控。」
這表示如果你的組織有開發軟體,應該:
- 在 GOVERN 階段:將安全開發納入組織政策
- 在 IDENTIFY 階段:識別開發環境中的風險
- 在 PROTECT 階段:實施 SSDF 的安全開發實務
- 在 DETECT 階段:監控軟體弱點
- 在 RESPOND/RECOVER 階段:處理已發現的弱點
實務整合範例
假設你是一家金融科技公司,同時需要:
┌─────────────────────────────────────────────────┐
│ 企業層級(CSF) │
│ ┌─────────────────────────────────────────┐ │
│ │ 組織資安治理 (GV) │ │
│ │ - 董事會資安責任 │ │
│ │ - 資安政策制定 │ │
│ │ - 供應鏈風險管理 │ │
│ └─────────────────────────────────────────┘ │
│ │ │
│ ┌────────────────────▼────────────────────┐ │
│ │ 開發團隊層級(SSDF) │ │
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
│ │ │ 準備組織 │ │ 保護軟體 │ │產出安全 │ │ │
│ │ │ (PO) │ │ (PS) │ │軟體(PW) │ │ │
│ │ └─────────┘ └─────────┘ └─────────┘ │ │
│ │ ┌─────────┐ │ │
│ │ │回應弱點 │ │ │
│ │ │ (RV) │ │ │
│ │ └─────────┘ │ │
│ └─────────────────────────────────────────┘ │
└─────────────────────────────────────────────────┘
如何開始使用 NIST CSF?
給新手的起步建議
第一步:了解組織現況
- 你們有哪些重要的數位資產?
- 目前有什麼資安措施?
- 過去發生過什麼資安事件?
第二步:選擇適合的起點
| 組織類型 | 建議起點 |
|---|---|
| 小型企業、新創 | 從 NIST 的「小型企業快速入門指南」開始 |
| 有基礎資安措施 | 建立現況概況,找出差距 |
| 已有成熟資安 | 用 CSF 2.0 重新檢視,特別是 GOVERN 功能 |
第三步:善用 NIST 資源
NIST 提供許多免費資源:
- 快速入門指南(QSG):針對特定主題的簡短指引
- 資訊參考(Informative References):與其他標準的對照表
- 實作範例(Implementation Examples):具體的實作建議
- 社群概況(Community Profiles):產業別的概況範本
🔗 資源連結:NIST CSF 官方網站
常見問題 FAQ
Q1:NIST CSF 是強制性的嗎?
A:對美國聯邦機構有強制性,但對一般企業是自願採用。不過,許多產業法規(如金融業、醫療業)會參考或要求遵循 CSF。
Q2:我們公司很小,也需要用 CSF 嗎?
A:CSF 設計上適用於任何規模的組織。小公司可以從核心的成果開始,選擇最相關的項目實施。
Q3:CSF 和 ISO 27001 有什麼不同?
| A: | 面向 | NIST CSF | ISO 27001 |
|---|---|---|---|
| 類型 | 框架(Framework) | 標準(Standard) | |
| 認證 | 無正式認證 | 可取得認證 | |
| 費用 | 免費 | 需購買標準文件 | |
| 彈性 | 較高 | 有明確要求 |
許多組織會同時使用兩者,用 CSF 做策略規劃,用 ISO 27001 做驗證。
Q4:從 CSF 1.1 升級到 2.0 要注意什麼?
A:主要變化包括:
- 新增 GOVERN 功能
- 強化供應鏈風險管理
- 更新子類別編號(部分有變動)
- 新增線上工具與資源
NIST 有提供升級指南,建議詳細閱讀。
結語:資安是一趟旅程,不是終點
NIST CSF 不是一份勾選完就結束的清單,而是一套持續改善的方法論。
就像夜市攤販不會因為今天生意好就停止進步,你的組織資安也需要:
- 📊 定期評估現況
- 🎯 設定合理目標
- 🔄 持續改善流程
- 👥 全員參與投入
從今天開始,用 NIST CSF 的思維來看待你的組織資安吧!
延伸閱讀
[NIST] 001 軟體開發也要穿防彈衣?一次搞懂 NIST SSDF 安全開發框架
「寫程式就寫程式,還要管什麼資安?」如果你還這樣想,那可能要小心了!現在的軟體開發,沒有做好安全防護,就像開店沒裝監視器一樣危險。今天就用最生活化的方式,帶你認識 NIST SSDF(安全軟體開發框架)!
什麼是 NIST SSDF?用便當店來解釋!
想像你要開一間便當店,你不會只顧著炒菜,對吧?你還需要:
- 👨🍳 訓練員工 怎麼安全使用刀具和瓦斯
- 🔒 保護食材 不被偷或污染
- 🍱 確保便當品質 衛生又好吃
- 📞 處理客訴 萬一有人吃壞肚子要怎麼辦
NIST SSDF 就是把這套邏輯用在軟體開發上!它是由美國國家標準暨技術研究院(NIST)發布的 SP 800-218 文件,告訴你怎麼從頭到尾把軟體寫得「安全」。
SSDF 的核心精神:左移(Shift Left)
傳統做法是寫完程式再找漏洞,就像便當做好才檢查有沒有蟑螂 🪳(已經太晚了!)
左移的概念是:越早處理安全問題,成本越低。就像買菜時就挑新鮮的,比煮完發現爛掉好太多了!
SSDF 四大實務領域:用便當店來比喻
SSDF 把安全開發分成四大區塊,我們繼續用便當店來解釋:
🏢 PO(Prepare the Organization):準備好你的組織
便當店版本: 開店前的準備工作
| SSDF 任務 | 便當店對照 |
|---|---|
| PO.1 定義安全需求 | 制定食材採購標準、衛生規範 |
| PO.2 建立角色與責任 | 誰負責採購?誰負責烹飪?誰負責清潔? |
| PO.3 導入工具鏈 | 買冰箱、裝抽油煙機、設置監視器 |
| PO.4 定義安全檢查標準 | 什麼溫度叫「熟了」?什麼狀態叫「新鮮」? |
| PO.5 維護安全環境 | 廚房要乾淨、倉庫要上鎖、員工入口要刷卡 |
程式開發實例:
✅ 制定安全編碼規範(Coding Standard)
✅ 指派資安負責人(Security Champion)
✅ 導入 SAST/DAST 工具
✅ 設定 CI/CD Pipeline 的安全檢查點
✅ 開發環境與正式環境要隔離
🔐 PS(Protect the Software):保護你的軟體
便當店版本: 保護你的食材和配方
| SSDF 任務 | 便當店對照 |
|---|---|
| PS.1 保護程式碼 | 祖傳滷肉飯配方要鎖在保險箱 |
| PS.2 提供完整性驗證 | 便當貼上防拆封貼紙 |
| PS.3 保存發布紀錄 | 記錄每批食材的來源和日期(溯源) |
程式開發實例:
✅ 程式碼存放在私有 Git Repository
✅ 使用 Code Signing 簽署發布檔案
✅ 產生 SBOM(軟體物料清單)
✅ 保存每次 Release 的完整紀錄
什麼是 SBOM?
就像便當的成分標示一樣!SBOM 會列出軟體裡用了哪些套件、版本是什麼,萬一某個套件出事,你可以馬上知道自己有沒有用到。
⚙️ PW(Produce Well-Secured Software):生產安全的軟體
便當店版本: 做出安全好吃的便當
| SSDF 任務 | 便當店對照 |
|---|---|
| PW.1 安全設計 | 菜單設計考慮過敏原、熱量標示 |
| PW.2 設計審查 | 試菜會議,確認口味和安全 |
| PW.4 重複使用安全元件 | 用經過認證的醬料,不要自己亂調 |
| PW.5 遵循安全編碼實務 | 按照 SOP 烹飪,不亂加料 |
| PW.6 安全配置編譯工具 | 確保瓦斯爐、烤箱設定正確 |
| PW.7 程式碼審查 | 主廚試吃確認品質 |
| PW.8 測試執行檔 | 出餐前最後檢查 |
| PW.9 預設安全設定 | 便當預設少油少鹽(健康優先) |
程式開發實例:
✅ 做威脅建模(Threat Modeling)
✅ 使用經過驗證的加密函式庫
✅ 執行 Code Review
✅ 跑 SAST(靜態掃描)和 DAST(動態掃描)
✅ 輸入驗證、輸出編碼
✅ 預設啟用 HTTPS、停用 Debug 模式
小提醒:常見的安全編碼原則
| 原則 | 說明 | 便當店比喻 |
|---|---|---|
| 輸入驗證 | 檢查使用者輸入的資料 | 確認客人點的餐真的有在菜單上 |
| 輸出編碼 | 避免 XSS 攻擊 | 便當盒要密封好,湯汁不能亂灑 |
| 最小權限 | 只給必要的權限 | 洗碗工不需要進金庫 |
| 錯誤處理 | 優雅地處理錯誤 | 賣完了就說「售完」,不要讓客人看到後廚在吵架 |
🚨 RV(Respond to Vulnerabilities):回應漏洞
便當店版本: 客訴處理與危機應變
| SSDF 任務 | 便當店對照 |
|---|---|
| RV.1 持續辨識漏洞 | 定期檢查食材有沒有過期 |
| RV.2 評估與修復漏洞 | 客人說太鹹,調整食譜 |
| RV.3 分析根本原因 | 為什麼會太鹹?是廚師手抖還是鹽巴受潮? |
程式開發實例:
✅ 建立漏洞通報管道(VDP)
✅ 訂閱 CVE 資料庫更新
✅ 定期執行弱點掃描
✅ 建立 PSIRT(產品安全事件應變小組)
✅ 做 Root Cause Analysis(根因分析)
實際案例:從零開始導入 SSDF
假設你是一間新創公司的工程師,老闆說要導入 SSDF,你可以這樣做:
第一步:盤點現況(PO)
□ 公司有沒有安全編碼規範?
□ 有沒有人負責資安?
□ 開發環境和正式環境有隔離嗎?
□ 有在用什麼安全工具嗎?
第二步:保護程式碼(PS)
□ 程式碼是不是放在私有 Repository?
□ 有沒有做 Code Signing?
□ 知道專案用了哪些第三方套件嗎?
第三步:建立安全開發流程(PW)
□ 有沒有做威脅建模?
□ 有沒有執行 Code Review?
□ CI/CD 有跑安全掃描嗎?
□ 預設設定是安全的嗎?
第四步:準備回應機制(RV)
□ 外部人員發現漏洞怎麼通報?
□ 內部發現漏洞怎麼處理?
□ 有沒有做過資安演練?
SSDF 對照表:讓你一目瞭然
| 領域 | 代碼 | 中文名稱 | 核心問題 |
|---|---|---|---|
| 準備組織 | PO | Prepare the Organization | 「開工前準備好了嗎?」 |
| 保護軟體 | PS | Protect the Software | 「東西放好了嗎?」 |
| 生產安全軟體 | PW | Produce Well-Secured Software | 「做得夠安全嗎?」 |
| 回應漏洞 | RV | Respond to Vulnerabilities | 「出事怎麼辦?」 |
常見問題 FAQ
Q1:SSDF 是強制性的嗎?
對於一般企業,SSDF 是自願採用的最佳實務。但如果你要賣軟體給美國聯邦政府,根據行政命令 EO 14028,就需要符合 SSDF 的要求。
Q2:小公司也需要導入 SSDF 嗎?
SSDF 是可擴展的!你不需要一次做完所有項目。可以根據公司規模和風險程度,挑選最重要的項目先做。
Q3:SSDF 和 ISO 27001 有什麼不同?
| 框架 | 重點 |
|---|---|
| SSDF | 專注於軟體開發過程的安全 |
| ISO 27001 | 整體資訊安全管理系統(涵蓋範圍更廣) |
兩者可以互補,SSDF 可以作為 ISO 27001 在軟體開發領域的細部實作指南。
Q4:有什麼工具可以幫助導入 SSDF?
| 類別 | 工具範例 |
|---|---|
| SAST(靜態掃描) | SonarQube, Checkmarx, Fortify |
| DAST(動態掃描) | OWASP ZAP, Burp Suite |
| SCA(軟體組成分析) | Snyk, Dependabot, OWASP Dependency-Check |
| SBOM 產生 | Syft, CycloneDX |
| 秘密掃描 | GitLeaks, TruffleHog |
總結:讓安全成為習慣
NIST SSDF 不是要讓你的開發流程變得更複雜,而是要讓安全成為開發的一部分。就像便當店把衛生習慣內化到日常作業一樣,當安全變成習慣,就不會覺得麻煩了。
記住這四個關鍵字:
- 準備(PO):人員、流程、工具都要到位
- 保護(PS):程式碼和發布物要保護好
- 生產(PW):每個環節都要考慮安全
- 回應(RV):出問題要有應變能力
現在就開始檢視你的開發流程,看看哪些地方可以「左移」改善吧!