本文收錄於《阿里新一代安全架構-安全基建專欄》
作者:阿里安全高階安全專家飛蝠
利用漏洞清除債務,盜取資料,一鍵獲取XX遊戲的所有賬戶登陸許可權,這些看似爽文裡的“騷操作”其實早就在現實中上演。
2013年,一個自稱RedHack的黑客小組利用土耳其政府網站的Web漏洞,清除了相關人員在政府機構的債務資料。2015年,某安全研究人員公開稱,可以通過特定的注入漏洞攻破某知名汽車的網站,獲得管理許可權,並竊取使用者資料。2019年,擁有超過3.5億使用者的線上遊戲“XX壘之夜”被爆出一個SQL隱碼攻擊漏洞,可以讓攻擊者訪問所有使用者帳戶。
這些都是Web應用程式的漏洞,Web應用程式已經廣泛應用社交網路、網上支付等各個領域,真正影響人們的生活,因此Web應用中存在的各種安全漏洞越來越引起人們的重視。
為趕在惡意人員之前發現並修復Web應用程式中的安全漏洞,安全人員需要利用各種安全測試技術識別並修復Web應用程式中的缺陷。靜態應用安全測試(Static Application Security Testing ,SAST)由於不需要執行被測程式,具有覆蓋率高、自動化程度高、可以在開發生命週期早期使用等特點,是目前被業界廣泛採用的應用安全測試技術之一。但是靜態應用安全測試作為一種針對應用安全缺陷的自動化檢測方法,本質上處理的是一個不可判定問題,理論上不可能同時做到沒有誤報也沒有漏報。
大量的誤報會使人對分析工具失去信心,而漏報會造成程式具有較高安全水位的假象,很多情況下減少誤報和減少漏報就是一對矛盾體。為儘量減少不必要的漏報和誤報,往往需要運用更復雜的分析技術,意味著更高的複雜度,因此分析的精度與分析的速度往往也是一對不可兼得的矛盾體。實用的靜態應用安全測試工具需要根據分析目標和應用場景在誤報、漏報、效率、易用性、可擴充套件性之間達到一個合理的平衡。
哪些缺陷型別需要“關心”
程式分析工具都有其針對的“分析目標程式屬性”(target program properties),通俗地來說“分析目標程式屬性”就是分析工具“關心哪些缺陷型別”。當前許多通用的靜態缺陷檢測工具往往強調“大而全”,強調能夠適應不同的掃描場景,強調能夠覆蓋更多的缺陷型別,實際上這裡存在誤區。實際中的程式千變萬化,對不同型別的程式,在不同的場景下,人們關注的程式屬性不一樣,對分析工具的各項要求也不一樣。靜態分析都會引入某種程度上的抽象,最有效的抽象方法需要充分利用分析目標程式屬性本身的特點。明確應用場景和分析目標程式屬性(target program properties)是設計真正實用分析工具的首要任務。
Web應用靜態安全測試的主要應用場景在開發階段而不是開發完成之後,它的重要優勢是能夠在早期就檢測出原始碼中的安全漏洞,從而大大降低修復安全問題成本,成熟的大型軟體開發組織通常將其融入DevSecOps流程中。這更加要求分析工具能夠在漏報、誤報和效率之間達到合理的平衡,避免不必要地打擾和減緩正常開發流程。
Web應用靜態安全測試的分析目標程式屬性是常見的Web應用程式安全風險,核心關注的就是OWASP Top 10中列出的安全風險。下圖是最新發布的OWASP Top 10Web應用安全風險:
Web應用程式安全風險和空指標解引用、陣列越界、資源洩漏、數值溢位等記憶體安全程式屬性有顯著區別。Web應用程式安全風險從程式語義上看更加高層(更加靠近應用層),記憶體安全則更加底層,更加關注程式中變數的具體取值情況。為了開發真正實用的分析工具,需要充分利用“分析目標程式屬性”的特點,選擇能夠達到最佳平衡的分析演算法和策略。
Web應用安全風險程式屬性建模
為了保證靜態應用安全測試工具能夠無二義性地識別和分析目標缺陷型別,我們將目標缺陷型別的分析配置描述為靜態應用安全測試工具能夠識別的“規則”。易用且可擴充套件性好的Web應用靜態安全測試工具都應該做到規則和引擎分離。規則描述結構設計的過程本質上是對Web應用程式安全風險知識進行建模的過程。OWASP Top 10列表中的Web應用安全風險可分為兩類:一類是和非正常資料流相關的安全風險,如注入、敏感資訊洩露、XML外部實體、跨站指令碼和不安全的反序列化。一類是和非正常控制流或狀態相關的安全風險,如失效的身份認證、失效的訪問控制、安全配置錯誤、使用含有已知漏洞的元件不足的日誌和監控。我們採用兩種不同的規則描述模型來支援上述兩類Web應用安全風險:汙染傳播模型和狀態機模型。
汙染傳播分析
汙染傳播分析又被稱作資訊流分析(information-flow analysis),它是用於追蹤程式中特定資料傳播和依賴的一種資料流分析技術。汙染傳播分析是Web應用安全缺陷檢測的主要方法之一,其基本思想是通過對不可信的源頭(source)引入的資料進行汙染標記,跟蹤被標記的汙染資料在程式中的傳播,若汙染資料在進入敏感操作(sink)前未經過恰當的淨化操作(sanitizer),則表明存在潛在的安全缺陷。
汙染傳播規則中的配置包括source、sanitizer、sink、安全型別等。安全型別指的是對於當前目標程式屬性來說認為肯定不會汙染的型別,例如對於注入類安全風險可以認為所有的列舉型別、布林型別、日期型別、浮點型別等都是安全的。
對於常見的web注入安全風險,我們的解法是,提供統一的“安全方法”給開發人員呼叫,這些“安全方法”也是靜態分析工具能夠識別的統一的淨化操作。汙染傳播分析沿控制流在每個程式位置上計算當前汙染變數集合,並在汙染變數間建立汙染傳播依賴關係。
狀態機分析
理論上來說,Web應用安全缺陷檢測所檢查的缺陷型別都屬於時序安全屬性(temporal safety properties),安全屬性描述的是“壞的事情不會發生”一類屬性,通常可以描述成如下統一模式:“程式中某些動作或行為構成時序上的約束,一旦違背這種約束即被認為是一個缺陷”。
有限狀態機(finite state machine)是描述時序安全屬性的有效工具,汙點傳播相關的缺陷型別本質上也屬於時序安全屬性,即“來自source的資料在進入sink點之前必須經過sanitizer操作,否則報告一個缺陷”(但為了缺陷報告時更好地給出汙染在變數間的傳播路徑,將其採用專門的汙染傳播分析進行建模)。狀態機規則中的配置包括狀態集合、狀態間的轉換集合以及各轉換所需滿足的條件集合等。
在實際的狀態機分析過程中還需要引入狀態機例項的概念,在程式中的每個分析入口函式處會建立一個狀態機例項,並沿控制流在每個程式位置上的計算它的可能狀態。如果一旦某個狀態機例項的當前可能狀態中出現了error狀態則報告一個缺陷。
分析策略選擇
從不同的抽象和近似精度角度,靜態分析方法可以區分是否流敏感(flow sensitive)、路徑敏感(path sensitive)、上下文敏感(context sensitive)、域敏感(field sensitive)、物件敏感(object sensitive)等。
具體來說流敏感需要在分析中考慮語句的執行順序,路徑敏感需要在分析中考慮分支判斷條件的組合關係並排除不可達路徑(infeasible path),上下文敏感需要在分析中考慮被調函式在不同呼叫點的上下文影響,域敏感需要在分析中區分同一物件的不同欄位,物件敏感需要在分析中區分同一欄位的不同物件。一般來說,敏感性支援得越多,分析精度越高,實現越複雜,分析速度越慢。對於實際的靜態分析工具來說,最好的選擇是根據分析目標和應用場景的需要花最少的代價獲得最大的回報。對於Web應用程式安全風險來說,引入路徑敏感的“價效比”並不高。
汙染傳播分析和狀態機分析本質上都可納入傳統的資料流分析框架,汙染傳播分析在每個程式位置上計算當前汙染變數集合,其對應資料流分析值為“當前汙染變數集合”。狀態機分析在每個程式位置上計算狀態機例項的的當前可能變數集合,其對應資料流分析值為“狀態機例項的的當前可能變數集合”。汙染變數集合和可能狀態集合的轉換函式都是滿足分配率。
傳統資料流分析基於迭代收斂完成過程內資料流分析,基於圖可達演算法完成過程間資料流分析。對於本文所關注的靜態應用安全測試分析目標程式屬性來說,傳統資料流分析演算法的“價效比”太低。傳統資料流分析中的迭代主要是因為實際的程式中存在迴圈和遞迴結構,需要通過迭代並收斂於不動點來處理控制流圖中迴圈回邊帶來的影響。而實際上對於汙點分析和狀態機分析(Web應用安全風險這類目標程式屬性)來說控制流圖中的回邊在實際中分析結果中的影響很小。至於圖可達演算法考慮的過程間呼叫和返回匹配問題可以在搜尋汙染傳播跟蹤路徑時進行單獨處理。在不考慮迴圈和遞迴結構的前提下(相當於迴圈和遞迴只展開1次),汙染傳播分析和狀態機分析可以做到接近線性複雜度O(n),n為程式中的語句條數。
函式摘要
函式摘要(function summary)是靜態分析過程中常用的一種過程間分析技術,它根據函式內分析結果生成被調函式的摘要資訊,以此替代函式的實際展開,從而避免同一個函式的多次展開分析,提高函式間分析效率。函式摘要是對已展開分析過函式的“抽象和總結”,函式摘要可以看作是以函式為單位,對函式實際語義的抽象。其理想的效果是:使用函式摘要得到的計算結果等於展開實際函式呼叫得到的計算結果。
需要指出的是函式摘要是對函式實際語義的抽象,這種抽象必然是面向實際分析目標程式屬性特點的,應該根據不同的分析目標程式屬性設計並收集對應的函式摘要。由於靜態分析的不可判定性,通用的精確的函式摘要必然退化為函式的另一個完整實現。由於汙染變數集合和可能狀態集合的轉換函式滿足分配律,面向汙染傳播和狀態機的函式摘要完全可以滿足:使用函式摘要得到的計算結果=展開實際函式呼叫得到的計算結果。
跨應用、多語言支援
這裡所謂的“跨應用”,其實用“跨掃描單元”來表述可能更為準確,“掃描單元”是掃描過程中確定和區分被掃物件的基本管理單位,它與缺陷的關閉與合併,許可權管理,掃描中間結果的記錄等有關,直觀地理解就是一次原始碼掃描過程中的被掃物件。
目前市面上的靜態應用安全測試工具都侷限於處理單個掃描單元內部的汙染資料傳播,無法處理跨掃描單元傳播的場景,隨著微服務/Serverless/FaaS等開發技術和模式的逐步演進,業務開發程式碼日趨碎片化,使得這一問題愈發嚴重,成為靜態應用安全測試技術的重大挑戰。跨掃描單元所關注的單元間依賴關係分為兩類:一類是通過引用二三方包而形成的依賴關係,另一類是通過各種遠端呼叫服務(remote procedure call , RPC)形成的依賴關係。前一類依賴關係通常在編譯時可以通過類似maven這樣的機制獲取,後一類依賴關係通常需要通過分析具體的配置檔案獲取或者掃描時由使用者額外提供。
最直接的跨單元掃描解決方案是將所有相關掃描單元程式碼進行合併掃描。但是在實際中,這樣會使得單次掃描的程式碼量急劇膨脹而難以實現。另外,對於被依賴掃描單元來說,每次的重複掃描也將會是極大的資源浪費。
在實際中通常平均每個“應用”依賴的其他掃描單元(包括二三方包依賴和RPC依賴)超過200,最大甚至超過2000。對於這些依賴非常多的“應用”,所有相關掃描單元程式碼合併後的程式碼將會超過1000萬行。本文所述分析工具當前執行節點的典型配置為8核32G記憶體,單個掃描任務要求掃描時間不超過10分鐘。工具的記憶體開銷與程式碼行數基本成線性關係,實際中平均每10萬行程式碼消耗記憶體約2G左右。時間開銷與程式碼行數關係略高於O(n),10萬行程式碼的掃描時間約1分鐘左右。因此合併掃描的方案在實際中由於空間、時間以及儲存成本的限制而無法實現。
一種更好的跨單元掃描解決方案是:首先,在不損失精度的前提下,以掃描單元為單位建立被依賴單元的靜態應用安全檢測中間結果表示,並將這些中間結果持久化地儲存下來;其次,在其他單元掃描前,先依據其依賴關係將需要的中間結果下載到本地,並應用於當前單元的掃描過程。
根據上一節的討論,基於汙染傳播和狀態機的中間結果表示核心即是函式摘要。另外,對於通常的RPC呼叫來說,只要在介面層面進行了統一,具體用何種語言實現對呼叫方是完全透明的,因此,基於函式摘要的跨單元掃描解決方案天然支援跨語言。上述方案如下圖所示:
經驗與體會
本文討論的Web應用安全靜態測試工具主要的使用方式是與應用持續整合/釋出平臺對接,作為持續整合/釋出的一個環節,在釋出之前整合釋出平臺呼叫工具進行程式碼安全掃描,如果發現安全缺陷則通知使用者進行修復,修復後才可以釋出上線。在這樣的應用場景下有如下幾點總結和體會:
1. 實用的靜態應用安全測試工具通常是根據分析目標和應用場景在誤報、漏報、效率、易用性、可擴充套件性之間達到一個合理的平衡。
2. Web應用安全風險和通用的記憶體安全漏洞有不同的特點,這些特點決定了分析演算法和策略的選擇。
3. 函式摘要對於Web應用安全風險相關的靜態分析來說是一種重要的技術,它不僅可以大大提高應用內掃描的效率,也是支援跨應用多語言掃描的一種方法。
4. 靜態應用安全測試方法有許多天然的優點,但也有其固有的缺點,在實際中亟需將它與其他方法結合起來,才能更好地面對不斷湧現的Web應用安全檢測新場景和新需求。