安全左移理念,鹅厂 DevSecOps 如何实践?
作者:yuyangzhou、dexyfruan,騰訊 TEG 應用運維安全工程師
引子
隨著 DevOps 模式的落地,快字當頭。研效提速也意味著出現安全漏洞的數量和概率隨之上漲。過去安全風險的管控主要依賴于 DAST 類技術,即:采用黑盒測試技術,對待檢查目標發起含檢查用例的請求。DevOps 給這一模式帶來了挑戰,安全檢查速度慢、周期長,容易給業務帶來干擾,一定程度上有阻礙業務持續交付的風險。另據 Capers Jones 的研究結論:解決缺陷的成本,在研發流程中越靠后越高。
因此,安全機制的左移在開展 DevSecOps 建設時就變得更為重要了。 左是指軟件開發生命周期的早期,也就是設計、編碼階段。發生安全漏洞研發的早期階段存在哪些問題?我們認為可以總結為三類:
開發人員不了解安全編寫代碼的知識
開發人員有一定安全意識,但因為趕進度或疏忽遺漏編寫安全機制,或是錯誤地實現安全校驗邏輯
代碼編寫是否安全僅憑開發人員自覺,缺乏檢查和卡點機制
調研業界理念與實踐基礎上,團隊進行了安全左移建設的探索,主要包括三個機制:面向開發人員的代碼安全指南、默認安全框架組件、嵌入基礎設施的代碼安全檢查。作為前述項目的參與者,我們想與業界同行分享交流其中的一些思考與經驗。
I. 代碼安全指南
1.1 背景
首先是開發人員缺乏安全編寫代碼知識的問題。 在開展日常安全運營過程中,常常會遇到如下與之關聯的挑戰:
一個業務被發現問題,如何把這種“踩坑”的經驗沉淀下來,分享給其他業務以及新加入公司的同事?
如何幫助開發人員建立起安全編碼意識,實現代碼寫出來就沒有漏洞?
當檢出安全漏洞時,如何給予開發人員詳細、可操作的改進指引?
安全編碼意識和漏洞修復指引,兩份材料是否合二為一?
綜合上述背景,去年梳理了一份統一代碼安全指南。從開發人員視角講述安全注意事項,并配套了豐富的代碼示例。覆蓋常見的 8 門編程語言,包括:C#、C,C++、Go、JavaScript、Java、Objective-C、PHP、Python。
1.2 設計理念
代碼安全指南的內容呈樹狀結構展開,共分 5 層,如下:
1.2.1 語言
每種語言面臨安全的風險種類不同,需要分別開展詳述。如:go 和 javascript 對比,go 就不存在原型鏈污染的問題。同時,由于公司內的代碼風格規范亦分語言展開,安全規范采取相同的分語言方式能保持整體的連貫性。
1.2.2 端
這里的端是指不同的終端,如:Web、安卓客戶端、iOS 客戶端、PC 客戶端。實踐過程中,將內容按端區分的原因有:
1、同一門編程語言,用在不同的終端應用開發,其面臨的風險類型和數量有著天壤之別。例如:JavaScript 應用于前端頁面開發時,面臨的主要風險是 DOM XSS;但 JavaScript 亦可依托 Node.js 進行 Web 后端接口開發,如果編碼不當,則存在命令注入、SQL 注入等風險。
2、大型互聯網公司內,項目開發采取“流水線”化作業,分工往往精細明確,將不同端的場景作為主干目錄,更便于開發人員檢索、快速了解編碼安全知識。
1.2.3 場景
通過復盤歷史漏洞,安全風險可按成因粗略歸為兩類:
1、代碼漏洞,是指代碼編寫時,因不安全的 API 使用和邏輯編寫產生的安全風險。
2、運維漏洞,是指代碼的運行環境、配置和依賴等系統運維相關的安全風險。如騰訊藍軍分享的《淺析軟件供應鏈攻擊之包搶注低成本釣魚》一文,涉及的安全風險本質上是是:部分語言依賴包管理,當部分企業私有軟件包僅在公司內部軟件源注冊時,攻擊者就可以在外部公共軟件源上搶注。如果公司內員工使用包管理軟件拉取時,未配置公司鏡像源時,就會拉取到攻擊者搶注的惡意包。
1.2.4 功能
在對內、外部發現的漏洞進行復盤過程中,我們發現安全風險與業務場景高度相關,例如:
由于代碼安全指南的目標受眾是開發人員看的。在撰寫指南過程中,我們嘗試將漏洞轉化為功能場景,作為主干目錄。由于與具體的業務場景關聯,在開發時能更容易想起相關的注意事項,由此可降低認知、學習成本。
1.2.5 API/sink 點
對于開發人員來說, 各類 API 是程序代碼的基礎組成部分。對安全團隊來說,API 也就是編寫安全檢查策略要收集整理的 sink 點。
1、為什么要在代碼安全指引中,枚舉 API/sink 點?
對開發人員來說,API 是實現業務邏輯時,高頻接觸對象。通常安全漏洞往往可歸因為 API 的錯誤使用。對安全工程師來說,sink 點是編寫安全策略、組件是非常重要的一部分,直接決定了 SAST 系統的掃描能力。
業界也不乏類似的探討,如 Google 在 ICSE '21 的論文*《If It’s Not Secure, It Should Not Compile: Preventing DOM-Based XSS in Large-Scale Web Development with API Hardening》*中,闡釋了 Google 加固前端組件,使其 Web 頁面能天然“免疫”DOM XSS 漏洞的實踐過程。
其中主要的思路是對.innerHTML 等容易被誤用產生安全問題的 API 做了加固,封裝為前端組件中新的函數對象。形成了 JavaScript 公共庫https://github.com/google/closure-library,并設計了對應的編譯時檢查工具。自2018年在其內部逐步推廣后,截止2020年Q2外部向Google報告全部漏洞類型中,DOM XSS 已由原先的 20%降低至 2%。
在上述實踐過程中,最為重要的一步是:XSS sink 點的提取,也就是易被誤用產生安全漏洞的 API。原文“We would like to mention that many other XSS counter-measures, such as data-flow analyses, also need to identify areasonably comprehensive set of XSS sinks to be effective. Therefore, enumerating the sinks are somewhat orthogonal to API hardening",指出 sink 點的提取是開展 API 加固極為重要的一步。
與上述實踐類似,我們認為在代碼安全指南中,清楚地列出容易被誤用的 API,對日常開發和安全策略建設均有幫助。
2、如何確保所枚舉 API 的完善性?
這也是上述論文中拋出的一大難點,原文提到:“It is unrealistic to cover all browser-specific XSS sinks because many browsers have undocumented behaviors. As our best effort, we work with the developers of some mainstream browsers to stay informed about new browser features that may have security implications.”。
文章指出,這是一項非常有挑戰的任務。編寫代碼安全指引時,我們亦遇到了類似的挑戰,采取的解決思路是:
1)整合各語言、組件、框架文檔中的最佳安全實踐。在編寫安全指南初期,我們重點參考了 CWE、OWASP 等材料。
2) 結合內、外部已知的漏洞案例的復盤、抽象,做校對補充。
3)舉一反三,推導鮮有提及的風險點。例如,使用 jQuery 的頁面,會因為不安全地使用.html()方法產生 DOM XSS 漏洞。那是否還有其他函數有同樣的風險呢?通過查閱 jQuery 的開發者手冊https://api.jquery.com/html/發現,.html 函數接受的入參類型為 htmlString 和 function。
官方文檔給出的示例如下:
$( "div.demo-container" ).html( "<p>All new content. <em>You bet!</em></p>" );因此可以得出產生漏洞的原因是:從用戶可控來源獲取切未經過濾的值,可定義為 htmlString 類型并經.html()寫入頁面,進而產生 XSS 漏洞。順藤摸瓜可以整理出:.append()、.prepend()、.wrap()、.replaceWith()、.wrapAll()、.wrapInner()、.after()、.before()等 API 存在同樣的因誤用產生安全風險的可能性。最終,針對上述場景下的指引要求描述如下:
除列出所有風險 API,讓開發人員在使用時,腦海里能對快速關聯到指引要求外,在編寫指引時,我們約定還采取了兩種額外的表述注意點,來保證指引內容的可操作性:
a、限定產生安全風險的開發場景,更明確;
b、明確給出安全漏洞的規避方式,或是提供可選的“開箱即用”式安全方案。最終,效果如下:
1.3 效果與不足
通過上述的思路,撰寫代碼安全指南并配套在線學習課程和考試,我們試圖解決開發人員不了解如何安全地開發的問題。當前,該方向仍存在兩項挑戰:
1、補充完善 sink 點的工作長尾且任務量大,需要隨著內外部發現的漏洞、編程語言&框架的迭代不斷迭代。為此我們決定將上述代碼安全指南通過 Github 開源,希望和社區攜手,一道維護完善。項目地址:https://github.com/Tencent/secguide
2、代碼安全指南只是安全左移建設的第一步,還需解決的挑戰有:
開發人員有一定安全意識,但因為趕進度或疏忽遺漏編寫安全機制,或是錯誤地實現安全校驗邏輯
代碼編寫是否安全全憑開發人員自覺,缺乏提示、檢查和卡點機制
II. 靜態代碼安全檢查
2.1 現有技術
“代碼編寫是否安全全憑開發人員自覺,缺乏提示、檢查和卡點機制”的問題,解決方式是:靜態代碼安全檢查解決。
要對代碼安全規范掃描,我們首先需要考慮的就是將源碼表示成一種方便檢查的形式,然后選擇合適的方式進行掃描。常規的源碼表示方式以 AST(抽象語法樹)和 IR(中間表達)為主:以 C++ 為例, clang 可以將 C/C++源碼轉換為 clang AST 和 LLVM IR。
一般而言,IR 是從 AST 經過層層轉換而來,所以會比 AST 擁有更多信息。但相對的,每種語言一般會有自己不同的 IR,處理起來會相對比較困難。而 AST 的形式則簡單直觀,操作起來也比較容易。
源碼
Clang AST
LLVM IR
根據選擇的源碼表示不同,有不同的方式做代碼檢查:
方式一、AST 匹配
第一種方式是在 AST 上做檢查,既然源碼被表示成了樹的形式,我們就可以遍歷 AST,使用一些 pattern 去檢查代碼規范中的問題。如:Go 語言代碼安全指南中的 1.7.2 條目(CSRF 防護)
//?good import?("net/http""github.com/gorilla/csrf""github.com/gorilla/mux")func?main()?{r?:=?mux.NewRouter()r.HandleFunc("/signup",?ShowSignupForm)r.HandleFunc("/signup/post",?SubmitSignupForm)//使用csrf_token驗證http.ListenAndServe(":8000",csrf.Protect([]byte("32-byte-long-auth-key"))(r))}對于該樣例,我們需要做兩個檢查:
檢查 http.ListenAndServe 參數中是否存在 CSRF 防護相關配置
檢查該配置的正確
具體實現上,我們可以遍歷該文件的 AST,尋找到 http.ListenAndServe 調用所在的節點,遍歷它的參數,觀察是否存在 CSRF 防護相關的參數,再對參數的內容正確性做檢查。
通過使用 AST 的方式我們能方便快捷的進行相關規范條目的驗證。但對于一些條目,例如 C++的 1.2 條目:
//?Goodstd::string?cmdline?=?"ls?"; cmdline?+=?user_input;if(cmdline.find_first_not_of("1234567890.+-\*/e?")?==?std::string::npos)system(cmdline.c_str()); elsewarning(...);很顯然這里如果要判斷它違反規范需要滿足兩個條件:
cmdline 含有用戶輸入
沒有對 cmdline 做相關檢查
如果說第二個條件還能通過模式匹配的方式檢查的話,第一個條件就很難通過模式匹配的方式檢查了,所以我們需要另一種檢查方式。
方式二、污點分析
污點分析是更為常用的檢查安全漏洞的方法。通過標記外部輸入點、基于程序數據流觀察數據是否能到達危險函數(如:SQL 查詢,命令執行等函數)來檢查安全漏洞。
要實現污點分析,有三個核心的關鍵點:
source 點:表示外部輸入,如 web 輸入,文件輸入等。
sink 點:表示危險的函數調用或者變量賦值,如 system 等函數
sanitizer:表示過濾點,經過過濾點的數據將被取消標記。
以下面這段代碼為例,污點分析從 user_input 一路進行數據流追蹤(一般因為 source 點的數量遠遠大于 sink 點的數量,會反過來從 sink 點開始回溯以提升效率),中間的檢查就是 sanitizer,這時候會取消標記,因此該漏洞并不成立。
使用污點分析,由于是通過數據流追蹤的方式得到漏洞,我們能得到程序相對精確的漏洞觸發流程,便于研發二次檢查。同時因為依賴手動配置 source 點、sink 點和 sanitizer,會有部分漏報。而且研發往往會采用不同的過濾方式,不同的寫法,導致 sanitizer 并不能很好的確定下來。在大型項目中,組件往往分布于不同倉庫,加上許多自定義的通信框架,完整的程序數據流會很難得到。
綜上我們可以總結出兩種不同的掃描方式各自的優缺點:
2.2 工具調研
在初步了解了掃描方式后,就要對社區工具做調研。針對單一語言的工具寫起來就太多了(各種語言的 lint),這里主要提兩個工具:Semgrep 和 CodeQL。一是這兩個工具支持語言都不止一個,二是在各自技術領域它們都比較有代表性。
2.2.1 Semgrep
Semgrep 是一款基于 Facebook 開源 SAST 工具 pfff 中的 sgrep 組件開發的開源 SAST 工具,目前由安全公司 r2c 統一開發維護,提供強于 grep 工具的代碼匹配檢索能力。
其核心技術原理可以用下面這張圖概述:
Semgrep 支持兩種類型的代碼模式匹配。一種是基于 AST 的匹配,使用 tree-sitter parse 各種語言的源碼,并將它們轉換成 generic AST(Semgrep 內的一種通用 AST 格式),然后再使用規則匹配。舉個例子,如果要檢索代碼中使用 strcpy 的代碼行,可以編寫如下 ripgrep 命令:
rg --quiet --stats strcpy -tc
但類似如下的代碼也會被匹配到,實際上它僅為注釋,并沒有真正調用 strcpy:
45:// string.h is not guaranteed to provide strcpy on C++ Builder.
而運行如下 semgrep 命令,即可基于 AST 搜索,實現更精準的匹配。其中 ... 是 semgrep 提供的代碼模式匹配語法 —— 省略號運算符(Ellipsis operator),用于代表若干參數、語句或字符:
semgrep -e "strcpy(...)" --lang=c .
另一種模式是 generic pattern matching,使用一個通用文本 parser(spacegrep),通過分詞和特殊字符的識別來做代碼模式匹配。相比基于 AST 的匹配,該模式能力較弱,但拓寬了工具對各類編程語言的覆蓋能力。例如對 YAML、ERB、Jinja 等語言,就可以使用該模式進行檢查。假設有一個配置文件如下,想要檢索其中不正確的“allowed_origins”配置:
resource "aws_s#_bucket" "b"{?????????????????bucket = "s3-website-test-open.hashicorp.com"acl = "private"??????????????????cors_rule {allowed_headers = ["\*"]allowed_methods = ["PUT", "POST"]allowed_origins = ["\*"] \# \<--- Matches hereexpose_headers = ["ETag"]max\_age_seconds = 3000} }?????????????盡管還不支持解析該文件格式的 AST,可以基于 spacegrep 提供的能力,編寫如下規則對代碼庫進行檢索:
但該種匹配模式下,有時無法區分出是真實的 API 調用,還是代碼注釋。兩種模式對同一代碼片段匹配效果,比對如下:
綜上,Semgrep 的特點如下:
安裝便捷。通過包管理工具安裝 cli,即裝即用。
規則上手、編寫簡單。采用 yaml 配置文件編寫掃描規則,語法簡單但表現能力相較于傳統 grep 類工具更強大。
引擎本身和規則集均開源,且支持的規則集豐富,已經開源包含總計有 1000+條規則。
掃描速度快。直接基于 AST/文本匹配,工具效率會相對較高。經測試,掃描速度可達到 2~10w 行代碼/秒。
支持代碼自動修復替換。通過 AutoFix 語法可自動修復存在安全風險的代碼。
易于集成,官方已給出了一系列和 CI 集成的配置,涉及 14 款 CI 平臺,如 Jenkins、Gitlab、Circle CI 等。
2.2.2 CodeQL
CodeQL 是 Semmle 公司推出的一款靜態代碼分析工具(以前叫 Semmle QL),后被 Github 收購,并成立了 Security Lab 支持 Github 的開源代碼安全檢查能力。
相對于 Semgrep,CodeQL 走的是深度分析的技術路線,核心技術原理是分析源碼并將其轉換成代碼快照,然后通過它自己的 QL 查詢語言做代碼查詢來達到掃描的目的。
如上圖,先提取不同語言的源代碼文件到代碼快照,然后將查詢規則(.ql 文件)編譯成 CodeQL 內部的查詢形式,再對代碼快照進行查詢。
其規則形式如上(一部分),編寫起來會比較復雜。CodeQL 的優勢是支持完整的污點分析和過程間分析,相對不可避免的,分析時間會大大上升。
值得一提的是:兩款工具都對策略規則寫法做了統一,能較好地解決跨編程語言檢查的需求。 設想一下:如果用每種語言的 lint 編寫檢查規則,不同 lint 間的規則語法不一致,將會帶來比較高的維護門檻。
2.2.3 比對及選型
通常,編寫代碼涉及三個環節 -- 編碼、代碼托管、CI/CD,開發人員在各階段對檢查工具和結果的期望和要求是不同的。可以簡單概括并比對如下:
兩款代碼檢查工具可簡單比對總結如下:
2.3 結論與實踐
在編寫代碼的不同階段,開發人員對檢查工具和結果的預期和要求各不相同。在不同編碼階段采取的靜態代碼安全檢查方案可概括如下:
1、本地編寫階段
在本階段,對工具有一定要求:速度快,容錯性要高。而且往往這個點代碼還未寫完,工具的檢查錯誤可以快速得到修復。這時候 AST 模式匹配就會是一個很好的檢查方式。在編碼階段,可以使用 semgrep 等類似 lint、grep 工具,封裝為 IDE 插件。
實踐過程中,還可以嘗試引入一些更激進的策略,如:提示并要求修改不安全的 SQL 查詢拼接邏輯。開發人員可根據提示快速判斷,如果風險確實存在,即借助自動修復功能修改代碼,進而在代碼構建前收斂安全風險。
2、構建部署階段
這個階段代碼已簽入代碼倉庫,類似 semgrep 或 CodeQL 的方案可封裝為流水線原子,提供給開發人員使用,并配套提供安全卡點(質量紅線)機制。如果檢查出安全漏洞,應給出詳細的漏洞觸發路徑,并提示風險關聯的代碼安全指南條目來引導修復。
3、日常檢查階段,代碼倉庫檢查
該階段一般為純旁路的檢查,時效性可以適當放寬,可進行一系列復雜的分析。但需要注意的是,由于代碼倉庫是純靜態代碼,如果工具對編譯有要求(如 Clang,CodeQL 的部分語言),在該階段檢查應注意編譯環境的適配。
值得一提的是,代碼安全規范/指南也在編寫策略的過程中扮演非常重要的角色。如果公司內有一份比較清晰、完善的規范,能詳細地列出各類容易出錯的 API,編寫檢查規則會容易許多。
III. 默認安全的框架組件
3.1 背景
當有了一份代碼安全指南和配套的靜態檢查機制后,開發人員仍需要自行在項目中引入或實現安全校驗邏輯。這時候就會遇到“開發人員有一定安全意識,但因為趕進度或疏忽遺漏編寫安全機制,或是錯誤地實現安全校驗邏輯”的問題。
深挖背后的原因及“痛點”,我們認為可以歸納為如下三點:
全憑安全意識不靠譜。 即便是安全工程師也會犯錯,需要將安全指南的要求轉化為開箱即用式的安全組件。
重檢查,輕具可操作性、便捷的解決方案。 檢查工具聚焦于發現問題,但開發人員在解決問題的時候,如果沒可操作的解決方案,修復工作往往難以推動。
研發效率與質量。 不同業務重復在寫安全校驗邏輯,不僅浪費人力,還容易出錯。
通過分析業界相關理論與實踐,借助公司建設統一后臺框架的契機,我們開展了開展默認安全的框架組件建設。
3.2 分析與解決
3.2.1 業界理論與實踐
1、嵌入框架的安全組件。 Google 在《Building Secure and Reliable Systems: Best Practices for Designing, Implementing, and Maintaining Systems》一書的第 12 章中分享了其內部在代碼編寫階段開展的安全左移建設實踐。可概括為:
“越早越好”。應該在軟件設計初期就考量安全、穩定性問題。否則,越往后代價越高,過程會很痛苦。(筆者注:本質上就是安全左移)
“安全意識教育很重要,但不是銀彈,即便是安全工程師也會犯錯”。依賴安全意識教育,效果不佳。這是因為,業務開發階段,關注點往往是功能的實現,要兼顧安全和穩定性設計方面的權衡,會很難。因此,應側重關注安全機制、工具的建設。
Google 團隊認為,安全能力嵌入框架大有裨益,如下:
規范化與一致性,復用最佳實踐。某些功能容易出問題,通過框架封裝,能減少由業務各自實現產生的風險
提升研效。業務邏輯與通用功能抽離,專注業務邏輯開發,無需關注其他細節。不僅能減少代碼審閱的精力,也能縮短修復問題的時間。
降低修復成本及時間。雖然框架不能保證預防、解決所有安全問題,但出現問題時,只需要在“一個點”集中解決
2、Security by Design。 USNIX15'的議題《Preventing Security Bugs through Software Design》中拋出了與眾不同卻巧妙的觀點:寫出漏洞不一定是開發者的問題,而可能是 API 設計得容易出錯。以 SQL 注入為例,盡管大部分語言、組件和框架都提供了參數綁定(參數化查詢)的功能,安全規范也有不斷強調。但開發人員仍非常容易寫出帶 SQL 注入問題的代碼。
為解決前述問題,提出了一種名為 trustedsqlstring 的機制,從接口設計層拒絕拼接 SQL 查詢語句傳入。以 Go 語言例,各類參數需要標注靜態類型的機制。通過修改 SQL 查詢組件導出操作函數的入參類型,可以從 API 設計機制上禁用查詢拼接,僅允許通過占位符動態拼接參數值進入查詢語句。
雖然 Google 僅分享了針對 XSS 和 SQL 注入做組件加固的方案,并不足以覆蓋所有應用漏洞。但核心思路仍具有借鑒價值,可歸納為:基于白名單模式,對現有組件做安全加固,使安全機制在默認情況下能生效。
3.2.2 安全組件方案分析
通過整理匯總,可以把現有的安全過濾方案分為三類:校驗、過濾和組件。
從上述對比來看,組合采用校驗,和帶默認安全機制的功能組件(融入 Security by Design 設計思路)兩個方案是最優解。
3.2.3 落地案例
數據校驗是幾乎每份安全規范類文檔會囊括的要點,但實際在業務研發過程中,落地情況并不理想。 一方面,引入數據校驗有一定成本和門檻,導致該邏輯往往會被省略;另一方面,即便是編寫了數據校驗邏輯,其準確性和安全性也鮮有檢查。結果是:我們在內部安全工單系統中,能看到許多開發人員在漏洞處理結論時備注“未做數據校驗,已經通過添加相關邏輯解決”。據內部復盤數據統計,這類可通過數據校驗規避的漏洞約占歷史 Web 漏洞安全工單數量的 70%~ 80%。
為此,我們為公司級 RPC 框架引入了一套 Validation 組件和檢查、卡點機制,并取得了不錯的效果。 公司級 RPC 框架使用 Protocol Buffer 作為 IDL,根據設計理念,Protocol Buffer 原本就帶有一定數據校驗類似的特性。但經分析,其不足以支撐業務和安全的需求,例如:校驗入參是否為空?傳入的是否是字母數字組合,這些需求是 PB 原生的能力無法支持的。因此,需要引入第三方數據校驗組件補充這部分能力,當前主要有兩類方案:
方案 1、在代碼中引入 validator,并編寫校驗規則
方案 2、在 IDL 文件中編寫校驗規則并自動生成代碼的 protoc 插件
通過分析對比,最終選擇了方案 2 —— 開發人員在定義 proto 文件時即在拓展字段中定義好校驗規則,過程如下:
同時,通過對歷史漏洞的復盤分析,我們發現許多漏洞是 string 類型的字段未限制字符集產生的。如:id 參數功能上僅允許數字傳入,但未做校驗,允許傳入`)('"等字符,帶入經拼接產生的 SQL 查詢語句,最終產生了 SQL 注入漏洞。于是,我們在內部代碼安全指南中添加了明確的要求:請求(Req)消息體中的 String 類型字段必須限定格式/字符范圍+長度。
另一方面,我們還與基礎設施開發團隊合作,將上述組件嵌入了 proto 管理平臺默認提供的文件模版中。開發人員幾乎可以無額外成本,快速上手使用這套機制:
此外,我們還設計了靜態安全檢查和卡點機制,并引入上述平臺,來保證數據校驗邏輯的準確性和安全性。開發人員在保存 proto 文件時,能立即獲得提示并及時修正存在的安全隱患。
綜上,數據校驗本身是一項業務需求,通過降低開發門檻、給出安全要求并配套自動化檢查和卡點機制,在框架層提供組件讓每個業務模塊都能做好數據校驗。基于前述思路建設的組件還有不少,包括:DB 組件、網絡資源請求組件等。這些組件不是自成一體的安全過濾函數庫,而是與某項特定功能需求結合的特定組件。
3.3 效果與小結
結合對業界現有理念與實踐的分析,我們基于代碼安全指南在公司級框架上建設了一系列“默認安全”的組件,并設計了一系列檢查工具嵌入在統一的研發基礎設施中。
理想情況下,組件是和代碼安全指南高度對應的。舉個例子,開發人員在 Go 項目編寫資源請求功能時,無需在每個項目中自行實現 SSRF 防御邏輯,只需引入組件即可快速實現業務功能,又確保安全。
由此帶來的收益是:
更高的業務接受度,安全機制內置在功能組件中,使用幾乎無感知,且會被當作一種最佳業務實踐口口相傳,逐步獲得高覆蓋度;
代碼安全檢查更準確方便;
研發效能的提升,開發人員無需自行、重復實現安全校驗/檢查代碼。
當然,上述工作也給安全和基礎組件研發團隊提出了挑戰:既要對應用安全風險有全面且深入的了解,在開發安全組件時,還要兼顧功能靈活性(業務需求)和安全性(安全需求)。
IV. 總結
綜上,借助代碼安全指南、默認安全框架組件、嵌入基礎設施的靜態代碼安全檢查三項機制聯動,我們試圖在軟件研發生命周期的最初階段收斂漏洞。
在上述框架下,研發和安全人員日常開展工作的模式為:
研發人員
閱讀學習代碼安全指南、安全組件文檔
業務基于統一框架、組件設計功能,聚焦于業務邏輯
使用自助安全檢查工具,在 DevOps 各環節檢查漏洞,漏洞修復指引會鏈接回代碼安全規范,形成閉環。
安全人員
有新的漏洞進來 -> 分析提煉漏洞模式(變體分析)-> 沉淀至代碼安全規范
基于代碼安全規范編寫檢查規則(淺層和深層)
推出對應的安全組件
在安全左移探索過程中仍有許多機制尚待優化,我們希望通過逐步開源上述解決方案,與業界一道豐富安全左移的理論和實踐。
上述探索過程中,獲得了基礎設施研發團隊(框架、持續集成平臺)、業務側研發安全團隊的支持,在此獻上誠摯的謝意。
參考資料
Kern, Christoph. "Preventing security bugs through software design." (2015).
Wang, Pei, Julian Bangert, and Christoph Kern. "If It’s Not Secure, It Should Not Compile: Preventing DOM-Based XSS in Large-Scale Web Development with API Hardening." 2021 IEEE/ACM 43rd International Conference on Software Engineering (ICSE). IEEE, 2021.
Adkins, Heather, et al. Building Secure and Reliable Systems: Best Practices for Designing, Implementing, and Maintaining Systems. O'Reilly Media, 2020.
輕量級開源 SAST 工具 semgrep 分析
騰訊研發安全團隊
騰訊公司內部與自研業務貼合最緊密的一線安全工程團隊之一。團隊負責軟件生命周期各階段的安全機制建設,包括:制定安全規范/標準/流程、實施內部安全培訓、設計安全編碼方案、構建安全漏洞檢測(SAST/DAST/IAST)與 Web 應用防護(WAF)系統等。在持續為 QQ、微信、云、游戲等重點業務提供服務外,也將積累十余年的安全經驗向外部輸出。通過為騰訊云的漏洞掃描、WAF 等產品提供底層技術支撐,助力產業互聯網客戶安全能力升級。
總結
以上是生活随笔為你收集整理的安全左移理念,鹅厂 DevSecOps 如何实践?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一通电话被骗走4年生活费,她决定用技术守
- 下一篇: 一文入门 Kafka