自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

瀏覽器中存儲訪問令牌的最佳實踐

存儲 存儲架構(gòu)
使用OAuth和訪問令牌可以最好地保護(hù)API訪問。但是,JavaScript應(yīng)用程序處于不利地位。瀏覽器中沒有安全的令牌存儲解決方案。所有可用的解決方案在某種程度上都容易受到XSS攻擊。因此,確保任何應(yīng)用程序安全的首要任務(wù)應(yīng)該是防止XSS漏洞。

瀏覽器提供了各種持久化數(shù)據(jù)的解決方案。當(dāng)存儲令牌時,您應(yīng)該權(quán)衡存儲選擇與安全風(fēng)險。

圖片

譯自Best Practices for Storing Access Tokens in the Browser。

web應(yīng)用程序不是靜態(tài)站點,而是靜態(tài)內(nèi)容和動態(tài)內(nèi)容的精心組合。更常見的是,web應(yīng)用程序邏輯在瀏覽器中運行。與從服務(wù)器獲取所有內(nèi)容不同,應(yīng)用程序在瀏覽器中運行JavaScript,從后端API獲取數(shù)據(jù),并相應(yīng)地更新web應(yīng)用程序呈現(xiàn)。

為了保護(hù)數(shù)據(jù)訪問,組織應(yīng)該采用OAuth 2.0。通過OAuth 2.0,JavaScript應(yīng)用程序需要在對API的每個請求中添加訪問令牌。出于可用性原因,JavaScript應(yīng)用程序通常不會按需請求訪問令牌,而是存儲它。問題是,如何在JavaScript中獲取這樣的訪問令牌?當(dāng)您獲取一個令牌時,應(yīng)用程序應(yīng)該在哪里存儲令牌,以便在需要時將其添加到請求中?

本文討論了瀏覽器中可用的各種存儲解決方案,并突出了與每種選擇相關(guān)的安全風(fēng)險。在審查威脅之后,它描述了一種解決方案,以提供最佳的瀏覽器安全選項,用于必須與OAuth保護(hù)的API集成的JavaScript應(yīng)用程序。

獲取訪問令牌

在應(yīng)用程序可以存儲訪問令牌之前,它需要先獲取一個令牌。當(dāng)前的最佳實踐建議通過“授權(quán)碼流”這一方式來獲取訪問令牌: 授權(quán)碼流是一個兩步流程,首先從用戶那里收集一個授權(quán)許可——授權(quán)碼,然后應(yīng)用程序在后臺通道中用授權(quán)碼交換訪問令牌。這個請求稱為令牌請求,例子如下:

const accessToken = await fetch(OAuthServerTokenEndpoint, {
method: "POST",
// token request with authorization code and PKCE
// submits data in as x-www-form-urlencoded encoded format
body: new URLSearchParams({
 client_id: "example-client",
grant_type: "authorization_code",
code: authorization_code,
 code_verifier: pkce_code_verifier
})
})
// server responds with JSON object
.then (response => response.json())
.then (tokenResponse => {
  // parse access token from response
  if (tokenResponse.accessToken) {
    return tokenResponse.accessToken;
  } // else handle error response
})
.catch( 
// handle network error
)

請注意,任何人都可以檢查瀏覽器加載的資源,包括任何JavaScript代碼。因此,任何用JavaScript實現(xiàn)的OAuth客戶端都被認(rèn)為是一個公開客戶端——一個無法保密的客戶端,因此在令牌請求期間無法進(jìn)行身份驗證。然而,代碼交換的證明密鑰(Proof Key for Code Exchange,PKCE)提供了一種方法來確保公開客戶端的授權(quán)碼流的安全性。為了減輕與授權(quán)碼相關(guān)的風(fēng)險,在使用授權(quán)碼流時,始終應(yīng)用PKCE。

瀏覽器威脅

跨站請求偽造(CSRF)

在跨站請求偽造(CSRF)攻擊中,惡意行為者會欺騙用戶通過瀏覽器無意中執(zhí)行惡意請求。例如,攻擊者可以在網(wǎng)站中嵌入精心設(shè)計的圖像源字符串,以觸發(fā)瀏覽器運行GET請求,或者在惡意網(wǎng)站上添加表單,以觸發(fā)POST請求。在任何情況下,瀏覽器都可能會自動將cookie(包括單點登錄cookie)添加到這樣的請求中。

CSRF攻擊也被稱為“會話騎乘”,因為攻擊者通常會利用用戶的經(jīng)過身份驗證的會話來進(jìn)行惡意請求。因此,攻擊者可以默默地代表用戶執(zhí)行請求,并調(diào)用用戶可以調(diào)用的任何端點。然而,攻擊者無法讀取響應(yīng),所以他們通常以一次性狀態(tài)更改請求為目標(biāo),如更新用戶的密碼。

跨站腳本(XSS)

跨站腳本(XSS)漏洞允許攻擊者將惡意的客戶端代碼注入到一個本來受信任的網(wǎng)站中。例如,如果用戶輸入生成的輸出沒有被適當(dāng)清理,web應(yīng)用程序的任何地方都可能存在漏洞。瀏覽器會自動在受信任的網(wǎng)站的上下文中運行惡意代碼。

XSS攻擊可用于竊取訪問令牌和刷新令牌,或執(zhí)行CSRF攻擊。不過,XSS攻擊有一個時間窗口,因為它們只能在有限的時間段內(nèi)運行,如令牌的有效期內(nèi),或者打開的選項卡存在漏洞的時長。

即使在XSS無法用于檢索訪問令牌的情況下,攻擊者也可以利用XSS漏洞通過會話騎乘向有保護(hù)的Web端點發(fā)送經(jīng)過身份驗證的請求。然后,攻擊者可以偽裝成用戶,調(diào)用用戶可以調(diào)用的任何后端端點,并造成嚴(yán)重?fù)p害。

瀏覽器中的存儲解決方案

應(yīng)用程序收到訪問令牌后,需要存儲該令牌以在API請求中使用它。瀏覽器中有多種方法可以持久化數(shù)據(jù)。應(yīng)用程序可以使用專用API(如Web存儲API或IndexedDB)來存儲令牌。應(yīng)用程序也可以簡單地將令牌保存在內(nèi)存中或?qū)⑵浞旁赾ookie中。一些存儲機(jī)制是持久的,另一些在一段時間后或頁面關(guān)閉或刷新后會被清除。

一些解決方案跨選項卡共享數(shù)據(jù),而其他解決方案僅限于當(dāng)前選項卡。但是,本指南中介紹的大多數(shù)方法都針對每個源存儲數(shù)據(jù)。因此,對于任何相關(guān)討論來說,理解一些概念很有幫助:origin和site。

某個(Web)資源的origin是其URL的scheme、hostname和port。例如,https://example.com/number/one和https://example.com:80/path/two具有相同的origin,因為它們共享scheme(https)、hostname(example.com)和端口(默認(rèn)端口)。它們的origin為https://example.com,與https://example.com:8443或https://this.example.com不同,因為它們在端口和主機(jī)名上有所不同。

相比之下,一個site比資源的origin要大。一個站點是為一組資源提供服務(wù)的Web應(yīng)用程序的通用名稱。簡單地說,一個站點是scheme和domain name,如https://example.com。雖然https://example.com和https://this.example.com:8443有不同的origin(不同的主機(jī)名和端口),但它們是相同的站點,因為它們托管在同一個域名(example.com)上并使用相同的scheme(https)。(從技術(shù)上講,這個定義還有細(xì)微差別,但這個簡化的說法有助于解釋這個概念)。

本地存儲

本地存儲是通過Web存儲API中的全局localStorage對象以JavaScript訪問的。本地存儲中的數(shù)據(jù)在瀏覽器選項卡和會話之間可用,也就是說它不會過期或在瀏覽器關(guān)閉時被刪除。因此,通過localStorage存儲的數(shù)據(jù)可以在應(yīng)用程序的所有選項卡中訪問。因此,在本地存儲中存儲令牌非常誘人。

// Storing the access token
localStorage.setItem("token", accessToken);
// Loading the access token
let accessToken = localStorage.getItem("token");

每當(dāng)應(yīng)用程序調(diào)用API時,它都會從存儲中獲取令牌并手動添加到請求中。但是,由于本地存儲可以通過JavaScript訪問,這意味著該解決方案也容易受到跨站腳本(XSS)攻擊。

如果您在本地存儲中使用access token,并且攻擊者設(shè)法在您的應(yīng)用程序中運行外部JavaScript代碼,那么攻擊者可以竊取任何令牌并直接調(diào)用API。此外,XSS還允許攻擊者操作應(yīng)用程序中的本地存儲數(shù)據(jù),這意味著攻擊者可以更改令牌。

請注意,本地存儲中的數(shù)據(jù)會永久存儲,這意味著存儲在其中的任何令牌會駐留在用戶的設(shè)備(筆記本電腦、電腦、手機(jī)或其他設(shè)備)的文件系統(tǒng)上,即使瀏覽器關(guān)閉后也可以被其他應(yīng)用程序訪問。因此,在使用localStorage時,請考慮終端安全性??紤]并防止瀏覽器之外的攻擊向量,如惡意軟件、被盜設(shè)備或磁盤。

根據(jù)上述討論,請遵循以下建議:

  • 不要在本地存儲中存儲敏感數(shù)據(jù),如令牌。
  • 不要信任本地存儲中的數(shù)據(jù)(尤其是用于認(rèn)證和授權(quán)的數(shù)據(jù))。

會話存儲

會話存儲是Web存儲API提供的另一種存儲機(jī)制。與本地存儲不同,使用sessionStorage對象存儲的數(shù)據(jù)在選項卡或瀏覽器關(guān)閉時會被清除。此外,session存儲中的數(shù)據(jù)在其他選項卡中不可訪問。只有當(dāng)前選項卡和origin中的JavaScript代碼可以使用相同的會話存儲進(jìn)行讀取和寫入。

// Storing the access token
sessionStorage.setItem("token", accessToken);
// Loading the access token
let accessToken = sessionStorage.getItem("token");

與本地存儲相比,會話存儲可以被認(rèn)為更安全,因為瀏覽器會在窗口關(guān)閉時自動刪除任何令牌。此外,由于會話存儲不在選項卡之間共享,攻擊者無法從另一個選項卡(或窗口)讀取令牌,這減少了XSS攻擊的影響。

在實踐中,使用sessionStorage存儲令牌的主要安全問題是XSS。如果您的應(yīng)用程序容易受到XSS攻擊,攻擊者可以從存儲中提取令牌并在API調(diào)用中重放它。因此,會話存儲不適合存儲敏感數(shù)據(jù),如令牌。

IndexedDB

IndexedDB是索引數(shù)據(jù)庫API的縮寫。它是一個用于在瀏覽器中異步存儲大量數(shù)據(jù)的API。但是,在存儲令牌時,這個瀏覽器API提供的功能和容量通常不是必需的。由于應(yīng)用程序在每次API調(diào)用中都發(fā)送令牌,最好是使令牌的大小最小化。

與迄今為止討論的其他客戶端存儲機(jī)制一樣,使用索引數(shù)據(jù)庫API存儲的數(shù)據(jù)訪問受到同源策略的限制。只有相同來源的資源和服務(wù)工作者才能訪問數(shù)據(jù)。從安全角度來看,IndexedDB與本地存儲相當(dāng):

  • 令牌可能會通過文件系統(tǒng)泄露。
  • 令牌可能會通過XSS攻擊泄露。

因此,不要在IndexedDB中存儲訪問令牌或其他敏感數(shù)據(jù)。IndexedDB更適合用于應(yīng)用程序脫機(jī)工作所需的數(shù)據(jù),如圖像。

內(nèi)存

存儲令牌的一個相當(dāng)安全的方法是將其保存在內(nèi)存中。與其他方法相比,令牌不存儲在文件系統(tǒng)中,從而減輕了與設(shè)備文件系統(tǒng)相關(guān)的風(fēng)險。

最佳實踐建議在內(nèi)存中存儲令牌時將其保存在閉包中。例如,您可以定義一個單獨的方法來使用令牌調(diào)用API。它不會向主應(yīng)用程序(主線程)透露令牌。下面的摘錄顯示了如何在JavaScript中使用內(nèi)存處理令牌的示例。

function protectedCalls(tokenResponse) {
  const accessToken = tokenResponse.accessToken;
  return {
    // call API with access token
    getOrders: () => {
      const req = new Request("https://server.example/orders");
      req.headers.set("Authorization", accessToken);
   return fetch(req)
    }
  }
}
const apiClient = protectedCalls(tokenResponse);
// call protected API
apiClient.getOrders();

請注意,攻擊者可能無法在獲取令牌后直接訪問令牌,因此可能無法直接使用令牌調(diào)用API。即便如此,通過持有令牌引用的apiClient,他們可以隨時通過apiClient調(diào)用API。但是,任何此類攻擊都限于選項卡打開并且接口提供的功能的時段。

除了與潛在的XSS漏洞相關(guān)的安全問題外,在內(nèi)存中保持令牌的最大缺點是頁面重載時令牌會丟失。然后,應(yīng)用程序必須獲取一個新令牌,這可能會觸發(fā)新的用戶身份驗證。安全的設(shè)計應(yīng)考慮到用戶體驗。

使用服務(wù)工作者的體系結(jié)構(gòu)通過在獨立的線程中運行令牌處理功能來減輕可用性問題,該線程與主網(wǎng)頁分離。服務(wù)工作者實際上充當(dāng)應(yīng)用程序、瀏覽器和網(wǎng)絡(luò)之間的代理。因此,它們可以攔截請求和響應(yīng),例如緩存數(shù)據(jù)和啟用離線訪問,或者獲取和添加令牌。

在使用JavaScript閉包或服務(wù)工作者處理令牌和API請求時,XSS攻擊可能會針對OAuth流程,如回調(diào)流或靜默流來獲取令牌。它們可以取消注冊并繞過任何服務(wù)工作者,或者使用原型污染“實時讀取令牌”通過覆蓋諸如window.fetch之類的方法。因此,請出于方便而不是安全性考慮JavaScript閉包和服務(wù)工作者。

Cookie

Cookie是存儲在瀏覽器中的數(shù)據(jù)片段。由設(shè)計,瀏覽器會將cookie添加到對服務(wù)器的每個請求中。因此,應(yīng)用程序必須謹(jǐn)慎使用cookie。如果未經(jīng)仔細(xì)配置,瀏覽器可能會在跨站請求時追加cookie,并允許跨站請求偽造(CSRF)攻擊。

Cookie具有控制其安全屬性的屬性。例如,SameSite屬性可以幫助緩解CSRF攻擊的風(fēng)險。當(dāng)一個cookie的SameSite屬性設(shè)置為Strict時,瀏覽器只會將其添加到源自并目標(biāo)與cookie的源站點相同的請求中。當(dāng)請求嵌入在任何第三方網(wǎng)站中時,瀏覽器不會添加cookie,例如通過鏈接。

您可以通過JavaScript設(shè)置和檢索cookie。但是,當(dāng)使用JavaScript讀取cookie時,應(yīng)用程序會變得容易受到XSS攻擊(除了CSRF之外)。因此,首選的選擇是讓后端組件設(shè)置cookie并將其標(biāo)記為HttpOnly。該標(biāo)志可以緩解通過XSS攻擊泄露數(shù)據(jù)的問題,因為它指示瀏覽器cookie不能通過JavaScript訪問。

為防止cookie通過中間人攻擊泄露,這可能導(dǎo)致會話劫持,cookie應(yīng)僅通過加密連接(HTTPS)發(fā)送。要指示瀏覽器僅在HTTPS請求中發(fā)送cookie,必須將Secure屬性設(shè)置為cookie。

Set-Cookie:token=myvalue;SameSite=Strict;Secure;HttpOnly

與瀏覽器中的任何其他永久存儲解決方案一樣,cookie可能會駐留在文件系統(tǒng)中,即使瀏覽器已關(guān)閉(例如,cookie不必過期,或者瀏覽器可以將會話cookie作為恢復(fù)會話功能的一部分保留)。為了減輕從文件系統(tǒng)中竊取令牌的風(fēng)險,只能在cookie中存儲加密的令牌。因此,后端組件只能在Set-Cookie頭中返回加密的令牌。

威脅矩陣

下表總結(jié)了瀏覽器中存儲解決方案的威脅評估,主要威脅向量標(biāo)記為紅色。橙色威脅需要除Web技術(shù)之外的緩解措施。綠色威脅已經(jīng)或可以通過適當(dāng)?shù)脑O(shè)置成功消除。

圖片圖片

無論攻擊者何時設(shè)法竊取令牌,只要令牌有效,他們就可以獨立于用戶和應(yīng)用程序使用訪問令牌。如果攻擊者設(shè)法竊取刷新令牌,他們可以顯著延長攻擊時間并增加損害,因為他們可以續(xù)新訪問令牌。黑客甚至可以將攻擊擴(kuò)展到除JavaScript應(yīng)用程序使用的API之外的其他API。例如,攻擊者可以嘗試重放訪問令牌并利用不同API中的漏洞。

被盜的訪問令牌可能會造成嚴(yán)重?fù)p害,XSS仍然是Web應(yīng)用程序的主要問題。因此,避免在客戶端代碼可以訪問的地方存儲訪問令牌。相反,將訪問令牌存儲在cookie中。當(dāng)使用適當(dāng)?shù)膶傩耘渲胏ookie時,瀏覽器泄露訪問令牌的風(fēng)險為零。然后,XSS攻擊與在同一站點上的會話劫持攻擊相當(dāng)。

使用Cookie的OAuth語義

Cookie仍然是傳輸令牌和充當(dāng)API憑據(jù)的最佳選擇,因為即使攻擊者成功利用XSS漏洞,也無法從cookie中檢索訪問令牌。但是,為了做到這一點,cookie必須適當(dāng)配置。

首先,將cookie標(biāo)記為HttpOnly,以便它們不可通過JavaScript訪問,以解決XSS攻擊的風(fēng)險。另一個關(guān)鍵屬性是Secure標(biāo)志,它確保cookie僅通過HTTPS發(fā)送,以減輕中間人攻擊。

其次,頒發(fā)短暫的只在幾分鐘內(nèi)有效的訪問令牌。在最壞的情況下,具有最小有效期的訪問令牌只能在可以接受的短時間內(nèi)被濫用。通常認(rèn)為15分鐘的有效期是合適的。讓cookie和令牌的過期時間大致相同。

第三,將令牌視為敏感數(shù)據(jù)。只在cookie中存儲加密令牌。如果攻擊者設(shè)法獲取加密令牌,他們將無法從中解析任何數(shù)據(jù)。攻擊者也無法將加密的令牌重放到任何其他API,因為其他API無法解密令牌。加密令牌只是限制了被盜令牌的影響。

第四,在發(fā)送API憑據(jù)時要限制性強(qiáng)。只向需要API憑據(jù)的資源發(fā)送cookie。這意味著確保瀏覽器只在實際需要訪問令牌的API調(diào)用中添加cookie。為此,cookie需要有適當(dāng)?shù)脑O(shè)置,比如SameSite=Strict、指向API端點域的域?qū)傩院吐窂健?/p>

最后,在使用刷新令牌時,請確保將它們存儲在自己的cookie中。沒有必要在每個API請求中都發(fā)送它們,所以請確保不是這種情況。刷新令牌必須只在刷新過期的訪問令牌時添加。這意味著包含刷新令牌的cookie與包含訪問令牌的cookie有稍微不同的設(shè)置。

令牌處理程序模式

在JavaScript客戶端中為OAuth提供最佳實踐原則的設(shè)計模式是令牌處理程序模式。它遵循OAuth 2.0 for Browser-Based Apps中描述的BFF(backend for frontend)方法。該模式引入了一個后端組件,能夠發(fā)出帶有加密令牌和上述必要屬性的cookie。

后端組件的責(zé)任是:

  • 作為OAuth客戶端與授權(quán)服務(wù)器交互,啟動用戶認(rèn)證并獲取令牌。
  • 管理JavaScript應(yīng)用程序的令牌,使其不可訪問。
  • 代理和攔截所有API請求,以附加正確的訪問令牌。

令牌處理程序模式定義了一個BFF,它為在瀏覽器中運行的應(yīng)用程序抽象了OAuth。換句話說,令牌處理程序模式建議一個JavaScript應(yīng)用程序可以用來認(rèn)證用戶并安全地調(diào)用API的API。為此,該模式使用cookie來存儲和發(fā)送訪問令牌。

令牌處理程序是一個后端組件,例如可以駐留在API網(wǎng)關(guān)中。它由兩部分組成:

  • OAuth代理,它處理OAuth流以從授權(quán)服務(wù)器獲取令牌。
  • OAuth代理,它攔截對API的所有請求并將cookie轉(zhuǎn)換為令牌。

圖片圖片

OAuth代理獲取令牌后,它會發(fā)出帶有以下屬性的cookie:

  • SameSite=Strict
  • HttpOnly
  • Secure
  • API的路徑

由于令牌處理程序是一個后端組件,所以O(shè)Auth代理是一個保密的客戶端,可以向授權(quán)服務(wù)器進(jìn)行身份驗證(與公開的JavaScript客戶端相比)。這意味著為了獲得令牌,OAuth代理需要進(jìn)行身份驗證。因此,攻擊者需要獲取客戶端憑據(jù)才能成功獲取新令牌。在JavaScript中運行靜默流而沒有客戶端憑據(jù)將失敗。

為了令牌處理程序模式能夠工作,JavaScript應(yīng)用程序和令牌處理程序組件必須部署在同一站點上(換句話說,它們必須在同一域中運行)。否則,由于cookie上的同站限制,瀏覽器不會將令牌cookie添加到API請求中。

要獲取數(shù)據(jù),JavaScript應(yīng)用程序只需通過OAuth代理調(diào)用API:

// http://www.example.com/app.js
// Call to OAuth Proxy
const response = await fetch("https://api.example.com/orders", {
// Instruct the browser to add cookies to cross-origin requests
credentials: "include"
});

瀏覽器會自動將cookie添加到請求中。在上面的示例中,瀏覽器將cookie包含在跨域請求中。但是,由于cookie屬性SameSite=Strict,瀏覽器只會將cookie添加到同一站點(同一域)的跨域請求中。

OAuth代理解密cookie并將令牌添加到上游API。cookie屬性確保瀏覽器僅將cookie添加到HTTPS請求中,以確保它們在傳輸過程中是安全的。由于令牌是加密的,它們在休息時也是安全的。然后令牌用于安全訪問API。

總結(jié)

使用OAuth和訪問令牌可以最好地保護(hù)API訪問。但是,JavaScript應(yīng)用程序處于不利地位。瀏覽器中沒有安全的令牌存儲解決方案。所有可用的解決方案在某種程度上都容易受到XSS攻擊。因此,確保任何應(yīng)用程序安全的首要任務(wù)應(yīng)該是防止XSS漏洞。

令牌處理程序模式通過在JavaScript無法訪問的cookie中存儲加密令牌來緩解XSS風(fēng)險。它將Web關(guān)注點與API關(guān)注點分離,并提供指導(dǎo),使用成熟的Web技術(shù)加固JavaScript應(yīng)用程序,而不會破壞Web架構(gòu)。查看令牌處理程序模式的詳細(xì)描述,并探索各種示例。

責(zé)任編輯:武曉燕 來源: 云云眾生s
相關(guān)推薦

2018-12-04 09:00:00

API安全性令牌

2012-05-30 15:14:11

ibmdw

2023-05-17 00:10:55

GPU瀏覽器解鎖

2016-06-02 13:22:12

LinuxWeb瀏覽器

2013-07-25 14:17:17

2013-06-17 15:41:13

Linux 終端瀏覽器

2012-12-20 12:42:59

傲游云瀏覽器

2019-08-16 10:54:03

本地存儲javascripthttp緩存

2010-04-05 21:57:14

Netscape瀏覽器

2018-11-30 09:00:19

html5cssjavascript

2015-10-14 09:23:21

Web瀏覽器Linux

2023-09-15 07:01:43

2021-12-31 10:49:02

惡意軟件黑客網(wǎng)絡(luò)攻擊

2021-09-26 05:32:58

漏洞OperaXSS

2012-03-20 11:07:08

2015-04-24 10:37:40

Web安全瀏覽器跨域訪問

2012-03-20 11:41:18

海豚瀏覽器

2012-03-20 11:31:58

移動瀏覽器

2012-03-19 17:25:22

2012-10-09 15:02:20

點贊
收藏

51CTO技術(shù)棧公眾號