作者:云鼎實驗室
原文鏈接:https://mp.weixin.qq.com/s/ncWGrMsIAvh9HEK1QC5IGQ
前言
近些年來,越來越多的IT產業正在向云原生的開發和部署模式轉變,這些模式的轉變也帶來了一些全新的安全挑戰。
對象存儲作為云原生的一項重要功能,同樣面臨著一些列安全挑戰。但在對象存儲所導致的安全問題中,絕大部分是由于用戶使用此功能時錯誤的配置導致的。據統計,由于缺乏經驗或人為錯誤導致的存儲桶錯誤配置所造成的安全問題占所有云安全漏洞的16%。
以2017美國國防部承包商數據泄露為例:此次數據泄露事件是由于Booz Allen Hamilton公司(提供情報與防御顧問服務)在使用亞馬遜S3服務器存儲政府的敏感數據時,使用了錯誤的配置,從而導致了政府保密信息可被公開訪問。經安全研究人員發現,公開訪問的S3存儲桶中包含47個文件和文件夾,其中三個文件可供下載,其中包含了大量“絕密”(TOP SECRET)以及“外籍禁閱”(NOFORN)文件。
與此相似的案例有很多,例如Verizon數據泄露事件、道瓊斯客戶數據泄露事件。如何正確的使用以及配置存儲桶,成為了云上安全的一個重要環節。
存儲桶的訪問控制包含多個級別,而每個級別都有其獨特的錯誤配置風險。在本文中,我們將深入探討什么是存儲桶、什么是存儲桶ACL、什么是存儲桶Policy以及平臺是如何處理訪問權限,并對錯誤配置存儲桶權限導致的安全問題進行闡述。通過本文的閱讀,可以很好的幫助理解存儲桶的鑒權方式以及鑒權流程,避免在開發過程中產生由存儲桶錯誤配置導致的安全問題。
首先,我們來看簡單的對對象存儲的概念進行了解。
對象存儲
對象存儲是一種存儲海量文件的分布式存儲服務,用戶可通過網絡隨時存儲和查看數據。對象存儲使所有用戶都能使用具備高擴展性、低成本、可靠和安全的數據存儲服務。
對象存儲可以通過控制臺、API、SDK 和工具等多樣化方式簡單、快速地接入,實現了海量數據存儲和管理。通過對象存儲可以進行任意格式文件的上傳、下載和管理。
在了解對象存儲之后,我們來梳理下ACL、Policy、存儲桶的鑒權方式以及鑒權流程以及使用過程中容易產生的配置錯誤。
存儲桶訪問權限(ACL)
訪問控制列表(ACL)使用 XML 語言描述,是與資源關聯的一個指定被授權者和授予權限的列表,每個存儲桶和對象都有與之關聯的 ACL,支持向匿名用戶或其他主賬號授予基本的讀寫權限。ACL屬性見下表:

從控制臺上來看,存儲桶訪問權限分為公共權限與用戶權限,見下圖:

從上圖的選項來看,公共權限和用戶權限配置共同組成了存儲桶訪問權限。公共權限包括私有讀寫、公有讀私有寫和公有讀寫這幾個選項可以選擇,且為單選:

用戶權限可以通過添加用戶進行配置,通過填寫賬號ID并為其配置數據讀取、數據寫入、權限讀取、權限寫入以及完全控制五個選項。

除完全控制選項,其他幾個選項都可以靈活的搭配;而勾選完全控制選項后,則會將前四個選項一同勾選上。
控制臺中存儲桶公共權限以及用戶權限可配置項如下:
| 存儲桶訪問權限 | ||
|---|---|---|
| 公共權限 | 用戶權限 | |
| 私有讀寫 | √ | |
| 公有讀私有寫 | √ | |
| 公有讀寫 | √ | |
| 數據讀取 | √ | |
| 數據寫入 | √ | |
| 權限讀取 | √ | |
| 權限寫入 | √ | |
| 完全控制 | √ |
但是公共權限與用戶權限有什么區別與關聯呢?二者又是如何作用于訪問控制列表(ACL)呢?
這些問題,單從控制臺上功能上來看是并不能完全理解的,我們需要通過修改控制臺中不同的公共權限與用戶權限組合,對比ACL中內容的變化來分析控制臺上這些配置項的真實作用。
首先我們通過在控制臺中勾選的選項來測試一下公共權限是如何作用于ACL的。
公共權限
公共權限包括:私有讀寫、公有讀私有寫和公有讀寫,我們將依次測試一下在控制臺中勾選后ACL中實際的配置情況。
私有讀寫
只有該存儲桶的創建者及有授權的賬號才對該存儲桶中的對象有讀寫權限,其他任何人對該存儲桶中的對象都沒有讀寫權限。存儲桶訪問權限默認為私有讀寫。
我們將公共權限設置為私有讀寫,見下圖:
通過訪問API接口,獲取此時存儲桶ACL規則:

如上所示,ACL 描述了存儲桶擁有者(Owner)為(用戶 UIN:10001xxx),且此用戶擁有存儲桶的完全控制權限(FULL_CONTROL)。
值得注意的是,此處XML中權限配置,并不是因為我們勾選了公共權限配置中的私有讀寫而來,而是控制臺中用戶權限里默認配置中當前賬號的權限策略,見下圖紅框處:

因此,在公共權限里勾選私有讀寫,相當于在ACL中不額外寫入任何配置內容。
公有讀私有寫
任何人(包括匿名訪問者)都對該存儲桶中的對象有讀權限,但只有存儲桶創建者及有授權的賬號才對該存儲桶中的對象有寫權限。 我們將公共權限設置為公有讀私有寫,見下圖:

通過訪問API接口,獲取此時存儲桶訪問權限(ACL)

從XML內容可見,通過勾選公有讀私有寫,ACL中新增了如下配置條目:
此條配置授予了AllUsers用戶組的READ的權限,按權限分類來說,屬于“匿名用戶公有讀”權限,示意圖如下:

公有讀寫
任何人(包括匿名訪問者)都對該存儲桶中的對象有讀權限和寫權限。

通過訪問API接口,獲取此時存儲桶ACL。

如上所示,通過勾選公有讀寫,ACL中新增了如下配置條目。

與上文的公有讀私有寫權限相比,新增了AllUsers用戶組WRITE的權限,即“匿名用戶公有讀寫”權限,示意圖如下:

從上述實驗結果來看:公共權限配置的選項“私有讀寫“、”公有讀私有寫“和公有讀寫”本質上是在ACL中添加AllUsers用戶組的READ與WRITE權限。公共權限配置選項的總結如下:
- 私有讀寫:不在ACL中添加任何額外的權限配置條目
- 公有讀私有寫:在ACL中添加AllUsers用戶組READ權限項
- 公有讀寫:在ACL中添加AllUsers用戶組READ權限項、AllUsers用戶組WRITE權限項
在分析完公共權限之后,我們來分析一下用戶權限。
用戶權限
用戶權限和公共權限有什么區別呢?其實都是修改ACL策略,沒有本質的區別,只是公共權限在勾選時,生成ACL中ALLUSers的三個權限,而通過用戶權限配置的,在ACL中精準到用戶,并且權限策略也擴充為5個可選項。

我們先保持公共權限的默認設置——私有讀寫,并在控制臺編輯用戶權限,添加一個ID為123456的賬號。
數據讀取-數據寫入
我們為此賬號設置數據讀取、數據寫入的權限,見下圖:

通過訪問API接口,獲取此時存儲桶ACL。

從XML內容可見,在控制臺新增一個擁有數據讀取、數據寫入權限的賬號后, ACL中新增了如下配置:

ACL中增加了一個uin為123456的用戶的READ與WRITE權限,示意圖如下:

權限讀取-權限寫入
接下來我們保持公共權限為默認的私有讀寫不變,并在用戶權限處添加一個ID為123456的賬號,我們為此賬號設置權限讀取、權限寫入的權限,見下圖:

通過訪問API接口,獲取此時存儲桶ACL。

如上所示,在控制臺新增一個擁有權限讀取、權限寫入的賬號后, ACL中新增了如下配置:

ACL中增加了一個uin為123456的用戶的READ_ACP與WRITE_ACP權限,此時123456用戶可以對ACL進行讀取以及更新操作,示意圖如下:

公有讀寫-數據讀取-數據寫入
在這環節中,我們將實驗一下公共權限與用戶權限的關系,我們將公共權限設置為公有讀寫,并在用戶權限處添加一個ID為123456的賬號,我們為此賬號設置權限讀取、權限寫入的權限,見下圖:

通過訪問API接口,獲取此時存儲桶ACL

通過對比公共權限章節中公有讀寫與用戶權限章節中數據讀取-數據寫入部分的內容可以發現, 在控制臺中配置的公共權限與用戶權限是各自作用于ACL中,在ACL中并不互相影響,配置的公有讀寫將會在ACL中添加一個AllUsers用戶組的WRITE與READ權限,而用戶權限中添加的123456賬號的數據讀取、數據寫入將在 ACL中加入了一個123456賬號的READ與WRITE權限。
但是細心的讀者可能會發現一個有意思的問題,在配置用戶權限時,ACL中默認的Owner的FULL_CONTROL權限不見了
消失的Owner權限
對比一下公共權限章節中私有讀寫部分的ACL,我們發現了一個問題,見下圖:

雖然我們僅僅是在用戶權限處增加了一個新用戶,并沒有刪除也沒有辦法刪除控制臺中默認的主賬號的完全控制權,但是ACL中默認的擁有完全控制權的主賬號條目不見了,見上圖紅框處。
這樣會不會導致主賬號失去了存儲桶的控制權呢?經過測試發現,主賬號依然擁有存儲桶的完全控制權,這是問什么呢?
通過查閱官方文檔,我們發現了答案:

資源的擁有者,即Owner始終對資源具備完全控制權,無論ACL中是否存在此項。
存儲桶策略(Bucket Policy)
在分析完ACL之后,我們來看看Policy。存儲桶策略(Bucket Policy)使用 JSON 語言描述,支持向匿名身份或任何 CAM 賬戶授予對存儲桶、存儲桶操作、對象或對象操作的權限,在對象存儲中存儲桶策略可以用于管理該存儲桶內的幾乎所有操作。Policy屬性見下圖:

我們可以通過在控制臺中添加策略的方式來設置Policy權限。

我們添加一個新策略,該策略允許所有用戶對我們的存儲桶進行所有操作,見下圖:

通過訪問API接口,獲取權限策略。

可以發現,Policy中以共有四個主要的屬性:Action、Effect、Principal、Resource,分別對應了控制臺中填寫的操作、效力、用戶、資源路徑。與ACL僅可以配置的用戶與權限選項相比,控制的顆粒更細。
接下來,我們添加一個允許賬號ID為123456的賬號對cos-aclxxx/policy_test路徑的讀操作。

通過訪問API接口,獲取權限策略。

在這個Policy中,我們可以看到更細膩的Action與Resource配置。
對象訪問權限
在對象存儲中,每一個對象同樣存在著可配置的訪問權限,默認繼承存儲桶的ACL。

我們將此對象設置為公有讀私有寫權限,見下圖:

通過查詢GetObjectAcl API接口,獲取其ACL。

從ACL可見,與存儲桶的ACL配置項完全一樣,只不過這里的ACL作用于目標對象而存儲桶ACL作用于存儲桶。
但是對象存儲是如何通過ACL與Policy共同協調控制存儲桶權限的呢?
我們接下來看一下對象存儲的訪問策略評估流程。
訪問策略評估機制
在開始介紹對象存儲訪問策略評估流程之前,我們先介紹一下幾個流程中涉及到的重要概念:顯示拒絕、顯示允許、隱式拒絕以及三者之間的聯系:
01顯式拒絕
在用戶策略、用戶組策略、存儲桶 Policy 中針對特定用戶有明確的 Deny 策略。
02顯式允許
在用戶策略、用戶組策略、存儲桶 Policy、存儲桶 ACL 中通過grant-*明確指定特定用戶針對特定用戶有明確的 Allow 策略。
03隱式拒絕
在默認情況下(未經配置的情況下),所有請求都被隱式拒絕(deny)。
顯示拒絕、顯式允許、隱式拒絕之間的關系如下:
如果在用戶組策略、用戶策略、存儲桶策略或者存儲桶/對象訪問控制列表中存在顯式允許時,將覆蓋此默認值。任何策略中的顯式拒絕將覆蓋任何允許。
在計算訪問策略時,應取基于身份的策略(用戶組策略、用戶策略)和基于資源的策略(存儲桶策略或者存儲桶/對象訪問控制列表)中策略條目的并集,根據顯示拒絕、顯式允許、隱式拒絕之間的關系計算出此時的權限策略。

通過上圖,我們可以很清楚的理解存儲桶的鑒權流程。
訪錯誤配置導致的安全問題
錯誤使用公有讀寫權限
在所有錯誤配置導致的存儲桶安全問題中,最常見的一種便是錯誤的使用了公有讀寫權限導致的安全問題。

通過上文的分析可知,公有讀權限可以通過匿名身份直接讀取用戶存儲桶中的數據,存在著嚴重的安全隱患。
但是有些用戶為了避免使用繁雜且細粒度的權限配置,會錯誤的將其存儲桶設置為公有讀寫,這將導致了其存儲桶中的內容被攻擊者竊取與篡改。正如本文前言中所描述的2017美國國防部承包商數據泄露案例。即便是美國國防部承包商,在使用存儲桶進行對象存儲時,也會犯下這樣的常見錯誤。
因此,為了保障存儲桶安全,建議用戶為存儲桶配置私有讀寫權限。
存儲桶、對象訪問權限差異性問題
存儲桶權限與對象權限的差異性,往往會為對象資源來安全性問題。
在實際操作中,為了存儲桶的安全起見,存儲桶的公共權限往往會被設置為私有讀寫,這也是存儲桶的默認公共權限配置,見下圖:

存儲桶的私有權限表明,只有該存儲桶的創建者及有授權的賬號才對該存儲桶中的對象有讀寫權限,其他任何人對該存儲桶中的對象都沒有讀寫權限。
但是將存儲桶的公共權限設置為私有讀寫可以完全保護存儲桶中的中的對象資源不被讀取嗎?
在我們測試的這個存儲桶中,并未設置Policy策略,并且存在著一個名為p2.png的對象。

而從上文可知,存儲桶中的對象也有著其對應的對象權限。
在這里我們將對象p2.png的ACL權限設置為公有讀私有寫,見下圖:

通過訪問p2.png資源url可以發現,此時p2.png對象可以被訪問,見下圖:

測試表明,當存儲桶公共權限設置為私有讀寫時,當存儲桶中的對象公共權限為公有讀私有寫時,此對象依然是可以被讀取的。
實際原理很簡單,我們為對象p2.png設置了公有讀私有寫ACL策略,此時對象資源p2.png的ACL如下:

根據上文訪問策略評估機制一章可知,對象p2.png設置了AllUsers用戶組的顯性允許READ權限,因此當匿名用戶訪問p2.png時,即使存儲桶設置了私有讀寫權限,依然可以訪問此對象,原理圖見下圖:

因此,單單依靠存儲桶的訪問權限,并不能保護其中資源的未授權訪問情況。為存儲桶中資源配置對應的訪問權限,才可以保證對象的安全性。
錯誤授予的操作ACL權限
在Policy權限設置中,如果授權用戶操作存儲桶以及對象ACL的權限(GET、PUT)見下圖:

即使Policy中沒有授權該用戶讀取存儲桶、寫入存儲桶、讀取對象、寫入對象的權限,這個操作依然是及其危險的,因為該用戶可以通過修改存儲桶以及對象的ACL進行越權。
我們在coscmd中配置授權用戶的密鑰信息后,通過coscmd list列出存儲桶中內容。
從返回結果來看,該用戶并沒有讀取存儲桶列表的權限
經過測試,用戶同樣也沒有下載p2.png對象的權限,見下圖:

但是我們卻可以查詢存儲桶中對象的ACL,見下圖:
由于該用戶擁有修改存儲桶中對象ACL的權限,因此可以通過如下指令授予該用戶讀取p2.png的權限,見下圖:
在修改過p2.png權限之后,可以順利的將此對象下載到本地。

資源超范圍限定
在使用存儲桶進行對象讀取或寫入操作時,如果沒有合理的或者錯誤的在Policy中配置用戶允許訪問的資源路徑(resource),則會出現越權訪問,導致用戶數據被惡意上傳覆蓋或被其他用戶下載等安全問題。
在Web應用開發中,經常會發生此類問題。設想以下場景:在一個Web應用使用對象存儲來存儲用戶頭像,且通過前端直傳的方式將用戶上傳的頭像傳至存儲桶中,并希望在存儲桶/avatar/路徑中存儲桶用戶的頭像,由于后端開發時為了方便而進行了不規范的存儲桶Policy配置,在生成用戶用以上傳頭像的臨時密鑰時直接將此臨時密鑰允許訪問的 resource 指定為 qcs::cos:
這樣以來,系統為每個用戶所生成的用以上傳以及瀏覽頭像的臨時密鑰雖然不盡相同,但是這個臨時密鑰都擁有qcs::cos:
這一錯誤的配置導致了很多嚴重的安全問題,由于在此場景下,Web應用程序使用前端直傳的方式訪問存儲桶,因此后臺生成的臨時密鑰將會發送給前臺,任意用戶通過網絡抓包等手段獲取到的臨時憑據,可參見下圖流量中響應包內容。

在獲取了臨時密鑰之后,攻擊者憑借此憑據讀寫qcs::cos:
攻擊者可以通過此方式覆蓋目錄中其他用戶資源,見下圖:

上圖攻擊者通過test.txt文件覆蓋了16.png。當然,攻擊者也可以輕易的讀取此目錄中其他用戶的文件。
針對此問題的修復方式如下:可以通過每個用戶的用戶標識來為每一個用戶設置一個獨用的路徑,例如可以在為用戶生成臨時密鑰時,將policy中resource 指定為 qcs::cos:
寫在后面
對象存儲服務作為一項重要的云上服務,承擔了存儲用戶數據的重要功能。從上文分析可見,對象存儲服務提供了細粒度的訪問權限控制功能,以保證用戶數據的安全性。
但是由于用戶使用對象存儲服務時安全意識不足或對訪問權限以及訪問策略評估機制錯誤的理解,將會導致數據被非法訪問或篡改。這些錯誤的配置包括用戶錯誤的使用公有讀寫權限、錯誤授予操作ACL權限、配置資源超過范圍限定以及對存儲桶權限機制錯誤理解等,這些錯誤的配置將會造成嚴重的安全問題。
因此,深入了解對象存儲服務所提供的訪問權限以及訪問策略評估機制,并始終遵循最小權限原則,將會為存儲桶中存儲的數據安全構筑立體防護體系的一道堅固的門鎖,與此同時,也可以通過檢查存儲桶日志以及文件時間戳來排查存儲桶是否被侵害,確保云上資產的安全。
參考文獻
https://blog.lightspin.io/how-to-access-aws-s3-buckets
https://blog.lightspin.io/risks-of-misconfigured-s3-buckets
https://cloud.tencent.com/document/product/436/40265
https://main.qcloudimg.com/raw/document/intl/product/pdf/436_9511_zh.pdf
本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/1682/
暫無評論