在前幾天,我們已經示範了「不受控的 Webhook」與「MCP-SSE 攻擊」。
今天,我們來到一個新的場景:駭客試圖呼叫敏感 Workflow。
這一次,我們要實際測試我們在 n8n 上的設計,看看是否能攔截攻擊。
curl -X POST "http://your-n8n-domain/webhook/hello" \
-H "Content-Type: application/json" \
-d '{"prompt":"Hello"}'
預期結果:HTTP 401
curl -X POST "http://your-n8n-domain/webhook/hello" \
-H "x-api-key: wrongkey" -H "Content-Type: application/json" \
-d '{"prompt":"Hello"}'
預期結果:HTTP 401
curl -X POST "http://your-n8n-domain/webhook/hello" \
-H "x-api-key: webhook_text_123" -H "Content-Type: application/json" \
-d '{"prompt":"DROP TABLE users; --"}'
預期結果:HTTP 400,回應 Forbidden Keyword
curl -X POST "http://your-n8n-domain/webhook/hello" \
-H "x-api-key: webhook_text_123" -H "Content-Type: application/json" \
-d '{"prompt":"Hello World"}'
預期結果:HTTP 200,進入 True Branch,觸發後續 HTTP Request
const headers = $json.headers || {};
const body = $json.body || {};
const prompt = body?.prompt || "";
// === API Key 驗證 ===
const apiKey = String(headers["x-api-key"] || "").trim();
const validKey = $env.API_KEY;
if (apiKey !== validKey) {
return [{
json: {
statusCode: 401,
valid: false,
message: "Invalid API Key"
}
}];
}
// === 輸入驗證 ===
const blacklist = ["drop table", "exec(", "<script>", "rm -rf", "shutdown"];
// 長度限制
if (prompt.length > 500) {
return [{
json: {
statusCode: 400,
valid: false,
message: "Prompt too long"
}
}];
}
// 黑名單檢查
for (const keyword of blacklist) {
if (prompt.toLowerCase().includes(keyword)) {
return [{
json: {
statusCode: 400,
valid: false,
message: `Forbidden keyword: ${keyword}`
}
}];
}
}
// === 驗證通過 ===
return [{
json: {
statusCode: 200,
valid: true,
message: "Authorized & Valid request",
prompt
}
}];
valid is equal to true
如果輸入驗證沒問題才放進Requset HTTP
狀況 | 攻擊者行為 | 系統反應 |
---|---|---|
無 API Key | {"prompt":"Hello"} |
401 Unauthorized |
API Key 錯誤 | x-api-key: wrong |
401 Unauthorized |
惡意 Payload | {"prompt":"DROP TABLE"} |
400 Invalid input |
合法請求 | {"prompt":"Hello World"} |
200 → True Branch 執行 |
這次模擬清楚展示了:
透過這種設計,敏感的 Workflow 只會在「授權 + 輸入合法」時才會被觸發,大幅降低了攻擊面。