對(duì)于一個(gè)安全的應(yīng)用來說,身份驗(yàn)證是第一道門檻,是與用戶建立數(shù)字信任關(guān)系的基礎(chǔ)部分,現(xiàn)代的身份管理系統(tǒng)可以自動(dòng)收集有關(guān)用戶的信息,驗(yàn)證他們的身份是否與他們的實(shí)際身份相符,并允許他們的注冊(cè)或訪問請(qǐng)求,從而創(chuàng)建了一種不會(huì)影響用戶體驗(yàn)的安全身份驗(yàn)證功能。
根據(jù) Javelin 2020 年身份欺詐調(diào)查,2019 年身份欺詐的總成本接近 170 億美元,現(xiàn)在這個(gè)數(shù)字更高。由于這些非常真實(shí)的風(fēng)險(xiǎn),可靠地驗(yàn)證用戶身份的能力是安全基礎(chǔ)設(shè)施的關(guān)鍵組成部分。
為了對(duì)那些有安全需求的特定資源進(jìn)行訪問控制,只讓某些特定的主體(個(gè)人、公司、甚至是一段代碼)對(duì)其執(zhí)行某些特定的操作(查看、修改等)。需要按照順序達(dá)成如下兩個(gè)條件:
1、認(rèn)證(Authentication):知道 ta 究竟是誰
2、授權(quán)(Authorization):知道 ta 有沒有權(quán)限對(duì)資源執(zhí)行試圖執(zhí)行的操作
認(rèn)證是決定一個(gè)主體究竟是誰的過程,換句話來說,是將當(dāng)前意圖訪問資源的用戶和提前存儲(chǔ)好的身份信息對(duì)應(yīng)起來的過程。顯然,這個(gè)操作需要由身份信息的持有者來完成,我們稱其為IdP(Identity Provider),它存儲(chǔ)的身份信息列表稱為用戶目錄或用戶池。所謂的身份信息可以是任意格式,包含但不限于以下兩種內(nèi)容:用戶的唯一標(biāo)識(shí)符(可以是唯一的用戶名、隨機(jī)字符串、UUID 等),以及只有該用戶才能提供,用來確認(rèn)該用戶身份的私密信息(密碼、指紋等)。前者可以是公開的,但后者必須是私密的,只有 IdP 和用戶自身才能持有。
為了完成認(rèn)證,用戶必須首先宣稱自己是誰,并且這個(gè)宣稱需要以某種形式和用戶目錄中的唯一一條記錄產(chǎn)生關(guān)聯(lián)。顯然,最簡(jiǎn)單的辦法就是直接向 IdP 宣布自己的唯一標(biāo)識(shí)符。之后,用戶需要通過某種保密的途徑悄悄告訴 IdP 自己的私密信息,IdP 確認(rèn)無誤后,就可以將當(dāng)前正在進(jìn)行請(qǐng)求的用戶和用戶目錄中的身份信息對(duì)應(yīng)起來,如此一來,用戶在 IdP 上的認(rèn)證過程就完成了。
確認(rèn)了用戶的身份之后,下一步就是確認(rèn)用戶到底有沒有權(quán)限訪問想要訪問的資源了。擁有身份信息后,這一步就變得很簡(jiǎn)單了——只需根據(jù)對(duì)應(yīng)資源的權(quán)限設(shè)置,檢查用戶的對(duì)應(yīng)操作是否被允許即可。
在最簡(jiǎn)單的身份模型中,身份持有者(IdP)和資源持有者運(yùn)行在同一個(gè)上下文中。這意味著一旦 IdP 完成了某個(gè)用戶的認(rèn)證,資源持有者立刻就能知道(例如通過數(shù)據(jù)庫查詢)用戶的身份信息。之后用戶訪問資源時(shí),資源持有者就能利用這一信息來決定是否允許用戶的操作(相當(dāng)于自己執(zhí)行授權(quán)),或者把這一決定交給 IdP 來做(相當(dāng)于 IdP 執(zhí)行授權(quán))。這種模型的缺點(diǎn)顯而易見——每個(gè)應(yīng)用都要維護(hù)一套自己的用戶目錄,不同應(yīng)用之間無法共享身份信息。為了解決這個(gè)問題,一個(gè)自然的想法就是將 IdP 獨(dú)立出來,讓所有資源持有者都從 IdP 處獲取用戶的身份。這種做法存在一個(gè)前提條件:當(dāng)一個(gè)用戶在 IdP 上完成了認(rèn)證之后,資源持有者必須得知這一點(diǎn),并能從 IdP 處獲取用戶對(duì)應(yīng)的身份信息,而且這一渠道必須是可信的,身份信息不能被惡意篡改。在實(shí)際應(yīng)用中,資源持有者一般會(huì)在用戶訪問資源時(shí),向 IdP 獲取用戶的認(rèn)證狀態(tài)和身份信息。如果成功,之后的授權(quán)步驟就和上面一致了。獨(dú)立的 IdP 有一個(gè)天然的好處——只要用戶在 IdP 上進(jìn)行過了認(rèn)證,其下關(guān)聯(lián)的所有資源持有者都能獲取到用戶的身份信息,正所謂一次認(rèn)證,到處訪問。所謂的單點(diǎn)登錄(SSO)本質(zhì)上就是如此。由于 Web 應(yīng)用天生的無狀態(tài)性,資源持有者并不能確定訪問資源的用戶和在 IdP 上認(rèn)證過的用戶是同一個(gè),因此用戶每次訪問資源時(shí)都需要提供身份標(biāo)識(shí)符和密碼,由資源持有者向 IdP 進(jìn)行確認(rèn)。為了解決這一問題,IdP 在完成認(rèn)證時(shí)可以向用戶頒發(fā)一個(gè)臨時(shí)的令牌(Token),這個(gè) Token 存儲(chǔ)著用戶目錄中的用戶身份,只有用戶本人才能持有,并且經(jīng)過 IdP 的數(shù)字簽名。用戶訪問資源時(shí),通過 Cookie 等手段自動(dòng)向持有者提供 Token,持有者可以在本地利用簽名驗(yàn)證 Token 的真實(shí)性和有效性,并且從 Token 中獲取到用戶的身份信息,無需再經(jīng)過 IdP 了。為了防止 Token 從用戶處泄露,它只在短時(shí)間內(nèi)有效,失效后必須由 IdP 重新頒發(fā)。最著名的 Token 技術(shù)是JWT(Json Web Token),它也是 OIDC 協(xié)議的一部分。除此之外,SAML 協(xié)議中的斷言(Assertion)也可以起到和 Token 相同的作用。當(dāng)然,用戶的登錄態(tài)也可以由資源提供者來維護(hù),資源提供者在向 IdP 確認(rèn)用戶身份后自己向用戶頒發(fā)一個(gè)類似的 Token,存放在用戶 Cookie 中。此時(shí)的 Token 可以實(shí)際存儲(chǔ)身份信息并進(jìn)行簽名,也可以作為一個(gè)索引的 Key,指向存放在資源提供者后端的,從 IdP 處獲得的身份信息(也就是所謂的 Session)。值得注意的是,在分離模型中,如果授權(quán)步驟由 IdP 執(zhí)行,用戶在 IdP 上進(jìn)行授權(quán)時(shí)還需要提供自己想要訪問的資源種類和執(zhí)行的操作,IdP 簽發(fā) Token 時(shí)也需要將這些信息寫在 Token 中,以便資源持有者核驗(yàn)。資源和操作的二元組被稱為Scope,OIDC 登錄時(shí)傳人的其中一個(gè)參數(shù)就是它。
由于Header和Payload是通過base64編碼的,因此如果敏感信息處理不到會(huì)導(dǎo)致泄露風(fēng)險(xiǎn)。簽名算法可被修改為none(CVE-2015-2951)也就是header中的“alg”為none,在線工具jwt.io無法修改,使用Pyjwt庫進(jìn)行修改,生成的jwt token只有header和payload兩部分,沒有signature:String encodedString = base64UrlEncode(header) + "." + base64UrlEncode(payload);String token = HMACSHA256(encodedString, 'secret');jwt利用算法對(duì)header和payload進(jìn)行加密生成signature,如果能知道密鑰secret就能隨意修改jwt token了;jwk ,json web key,就是header中的密鑰,通過偽造header中的密鑰來控制jwt token的生成:
身份驗(yàn)證繞過漏洞是現(xiàn)代web應(yīng)用程序中普遍存在的漏洞,也是隱藏最深很難被發(fā)現(xiàn)的漏洞。盡管單點(diǎn)登錄(SSO)等工具是對(duì)舊的登錄用戶方式的改進(jìn),但仍然可能包含嚴(yán)重的漏洞。無論是業(yè)務(wù)邏輯錯(cuò)誤還是其他軟件漏洞,都需要專業(yè)人員來分析其中的復(fù)雜性。
在這種情況下,一旦用戶使用有效憑證登錄到應(yīng)用程序,它就會(huì)創(chuàng)建一個(gè)在應(yīng)用程序其他地方使用的承載身份驗(yàn)證令牌。該認(rèn)證令牌在一段時(shí)間后過期。就在過期之前,應(yīng)用程序在終端/refresh/tokenlogin中向后端服務(wù)器發(fā)送了一個(gè)請(qǐng)求,該請(qǐng)求在標(biāo)頭和HTTP主體部分的用戶名參數(shù)中包含有效的身份驗(yàn)證令牌。進(jìn)一步的測(cè)試表明,刪除請(qǐng)求上的Authorization標(biāo)頭并更改HTTP主體上的用戶名參數(shù)將為提供的用戶名創(chuàng)建一個(gè)新的有效令牌。利用此漏洞,擁有匿名配置文件的攻擊者可以通過提供用戶名為任何用戶生成身份驗(yàn)證令牌。
大多數(shù)應(yīng)用程序都使用SSO系統(tǒng),因?yàn)榕c處理許多身份驗(yàn)證門戶相比,SSO系統(tǒng)更容易安全管理。但是簡(jiǎn)單地使用SSO并不能自動(dòng)保護(hù)系統(tǒng),因?yàn)镾SO的配置也應(yīng)得到保護(hù)。現(xiàn)在,一個(gè)應(yīng)用程序使用Microsoft SSO系統(tǒng)進(jìn)行身份驗(yàn)證。當(dāng)訪問internal.redacted.com URL時(shí),web瀏覽器會(huì)重定向到單點(diǎn)登錄系統(tǒng):乍一看,它似乎是安全的,但對(duì)后端請(qǐng)求的分析顯示,應(yīng)用程序在重定向響應(yīng)上返回了異常大的內(nèi)容長度(超過40000字節(jié))為什么應(yīng)用程序要這樣做呢?當(dāng)然是配置錯(cuò)誤。在將用戶發(fā)送到SSO的重定向時(shí),應(yīng)用程序向每個(gè)請(qǐng)求泄露了其內(nèi)部響應(yīng)。因此,可以篡改響應(yīng),將302 Found頭更改為200 OK,并刪除整個(gè)Location標(biāo)頭,從而獲得對(duì)整個(gè)應(yīng)用程序的訪問。
內(nèi)容管理系統(tǒng)(CMS),如WordPress、Drupal和Hubspot也需要進(jìn)行安全配置,以免它們?cè)谑褂弥幸肼┒础?/section>在發(fā)現(xiàn)的一個(gè)示例中,一個(gè)內(nèi)部應(yīng)用程序中使用了一個(gè)流行的CMS平臺(tái)Liferay。該應(yīng)用程序只有一個(gè)不需要身份驗(yàn)證就可以訪問的登錄頁面,所有其他頁面都在應(yīng)用程序UI中受到限制。對(duì)于那些不熟悉Liferay的人來說,CMS為應(yīng)用程序工作流使用了portlet,它的參數(shù)是數(shù)字中的p_p_id。對(duì)于該應(yīng)用程序,可以通過將參數(shù)值更改為58來訪問登錄portlet。在正常的登錄頁面中,只有登錄表單是可訪問的。然而,通過直接訪問portlet,可以達(dá)到Create Account功能,然后在不需要適當(dāng)?shù)氖跈?quán)情況下就可以進(jìn)行自注冊(cè)并訪問內(nèi)部應(yīng)用程序。請(qǐng)注意,雖然Liferay以前使用過這個(gè)工作流,但它的最新版本使用了portlet名稱而不是數(shù)字ID。不過,也可以通過更改名稱來訪問其他portlet。
JWT令牌或JSON web令牌,在新的web應(yīng)用程序中很流行。但是,雖然它們默認(rèn)具有安全機(jī)制,但后端服務(wù)器配置也應(yīng)該是安全的。然而,一些JS文件不需要身份驗(yàn)證就可以訪問。測(cè)試顯示,該應(yīng)用程序使用了安全登錄后通過Microsoft SSO系統(tǒng)發(fā)送的JWT令牌。在后端機(jī)制上,存在一個(gè)安全錯(cuò)誤配置,即不檢查是否為特定的應(yīng)用程序生成了JWT令牌。相反,它接受任何具有有效簽名的JWT令牌。因此,使用來自微軟網(wǎng)站的JWT令牌示例如下:有可能訪問內(nèi)部終端,泄露公司數(shù)據(jù)。
在此情況中,應(yīng)用程序通過 base64 編碼的 XML 請(qǐng)求向 HTTP 發(fā)布數(shù)據(jù)上發(fā)送所有請(qǐng)求。在登錄機(jī)制上,它將用戶名作為參數(shù)別名發(fā)送,將密碼作為scode發(fā)送。scode 參數(shù)內(nèi)的值已進(jìn)行哈希處理。分析顯示,它使用了所提供密碼值的 md5 值。請(qǐng)求中還有另一個(gè)有趣的標(biāo)志:scode 有一個(gè)屬性,其類型值為 2。嘗試將該值賦值為1,它將接受明文密碼。成功了!因此,在明文值中使用暴力攻擊中是可能的。把它賦值給空值怎么樣?或者其他值,如-1、0或9999999999?大多數(shù)都返回了除0之外的錯(cuò)誤代碼。用屬性0做了幾次嘗試,但沒有成功,直到將密碼值作為空值發(fā)送出去。這才意識(shí)到只需提供用戶名和密碼即可訪問任何帳戶。事實(shí)證明,這是一個(gè)很大的錯(cuò)誤。
復(fù)雜的身份驗(yàn)證機(jī)制可能成為攻擊者使用的最具隱蔽性的攻擊手段,特別是在容易出現(xiàn)業(yè)務(wù)邏輯漏洞的應(yīng)用程序上。因?yàn)樽詣?dòng)掃描器大多無法進(jìn)入這類漏洞,所以仍然需要手工來找到它們。保障用戶的合法資產(chǎn)和權(quán)益,維護(hù)系統(tǒng)安全穩(wěn)定地運(yùn)行,身份認(rèn)證路長且艱,任重而道遠(yuǎn)。