Google 孵化了三個Go安全庫,推薦使用!
大家好,我是煎魚。
Google 作為一家用戶體量很大的企業(yè),有非常多的產(chǎn)品,經(jīng)常會被黑客攻擊或被拿來練手。
因此其設(shè)計的產(chǎn)品、編程語言、工具庫等都會要求考慮安全性相關(guān)的內(nèi)容。例如:各種供應(yīng)鏈攻擊、CWE 等安全的查缺補漏等。
我們作為用戶(使用者),可以 “白嫖” 這些功能實現(xiàn)。直接復(fù)用在自家的業(yè)務(wù)上就可以了。這樣每年在護(hù)網(wǎng)上都能省不少勁。
三個 Go 安全庫
本次 Google 輸出了三個新的 Go 開源庫,能夠提供安全、高效的解決方案。接下來會給大家分享安全庫官方的一些案例和設(shè)計思路、方向。
圖片
本次介紹涉及如下幾個庫:
- SafeText[1]:用于 YAML 和 shell 命令模板,指的是對標(biāo) text/template 的安全增強。
- SafeOpen[2]:用于打開目錄中的文件,指的是對標(biāo) os.Open 等的安全增強。
- SafeArchive[3]:用于處理歸檔文件,指的就是壓縮文件的處理,對標(biāo) archive/tar 和 archive/zip 等的安全增強。
解決了什么問題
這些庫經(jīng)過精心設(shè)計,可應(yīng)對常見的安全攻擊,可以防范 CWE TOP25 中的以下弱點:
圖片
- #5 CWE-78[4]:操作系統(tǒng)命令中使用的特殊元素中和不當(dāng)(操作系統(tǒng)命令注入)。
- #6 CWE-20[5]:特殊情況下,輸入驗證不當(dāng)。
- #8 CWE-22[6]:對受限目錄的路徑名限制不當(dāng)(路徑遍歷)。
這幾個 Safe 系列庫提供了強大的保護(hù)機制。只要使用這幾個庫,即使輸入是由攻擊者輸入的,也能以無漏洞的方式執(zhí)行這些基本的系統(tǒng)操作。
庫使用和案例
SafeText
SafeText 庫,是 2023 年初發(fā)布的第一個安全庫的家族成員。
Google 要創(chuàng)造這一庫的原因是:內(nèi)部在使用 text/template 做開發(fā)基于 YAML 的應(yīng)用程序時,經(jīng)常受到 YAML 注入的攻擊。
YAML 模板
SafeText 庫被設(shè)計為 text/template 的直接替代品。我們可以用它來處理 YAML 模板,就像使用 text/template 一樣。
兩者不同的地方是:當(dāng)檢測到注入時,SafeText 庫會返回錯誤。
以下是例子,假設(shè)模板如下:
---
sensitive: data
innocent: "{{ .input}}"
當(dāng)使用 text/template 時,如果攻擊者控制了 .input 的值,他們就可以注入換行符,覆蓋其他字段或更改文檔結(jié)構(gòu)。
根據(jù)不同的使用情況,影響可能是嚴(yán)重的。例如:當(dāng)變更的結(jié)果被用作生產(chǎn)系統(tǒng)的配置文件時。
如果是使用 SafeText 庫時,SafeText 將返回錯誤信息:YAML Injection Detected,,并阻止這類可能的侵入式攻擊。
Shell 命令模板
在該庫原有 YAML 功能的基礎(chǔ)上,Safe 庫還增加了對 shell 命令模板的支持。
設(shè)計上考慮的是:確保輸入字符串不會被注入額外的命令或標(biāo)志,而不考慮潛在的錯誤轉(zhuǎn)義。(保證安全,接受部分錯誤的可能)
以下是例子,假設(shè)易受攻擊如下:
result := fmt.Sprintf("git commit -m %s", message)
如果信息變量受攻擊者控制,且連接字符串在某個時刻被執(zhí)行,那么這就是一個漏洞。
根據(jù)攻擊的具體執(zhí)行情況,操作系統(tǒng)命令或可執(zhí)行文件(本例中為 git cli)的參數(shù)都可能被注入。
如果使用 Safe 庫提高的 shsprintf 系列函數(shù),例如:
message := "`腦子進(jìn)煎魚了...`"
result, err := shsprintf.Sprintf("git commit -m %s", message)
或是:
message := "`煎魚進(jìn)腦子了`"
result := shsprintf.MustSprintf("git commit -m %s", shsprintf.EscapeDefaultContext(message))
兩個例子都能檢測到注入嘗試。第一個會返回錯誤,第二個則會引起恐慌??梢杂行鸬椒雷o(hù)的作用。
SafeOpen
SafeOpen 庫的設(shè)計目的是:防止路徑遍歷攻擊,它通過提供在基本目錄內(nèi)打開文件的函數(shù)來實現(xiàn)這一目的。
其原理很簡單:需要你指定一個受信任的根目錄,該庫就會強制要求文件操作不能超出該目錄。
保護(hù)的緣由是:當(dāng)要打開的文件路徑名受攻擊者控制(這意味著它可能包含 ./ 路徑組件)或根目錄 "不干凈"(例如它包含符號鏈接)時,它就能提供強大的保護(hù),因為無法跨過你所指定的目錄范圍。
SafeOpen 庫的使用例子,如下代碼:
rootDir:= "/data"
f, err := safeopen.OpenBeneath(rootDir, userInput)
if err != nil {
t.Fatalf("OpenBeneath(%q, %q) error: %v", rootDir, userInput, err)
}
// ... use f as an *os.File just like before
該庫對標(biāo)以下幾個函數(shù):
- os.Open
- os.OpenFile
- os.Create
- os.ReadFile
- os.WriteFile
SafeArchive
SafeArchive 庫的設(shè)計目的是:防止路徑遍歷攻擊(又稱 zip slip)以及與處理歸檔文件相關(guān)的各種攻擊。
該庫可直接替換 Go 標(biāo)準(zhǔn)庫中的的 archive/tar 和 archive/zip,直接換包的導(dǎo)入路徑就可以了。使用后,壓縮包中如果包含惡意信息,發(fā)現(xiàn)后將會被清除。
例子如下:如果該庫遇到包含惡意條目 ./././././etc/cron.daily/cronjob 的 .zip 文件,該庫會清理該名稱,并返回為干凈的 etc/cron.daily/cronjob。
代碼如下:
tr := tar.NewReader(buf)
tr.SetSecurityMode(tr.GetSecurityMode() | tar.SanitizeFileMode | tar.DropXattrs)
另外還支持了許多額外保護(hù)措施,例如:跳過特殊文件、凈化文件權(quán)限、凈化文件名、防止通過符號鏈接進(jìn)行遍歷等;
代碼如下:
tr.SetSecurityMode(tar.MaximumSecurityMode)
又或是:
tr.SetSecurityMode(tr.GetSecurityMode() &^ tar.SanitizeFileMode)
總結(jié)
這三個安全庫 SafeText、SafeOpen、SafeArchive 是非常典型的代表類別,通過這幾個庫我們可以從解決一些漏洞類的問題。