<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>身分安全 on Tarragon</title><link>https://tarrragon.github.io/blog/tags/%E8%BA%AB%E5%88%86%E5%AE%89%E5%85%A8/</link><description>Recent content in 身分安全 on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Wed, 29 Jul 2026 00:00:00 +0800</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/tags/%E8%BA%AB%E5%88%86%E5%AE%89%E5%85%A8/index.xml" rel="self" type="application/rss+xml"/><item><title>Credential Stuffing（憑證填充）</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/credential-stuffing/</link><pubDate>Wed, 29 Jul 2026 00:00:00 +0800</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/credential-stuffing/</guid><description>&lt;p>Credential stuffing 的核心概念是「拿在別處外洩的帳號密碼組合，到這個服務逐一試登入」。它利用的是同一個人在多個服務用同一組密碼，因此攻擊者不需要猜——手上的每一組都曾經是某人的真密碼，&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/authentication/" data-link-title="Authentication" data-link-desc="說明系統如何確認呼叫者身份">authentication&lt;/a> 這一層因此看到的是一次完全合法的登入。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>這一類攻擊與暴力破解共用同一個入口（登入端點），防護手段卻不同，因為它們消耗的資源不同。暴力破解對單一帳號嘗試大量密碼，按帳號計數的節流攔得住；credential stuffing 對大量帳號各試一兩組，每個帳號的失敗次數都在門檻之下，同一套機制因此看不到它。節流與帳號鎖定要分開看——鎖定本身可以被當成阻斷服務的手段（對著別人的帳號連續試錯就能把人鎖在外面），所以主線是延遲重試而非直接鎖。&lt;/p>
&lt;p>它也定義了密碼儲存的能力邊界。&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/salt/" data-link-title="Salt" data-link-desc="說明 salt 如何讓相同的密碼產生不同的雜湊值，以及它擋掉哪一類攻擊">salt&lt;/a> 與 work factor 提高的是「猜一次要付多少代價」，而這一類攻擊的密碼是已知的、不需要猜——&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/password-storage-and-work-factor/" data-link-title="7.30 使用者密碼儲存：參數會過期的那一類原語" data-link-desc="決定密碼用哪種雜湊與 work factor、或懷疑既有參數已經失效時，用來定參數、判斷合規要求有沒有鎖死選項、排複查節奏與規劃升級路徑">7.30 使用者密碼儲存&lt;/a> 的參數調到頂也擋不住它。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>登入端點的整體失敗率上升而個別帳號的失敗次數正常，是這一類的特徵訊號。其他常見形態：登入請求的來源位址分散但行為一致（相同的請求間隔、相同的 user agent）、大量帳號在短時間內首次從陌生地區登入成功、以及「帳號不存在」與「密碼錯誤」兩種回應的比例異常——後者代表攻擊者手上的清單與自己的使用者群重疊度高。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>防護的著力點在密碼之外。可用的機制包括比對外洩密碼清單、要求第二因子讓密碼正確也不足以登入、按來源與行為特徵而非按帳號做速率限制、以及對成功登入做異常判讀（新裝置、新地區、與平常不同的時段）。比對清單的時點有兩個而非一個：註冊與變更密碼時比對擋得住新設的那些，既有帳號的密碼在設定之後才外洩，那一批要在成功登入當下再比對一次才接得住。&lt;/p>
&lt;p>判斷自己的暴露程度，看的是使用者群體與大型外洩事件的重疊——面向一般消費者的服務重疊度最高，因為同一批人在數十個服務用同一組密碼。相鄰概念見 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/authentication/" data-link-title="Authentication" data-link-desc="說明系統如何確認呼叫者身份">authentication&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/step-up-authentication/" data-link-title="Step-Up Authentication（升階驗證）" data-link-desc="登入成功不等於高權限操作可被信任時、在關鍵操作點插入額外驗證的設計位置">step-up authentication&lt;/a>，登入節奏的判讀與處置見 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/identity-access-boundary/#%e7%b5%82%e7%ab%af%e4%bd%bf%e7%94%a8%e8%80%85%e7%9a%84%e7%99%bb%e5%85%a5%e7%af%80%e5%a5%8f" data-link-title="7.2 身分與授權邊界" data-link-desc="以問題驅動方式整理身分、授權、會話與供應商身分鏈">7.2 終端使用者的登入節奏&lt;/a>，登入方式本身的選型見 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/authentication-approach-selection/" data-link-title="7.31 認證方式選型：可離線猜測的材料最後落在哪裡" data-link-desc="要做登入功能、在自建帳號與委派身分與 passkey 之間決定時，用來定位每一種做法把可離線猜測的材料移到了哪裡">7.31 認證方式選型&lt;/a>。&lt;/p>
&lt;p>把可重用的共享秘密整個換掉是這一類攻擊的結構性解法，因為外洩清單裡的值在服務端對不上任何東西，見 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/passkey/" data-link-title="Passkey" data-link-desc="要用金鑰對取代密碼、或判斷已導入的 passkey 實際擋掉了什麼時，用來定位它的保護落在哪一段、上限由哪條路徑決定">passkey&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Credential stuffing 的核心概念是「拿在別處外洩的帳號密碼組合，到這個服務逐一試登入」。它利用的是同一個人在多個服務用同一組密碼，因此攻擊者不需要猜——手上的每一組都曾經是某人的真密碼，<a href="/blog/backend/knowledge-cards/authentication/" data-link-title="Authentication" data-link-desc="說明系統如何確認呼叫者身份">authentication</a> 這一層因此看到的是一次完全合法的登入。</p>
<h2 id="概念位置">概念位置</h2>
<p>這一類攻擊與暴力破解共用同一個入口（登入端點），防護手段卻不同，因為它們消耗的資源不同。暴力破解對單一帳號嘗試大量密碼，按帳號計數的節流攔得住；credential stuffing 對大量帳號各試一兩組，每個帳號的失敗次數都在門檻之下，同一套機制因此看不到它。節流與帳號鎖定要分開看——鎖定本身可以被當成阻斷服務的手段（對著別人的帳號連續試錯就能把人鎖在外面），所以主線是延遲重試而非直接鎖。</p>
<p>它也定義了密碼儲存的能力邊界。<a href="/blog/backend/knowledge-cards/salt/" data-link-title="Salt" data-link-desc="說明 salt 如何讓相同的密碼產生不同的雜湊值，以及它擋掉哪一類攻擊">salt</a> 與 work factor 提高的是「猜一次要付多少代價」，而這一類攻擊的密碼是已知的、不需要猜——<a href="/blog/backend/07-security-data-protection/password-storage-and-work-factor/" data-link-title="7.30 使用者密碼儲存：參數會過期的那一類原語" data-link-desc="決定密碼用哪種雜湊與 work factor、或懷疑既有參數已經失效時，用來定參數、判斷合規要求有沒有鎖死選項、排複查節奏與規劃升級路徑">7.30 使用者密碼儲存</a> 的參數調到頂也擋不住它。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>登入端點的整體失敗率上升而個別帳號的失敗次數正常，是這一類的特徵訊號。其他常見形態：登入請求的來源位址分散但行為一致（相同的請求間隔、相同的 user agent）、大量帳號在短時間內首次從陌生地區登入成功、以及「帳號不存在」與「密碼錯誤」兩種回應的比例異常——後者代表攻擊者手上的清單與自己的使用者群重疊度高。</p>
<h2 id="設計責任">設計責任</h2>
<p>防護的著力點在密碼之外。可用的機制包括比對外洩密碼清單、要求第二因子讓密碼正確也不足以登入、按來源與行為特徵而非按帳號做速率限制、以及對成功登入做異常判讀（新裝置、新地區、與平常不同的時段）。比對清單的時點有兩個而非一個：註冊與變更密碼時比對擋得住新設的那些，既有帳號的密碼在設定之後才外洩，那一批要在成功登入當下再比對一次才接得住。</p>
<p>判斷自己的暴露程度，看的是使用者群體與大型外洩事件的重疊——面向一般消費者的服務重疊度最高，因為同一批人在數十個服務用同一組密碼。相鄰概念見 <a href="/blog/backend/knowledge-cards/authentication/" data-link-title="Authentication" data-link-desc="說明系統如何確認呼叫者身份">authentication</a> 與 <a href="/blog/backend/knowledge-cards/step-up-authentication/" data-link-title="Step-Up Authentication（升階驗證）" data-link-desc="登入成功不等於高權限操作可被信任時、在關鍵操作點插入額外驗證的設計位置">step-up authentication</a>，登入節奏的判讀與處置見 <a href="/blog/backend/07-security-data-protection/identity-access-boundary/#%e7%b5%82%e7%ab%af%e4%bd%bf%e7%94%a8%e8%80%85%e7%9a%84%e7%99%bb%e5%85%a5%e7%af%80%e5%a5%8f" data-link-title="7.2 身分與授權邊界" data-link-desc="以問題驅動方式整理身分、授權、會話與供應商身分鏈">7.2 終端使用者的登入節奏</a>，登入方式本身的選型見 <a href="/blog/backend/07-security-data-protection/authentication-approach-selection/" data-link-title="7.31 認證方式選型：可離線猜測的材料最後落在哪裡" data-link-desc="要做登入功能、在自建帳號與委派身分與 passkey 之間決定時，用來定位每一種做法把可離線猜測的材料移到了哪裡">7.31 認證方式選型</a>。</p>
<p>把可重用的共享秘密整個換掉是這一類攻擊的結構性解法，因為外洩清單裡的值在服務端對不上任何東西，見 <a href="/blog/backend/knowledge-cards/passkey/" data-link-title="Passkey" data-link-desc="要用金鑰對取代密碼、或判斷已導入的 passkey 實際擋掉了什麼時，用來定位它的保護落在哪一段、上限由哪條路徑決定">passkey</a>。</p>
]]></content:encoded></item><item><title>Authorization Scope（授權範圍）</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/authorization-scope/</link><pubDate>Wed, 29 Jul 2026 00:00:00 +0800</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/authorization-scope/</guid><description>&lt;p>Authorization Scope 的核心概念是把一次授權表達成一組具名的範圍，讓「這個呼叫方獲准做什麼」在授予當下就寫成可列舉的清單。它與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/authorization/" data-link-title="Authorization" data-link-desc="說明授權如何判斷誰能對哪些資源執行哪些操作">authorization&lt;/a> 的分工是：authorization 回答單一請求該不該放行，scope 是那個判斷所依據的授予內容本身。OAuth 系列協定用 &lt;code>scope&lt;/code> 這個參數承載它，而同樣的結構在 API key 的權限勾選、雲平台的角色政策、資料庫的授權語句裡都成立。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Scope 的顆粒由&lt;strong>發行方&lt;/strong>決定，這是它與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/least-privilege/" data-link-title="Least Privilege" data-link-desc="說明身份、服務與人員只應取得完成工作所需的最小權限">least-privilege&lt;/a> 之間最常被忽略的落差。最小權限是使用方的原則，而使用方能挑的選項只有發行方提供的那幾個——想只給讀取而選項只有「全部」時，最小權限這條原則在這一格無法落實。判斷自己被卡在哪一側，看的是需求描述得出來的動作與可勾選的項目之間差幾層。&lt;/p>
&lt;p>自己就是發行方時（內部 API 多半如此）顆粒可以自己切，約束因此換成另一件事：重切 scope 要每個既有使用方跟著遷移，顆粒切錯是向後相容問題而非「沒得選」問題，處置見 &lt;a href="https://tarrragon.github.io/blog/backend/11-api-design/backward-compatibility-discipline/" data-link-title="11.6 向後相容的變更紀律" data-link-desc="哪些變更算 breaking、相容性檢查放人工還是 CI、檢查粒度怎麼選 — 讓介面變更可審可擋的日常紀律">11.6 向後相容的變更紀律&lt;/a>。&lt;/p>
&lt;p>授予的範圍與實際用到的範圍之間的差額，就是白白多承擔的暴露面，而它決定了發行方出事時傳導進來的半徑，收斂點見 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/blast-radius/" data-link-title="Blast Radius" data-link-desc="說明事故影響面如何估算與隔離">blast radius&lt;/a>。這個差額在正常運作期間沒有任何徵兆——沒被用到的權限不會產生錯誤、不會拖慢回應、也不會出現在任何監控上。&lt;/p>
&lt;p>Scope 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/token-revocation/" data-link-title="Token Revocation" data-link-desc="說明事件中如何撤銷 token，縮短可利用窗口">token revocation&lt;/a> 解的是相鄰但不同的問題：scope 限制的是這張憑證能碰到什麼，撤銷處理的是它什麼時候失效。兩者獨立成立——範圍收得很緊的憑證仍需要撤銷路徑，而撤銷很快的憑證在有效期內仍然由 scope 決定它能做多少事。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要正視 scope 設計的訊號是整合被授予的權限清單與它實際呼叫過的端點對不起來。取一段時間的存取日誌按端點去重，沒被呼叫過的權限就是超出實際使用的部分。&lt;/p>
&lt;p>發行方那一側的訊號是 scope 的名稱取自產品功能而非資源與動作（&lt;code>admin&lt;/code>、&lt;code>integration&lt;/code>、&lt;code>full_access&lt;/code> 這類）。名稱裡看不出它涵蓋哪些資源與哪些動作時，使用方沒有辦法判斷自己需要的是哪一個，於是傾向勾選看起來一定夠用的那一個——這一步不需要判斷發行方當初為什麼這樣命名，觀察得到的就足以決定處置。&lt;/p>
&lt;p>另一種形態是 scope 存在但顆粒只有兩級：全部或無。這一格常見於早期就開放 API 而權限模型尚未拆分的產品，使用方能做的取捨是接受粗顆粒、在自己這邊架一層降權的中間層、或換供應商。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>收斂 scope 的成本最低的時機是授予當下。整合上線之後縮小權限要協調對方調整程式碼，而這道協調成本讓「先給寬鬆權限之後再收」的收斂動作缺少發動的時機——沒有任何一方的既定工作會自然帶出它。成本次低的窗口是雙方本來就要動憑證的時刻：整合升級到新版介面、對方的憑證到期要重新授權、供應商事件之後的強制輪替。&lt;/p>
&lt;p>作為發行方設計 scope 時，一個 scope 要對應一組可列舉的資源與動作，並讓讀與寫分屬不同的 scope。顆粒切得太細的代價是使用方要勾一長串、容易漏；切得太粗的代價由每一個使用方承擔，而他們沒有辦法自行修正。&lt;/p>
&lt;p>代理場景的範圍是另一條判斷：一個系統代表某個使用者呼叫下游時，交集怎麼算、誰負責算、驗證方怎麼實測，都在 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/delegated-credential-selection/" data-link-title="7.33 委任型憑證：關係寫進憑證，還是留給驗證方拼湊" data-link-desc="一個系統要代表特定使用者呼叫下游時，用來判斷這層關係該由發行方寫進憑證還是由各驗證方各自認定、以及換過去之後撤銷粒度實際落在哪裡">7.33 委任型憑證&lt;/a>，本卡不重述。第三方整合的範圍與事件傳導半徑的關係見 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/api-authentication-trust-boundaries/" data-link-title="7.29 API 認證的信任邊界分層" data-link-desc="一個請求同時牽涉人、呼叫系統與跨系統身分對應時，用來判斷各層的撤銷粒度差在哪、混層後會失去什麼、以及規模不足時哪幾層可以合併">7.29 API 認證的信任邊界分層&lt;/a>，機器身分那一側的分域治理見 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/secrets-and-machine-credential-governance/" data-link-title="7.6 秘密管理與機器憑證治理" data-link-desc="以問題驅動方式整理 secret、token、key 與機器身份治理">7.6 秘密管理與機器憑證治理&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Authorization Scope 的核心概念是把一次授權表達成一組具名的範圍，讓「這個呼叫方獲准做什麼」在授予當下就寫成可列舉的清單。它與 <a href="/blog/backend/knowledge-cards/authorization/" data-link-title="Authorization" data-link-desc="說明授權如何判斷誰能對哪些資源執行哪些操作">authorization</a> 的分工是：authorization 回答單一請求該不該放行，scope 是那個判斷所依據的授予內容本身。OAuth 系列協定用 <code>scope</code> 這個參數承載它，而同樣的結構在 API key 的權限勾選、雲平台的角色政策、資料庫的授權語句裡都成立。</p>
<h2 id="概念位置">概念位置</h2>
<p>Scope 的顆粒由<strong>發行方</strong>決定，這是它與 <a href="/blog/backend/knowledge-cards/least-privilege/" data-link-title="Least Privilege" data-link-desc="說明身份、服務與人員只應取得完成工作所需的最小權限">least-privilege</a> 之間最常被忽略的落差。最小權限是使用方的原則，而使用方能挑的選項只有發行方提供的那幾個——想只給讀取而選項只有「全部」時，最小權限這條原則在這一格無法落實。判斷自己被卡在哪一側，看的是需求描述得出來的動作與可勾選的項目之間差幾層。</p>
<p>自己就是發行方時（內部 API 多半如此）顆粒可以自己切，約束因此換成另一件事：重切 scope 要每個既有使用方跟著遷移，顆粒切錯是向後相容問題而非「沒得選」問題，處置見 <a href="/blog/backend/11-api-design/backward-compatibility-discipline/" data-link-title="11.6 向後相容的變更紀律" data-link-desc="哪些變更算 breaking、相容性檢查放人工還是 CI、檢查粒度怎麼選 — 讓介面變更可審可擋的日常紀律">11.6 向後相容的變更紀律</a>。</p>
<p>授予的範圍與實際用到的範圍之間的差額，就是白白多承擔的暴露面，而它決定了發行方出事時傳導進來的半徑，收斂點見 <a href="/blog/backend/knowledge-cards/blast-radius/" data-link-title="Blast Radius" data-link-desc="說明事故影響面如何估算與隔離">blast radius</a>。這個差額在正常運作期間沒有任何徵兆——沒被用到的權限不會產生錯誤、不會拖慢回應、也不會出現在任何監控上。</p>
<p>Scope 與 <a href="/blog/backend/knowledge-cards/token-revocation/" data-link-title="Token Revocation" data-link-desc="說明事件中如何撤銷 token，縮短可利用窗口">token revocation</a> 解的是相鄰但不同的問題：scope 限制的是這張憑證能碰到什麼，撤銷處理的是它什麼時候失效。兩者獨立成立——範圍收得很緊的憑證仍需要撤銷路徑，而撤銷很快的憑證在有效期內仍然由 scope 決定它能做多少事。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要正視 scope 設計的訊號是整合被授予的權限清單與它實際呼叫過的端點對不起來。取一段時間的存取日誌按端點去重，沒被呼叫過的權限就是超出實際使用的部分。</p>
<p>發行方那一側的訊號是 scope 的名稱取自產品功能而非資源與動作（<code>admin</code>、<code>integration</code>、<code>full_access</code> 這類）。名稱裡看不出它涵蓋哪些資源與哪些動作時，使用方沒有辦法判斷自己需要的是哪一個，於是傾向勾選看起來一定夠用的那一個——這一步不需要判斷發行方當初為什麼這樣命名，觀察得到的就足以決定處置。</p>
<p>另一種形態是 scope 存在但顆粒只有兩級：全部或無。這一格常見於早期就開放 API 而權限模型尚未拆分的產品，使用方能做的取捨是接受粗顆粒、在自己這邊架一層降權的中間層、或換供應商。</p>
<h2 id="設計責任">設計責任</h2>
<p>收斂 scope 的成本最低的時機是授予當下。整合上線之後縮小權限要協調對方調整程式碼，而這道協調成本讓「先給寬鬆權限之後再收」的收斂動作缺少發動的時機——沒有任何一方的既定工作會自然帶出它。成本次低的窗口是雙方本來就要動憑證的時刻：整合升級到新版介面、對方的憑證到期要重新授權、供應商事件之後的強制輪替。</p>
<p>作為發行方設計 scope 時，一個 scope 要對應一組可列舉的資源與動作，並讓讀與寫分屬不同的 scope。顆粒切得太細的代價是使用方要勾一長串、容易漏；切得太粗的代價由每一個使用方承擔，而他們沒有辦法自行修正。</p>
<p>代理場景的範圍是另一條判斷：一個系統代表某個使用者呼叫下游時，交集怎麼算、誰負責算、驗證方怎麼實測，都在 <a href="/blog/backend/07-security-data-protection/delegated-credential-selection/" data-link-title="7.33 委任型憑證：關係寫進憑證，還是留給驗證方拼湊" data-link-desc="一個系統要代表特定使用者呼叫下游時，用來判斷這層關係該由發行方寫進憑證還是由各驗證方各自認定、以及換過去之後撤銷粒度實際落在哪裡">7.33 委任型憑證</a>，本卡不重述。第三方整合的範圍與事件傳導半徑的關係見 <a href="/blog/backend/07-security-data-protection/api-authentication-trust-boundaries/" data-link-title="7.29 API 認證的信任邊界分層" data-link-desc="一個請求同時牽涉人、呼叫系統與跨系統身分對應時，用來判斷各層的撤銷粒度差在哪、混層後會失去什麼、以及規模不足時哪幾層可以合併">7.29 API 認證的信任邊界分層</a>，機器身分那一側的分域治理見 <a href="/blog/backend/07-security-data-protection/secrets-and-machine-credential-governance/" data-link-title="7.6 秘密管理與機器憑證治理" data-link-desc="以問題驅動方式整理 secret、token、key 與機器身份治理">7.6 秘密管理與機器憑證治理</a>。</p>
]]></content:encoded></item></channel></rss>