最新消息:

Redis Lua 腳本:修復了一些安全漏洞

SEEBUG IMGIT 10浏览 0评论

原文鏈接:《Redis Lua scripting: several security vulnerabilities fixed》
作者:antirez
譯者:Roy@Knownsec

一個多月前我收到一封來自 Apple 信息安全團隊的郵件。他們在一次審計中發現了一個 Redis Lua 子系統中的安全問題,具體來說是在 cmsgpack 庫中。這個庫並非 Lua 的一部分,而是我自己按 MessagePack 實現的。在一次合併一個功能改進的 pull request 時引入了安全問題。後來他們又發現了 Lua struct 庫的一個新問題,同樣這個庫也不是 Lua 的,至少不是我們用的這版 Lua 的:我們才剛把源碼嵌入到自己的 Lua 實現里,以便能給 Redis 用戶使用的 Lua 解釋器添加一些功能。然後我就發現了該 struct 庫的另一個問題,接着 Alibaba 團隊也發現了許多 cmsgpack 的其他問題,並定位了調用這些 Lua API 的代碼。我迅速地就被一堆 Lua 相關的漏洞淹沒了。

這些漏洞更多地是影響在雲端提供託管 Redis 服務器這一特定場景,畢竟沒有 Redis 服務器權限的話,要利用已發現的漏洞幾乎不可能:很多 Redis 用戶根本就用不到 cmsgpack 或 struct 庫,即使用也不大可能用在不可信的輸入上。但云服務提供商就不同了:他們的 Redis 實例(通常有多種租約)是開放給了訂閱服務的用戶的。他或她可以發送任何東西給這些 Redis 實例,觸發漏洞、破壞內存、影響甚至完全操控 Redis 進程。

比如這個 Python 小程序就能擊潰 Redis,利用了 cmsgpack 其中一個漏洞。

https://gist.github.com/antirez/82445fcbea6d9b19f97014cc6cc79f8a

不過站在能控制 Redis 實例的輸入的普通用戶的角度來看,風險僅限於將不可信的內容傳入諸如 struct.unpack() 的函數,還得首先剛好選到一種危險的解碼格式 bc0 作為格式參數。

溝通協調

多虧了 Apple 信息安全團隊、我,和 Redis 雲服務提供商之間的積極配合和友好交流,我先聯繫上了所有重要的 Redis 提供商,盡量協調漏洞的發佈,好讓他們能先一步打上補丁。我提供了一個獨立補丁,使得提供商能輕易應用到他們的系統中。最後從昨天到今天我準備了 Redis 3、4 和 5 的新的修復版本,修復了安全性。你在看這篇博文時這些都已經發佈了。

不幸的是我沒能聯繫上較小或較新的雲服務提供商。處理與 Redis Lab, Amazon, Alibaba, Microsoft, Google, Heroku, Open Redis 和 Redis Green 的溝通已是竭盡全力,何況將信息擴散給其它主體將增加泄密的風險(各家公司都有很多人參與其中)。如果你是一名 Redis 服務提供商卻今天才知道這個漏洞,我很抱歉,我已經儘力了。

感謝 Apple 信息安全團隊以及其他提供商在這個問題上的提點與幫助。

Lua 的問題

老實說設計 Redis 的 Lua 引擎時,我並沒設想過這種顧客與雲服務提供商相對立的安全模型。這多少假設了 Redis 服務器的使用者是可信的。所以 Lua 庫普遍沒有經過安全審查。當時覺得你要是都有 Redis API 的權限了,你怎麼都能幹得比這更不安全。

不過後來事情就變了,雲服務提供商限制了開放給顧客的 Redis API,以使提供託管的 Redis 實例成為可能。但拒絕了 CONFIG 或 DEBUG 這類命令,就不可避免地要開放 EVAL 和 EVALSHA(譯者註:兩個都是用來執行 Lua 腳本的命令)。Redis Lua 腳本是社區里最常用到的功能之一。

因此在我真正留意到之前,Lua 庫也已因 Redis 開放給最終用戶的方式發生變化而日漸成為本該由 Redis 處理的安全模型中的一個攻擊點。如前所述,在這模型中相比 Redis 用戶,是託管 Redis 「雲」服務提供商受影響更多,但無論如何這是個必須解決的問題。

我們能做些什麼來改進雲服務提供商目前在安全方面的狀態,併兼顧 Lua 腳本的具體問題呢?我列出了一些事情,想在接下來的幾個月去做。

  1. Lua 棧保護。貌似 Lua 可以通過編譯以一些性能的犧牲來保證 Lua 棧 API 不被濫用。公正地說,我覺得 Lua 提出的關於棧的假設有點太瑣碎了,Lua 庫的開發者得一直檢查棧上是否有足夠的空間來壓入一個新的值。其它同等抽象的語言有 C API,就沒這個問題。所以我要好好考慮下在 Lua 底層 C API 中增加防範措施的低效是否可以接受。
  2. 安全審計與模糊測試。儘管時間有限,我仍給 Lua struct 庫做了些模糊測試。我將繼續檢查這領域的其它 Bug。肯定還有更多的問題,我們發現的 Bug 只是部分,這僅僅是因為之前沒有多餘的時間能投入到腳本子系統中。所以這是將要進行的一個重要的事情。在結束后我會再與 Redis 供應商協調,以使他們能及時打上補丁。
  3. 從 Redis 用戶的角度來說,有不可信數據發往 Lua 引擎時使用 HMAC (譯者註:一種加密的哈希方法)來確保數據沒被更改是很重要的。比如說有種流行的模式是把用戶的狀態存在用戶自己的 cookie 里,以後再解碼。這種數據後面可能被用作 Redis Lua 函數的輸入。這個例子中一定要用 HMAC 來保證我們讀到的是之前存儲過的。
  4. 更全面的 Lua 沙盒化。關於這個話題應該有大量的的文獻和優秀實踐。我們已有一些沙盒實現,但依據我的安全經歷我感覺沙盒化歸根結底就是個貓鼠遊戲,不可能做到完美。比如追蹤 CPU 或內存的濫用對 Redis 來說可能就太複雜了。但我們應至少能做到進程錯誤時「優雅」地退出,不產生任何內存內容錯誤。
  5. 也許到了升級 Lua 引擎的時候了?我不確定新版的 Lua 是否從安全角度來說更先進,但我們有大量問題使得升級 Lua 會導致老的腳本可能無法運行。對 Redis 社區里的腳本,尤其是 Redis 用戶隨便寫的那種,更先進的 Lua 版本的作用有限,這是一大問題。

相關 Issue

修復問題的提交如下:

ce17f76b 安全性: 修復 redis-cli 緩衝溢出。
e89086e0 安全性: 修復 Lua struct 庫偏移量處理。
5ccb6f7a 安全性: 更多 cmsgpack 的修復,來自 @soloestoy。
1eb08bcd 安全性: 更新 Lua struct 庫,提升安全性。
52a00201 安全性: 修復 Lua cmsgpack 庫棧溢出。

第一個提交與此無關,是一個 redis-cli 的緩衝溢出,只有在命令行中傳入一個很長的主機參數時才會被利用。其它的才是我們發現的 cmsgpack 與 struct 庫的問題。

這是兩個復現問題的腳本:

https://gist.github.com/antirez/82445fcbea6d9b19f97014cc6cc79f8a

https://gist.github.com/antirez/bca0ad7a9c60c72e9600c7f720e9d035

兩個都是蘋果信息安全團隊寫的。但第一個我做了修改,以便能更穩定地復現。

影響到的版本

幾乎所有帶 Lua 腳本的 Redis 都受到了影響。

修復的版本為以下 github tag:

3.2.12 
4.0.10 
5.0-rc2 

穩定版(4.0.10)仍可在 http://download.redis.io 找到。

各發行版 tarball 文件的哈希值在此:

https://github.com/antirez/redis-hashes

請注意發行的版本中也包含了其他的修復,所以最好也讀下版本說明,好了解切換到新版時其他會升級的東西。

希望再發博客時能帶來為 Redis 的 Lua 腳本子系統規劃的安全審計的報告。


Redis Lua 腳本:修復了一些安全漏洞
本文由 Seebug Paper 發佈,如需轉載請註明來源。本文地址:https://paper.seebug.org/622/

转载请注明:IMGIT » Redis Lua 腳本:修復了一些安全漏洞

发表我的评论
取消评论

*

code

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址