為了防止網路攻擊,Nonce(Number Used Once) 和 CSRF Token (Cross-Site Request Forgery Token) 是現代網站兩種常見且重要的防護機制。這兩者雖然都與網頁安全性相關,但其設計目標、解決的問題和應用場景卻各有不同。本文會介紹這兩種機制的運作方式,並探討它們的差異以及適用情境。
Nonce 是什麼?為什麼需要它?
Nonce 是一個僅使用一次的隨機字串,用於確保每個請求或操作的唯一性。它通常由伺服器生成,並附加到每個請求中。透過在伺服器端存儲並驗證 Nonce,能有效防止攻擊者攔截請求後重複執行,確保請求僅執行一次。
舉例來說,使用者在網頁表單中多次點擊提交按鈕可能導致多次訂單生成,而 Nonce 機制能阻止伺服器處理重複請求。同時也可以防止重放攻擊(Replay Attack),這類攻擊通常試圖利用攔截到的合法請求執行多次,造成系統不當操作。
Nonce 有點像是是活動入場券。每張票都有唯一的編號,僅能使用一次來進入活動場地。當票在入口被掃描後,系統會將其標記為已使用,確保相同的票無法再次使用進入。
Nonce 的應用場景
場景 1: 避免表單重複提交
在需要提交訂單的場景中,用戶可能不小心多次點擊提交按鈕,而每次提交都會產生一個新的請求,伺服器在沒有驗證機制的情況下,可能會重複處理這些請求,進而導致多筆訂單或是重複執行的任務。
為了解決這個問題,可以使用 Nonce 確保每次表單提交請求的唯一性。伺服器端會生成一個隨機的 Nonce,並將其嵌入到表單中,用戶提交後,伺服器驗證該 Nonce 是否已被使用,若已使用,則拒絕該請求。
比如在購物網站,用戶在提交訂單後,可能不小心多次點擊「提交」按鈕。伺服器端利用 Nonce 驗證每次請求是否唯一,確保訂單不會被重複提交。
場景 1 實作
表單
<form method="POST" action="/submit-order">
<input type="hidden" name="nonce" value="123456789abcdef">
<input type="text" name="orderDetails">
<button type="submit">提交訂單</button>
</form>
伺服器端檢查
if (isNonceValid(request.body.nonce)) {
processOrder();
invalidateNonce(request.body.nonce);
} else {
throw new Error("Invalid nonce!");
}
場景 2: 防止重放攻擊
攻擊者可能攔截合法的 API 請求,並多次發送相同的請求以實現惡意操作。為了防止這類重放攻擊,可以使用 Nonce 確保每個請求的唯一性。伺服器通過檢查 Nonce 是否已被使用來判斷請求是否有效。
假設有一個執行扣款功能的 RESTful API,若扣款請求被攔截到,攔截者可以惡意發送同樣扣款請求多次。這時就需要 nonce 來確保最多只會被扣款一次。
場景 2 實作
Request
POST /transactions HTTP/1.1
Host: example.com
Content-Type: application/json
Authorization: Bearer <access_token>
{
"nonce": "abcdef123456",
"amount": 100.00,
"account_id": "1234567890",
"transaction_type": "deduction"
}
伺服器端
if (isNonceValid(request.body.nonce)) {
executeTransaction(request.body.amount, request.body.account_id, request.body.transaction_type);
invalidateNonce(request.body.nonce);
} else {
throw new Error("Invalid or reused nonce!");
}
可以看到場景 1 與 場景 2 的伺服器端是一樣的邏輯,因為目的都是要避免重複的請求。
特別場景: 內容安全策略(CSP)
Nonce 在 Content Security Policy (CSP) 中的用法有點不同,主要是用於控制 inline script 或樣式的執行。伺服器會生成 Nonce,並將其同時包含在 CSP 標頭和授權的 <script>
或 <style>
標籤中。這個過程與先前介紹的 Nonce 機制類似,但驗證的動作發生在瀏覽器中。瀏覽器會強制執行 CSP 規則,確保只有帶有正確 Nonce 的腳本或樣式被執行,阻止未經授權的內容。
例如,一個顯示使用者特定數據的網頁可能需要動態生成的 inline JavaScript。透過在伺服器生成的 CSP 標頭和授權的腳本中嵌入 Nonce,只有預期的 script 會被執行,而未授權的 script 將被阻止。這確保了關鍵的 inline script 能夠安全地運行,同時避免頁面受到惡意 script 注入的威脅。
特別場景 CSP 實作
伺服器設置 CSP 標頭
Content-Security-Policy: script-src 'self' 'nonce-abcdef123456';
HTML
<script nonce="abcdef123456">
console.log('This is a secure script.');
</script>
<script>
console.log('This script will be blocked by CSP.');
</script>
結果:
- 僅有包含正確 Nonce 的 inline script 會被執行。
- 其他 script 將被 CSP 攔截並阻止。
- 最後只會印出
This is a secure script.
CSRF Token 是什麼?為什麼需要它?
CSRF Token(Cross-Site Request Forgery Token)是一種專門用於防範跨站請求偽造(CSRF)攻擊的安全措施。目的在於驗證每次請求是否來自用戶的合法操作,而非來自惡意網站的誘導請求。
CSRF 攻擊的典型場景是利用受害者的已登入狀態,在未經授權或不知情的情況下,通過受害者的瀏覽器向受信任的網站發送惡意請求。例如,攻擊者可能會偽造請求進行未經授權的資金轉帳、更改密碼或刪除用戶賬戶等高風險操作。
CSRF Token 通常由伺服器生成並與 session 綁定。伺服器將 Token 發送至用戶瀏覽器,並要求用戶在每次請求中附加此 Token。伺服器在接收請求時會驗證 Token 是否與用戶會話中的值匹配。如果 Token 無效或缺失,請求將被拒絕。
該機制通過驗證請求的合法性,阻止攻擊者利用跨站方式冒充用戶身份進行敏感操作,以提升應用的安全性。
CSRF Token 的應用場景
場景: 增加敏感操作的安全性
攻擊者可能利用用戶的已登錄狀態發起資金轉帳等高風險操作。為了防止這類情況,CSRF Token 是一種有效的驗證方式。
範例情境:用戶需通過 CSRF Token 保護資金轉帳請求。
實作
前端表單
<form method="POST" action="/transfer-funds">
<input type="hidden" name="csrf_token" value="abcd1234efgh">
<input type="number" name="amount" placeholder="轉帳金額">
<input type="text" name="to_account" placeholder="收款帳號">
<button type="submit">提交轉帳</button>
</form>
伺服器端
if (request.body.csrf_token === session.csrf_token) {
processTransfer(request.body.amount, request.body.to_account);
} else {
throw new Error("Invalid CSRF token!");
}
附註:CSRF 通常依賴於 session,因此有的 CSRF Token 會放在 HTTP 標頭(header)中,或是 <head>
下,也可能如範例一樣嵌入在隱藏的表單欄位中。實際存放位置並不關鍵,最重要的是在進行操作時,確保該 Token 能正確傳遞到伺服器,並由伺服器驗證其合法性,就能有效的確保請求的真實性。
總結
Nonce 與 CSRF Token 的差異比較
特性 | Nonce | CSRF Token |
---|---|---|
主要目標 | 防止重放攻擊、表單重複提交 | 防止跨站請求偽造攻擊 |
用法 | 確保請求的唯一性 | 驗證請求的合法性 |
實現層級 | 常用於 API 或表單提交 | 常用於 API 或表單提交 |
是否會重複使用 | 不會重複使用(單次有效) | 可能會重複使用(如多次提交表單的 session 中) |
- Nonce 用在確保請求的唯一性,避免重複的請求,或搭配 CSP 確保合法 script 的執行。
- CSRF Token 用在防範跨站請求偽造(Cross-Site Request Forgery),透過驗證每個請求中包含的隨機字串是否與伺服器生成的匹配,確保請求來自合法用戶。
Nonce 與 CSRF Token 是否可以一起使用?
可以,兩種機制是為了解決不同問題而存在的,並且使用上也不衝突。依據要解決的問題來實作即可。