編者按:圖表視圖流可以使我們能夠快速、有效和準確地找到最佳定位位置。本文通過圖表視圖將代碼可視化,幫助開發人員描繪出代碼的安全狀態,查看修復不同位置漏洞的影響,自動將超大代碼庫的結果縮小到可管理的數量。
使用源代碼分析(SCA)工具最大的挑戰是如何有效地確定優先級并進行大量修復行動。對此,一般開發人員都有點不知所措,他們試圖分析包含彼此獨立呈現結果的安全報告。
例如,WebGoat(OWASP將不安全的Web應用程序用作安全培訓的測試平臺)具有100多個跨站點腳本(XSS)漏洞,假設每個漏洞修復需要30 min,而驗證又需要30 min,那么我們的研究將至少需要3周的時間。
對于包含數千行代碼的大型項目而言,或者對于具有快速開發周期的環境(例如DevOps),這種周轉時間肯定太長而且成本昂貴,甚至不切實際。由于存在大量的漏洞,因此釋放易受攻擊且未修復的代碼也就不足為奇了。
在本文中,在介紹源代碼分析如何修復漏洞之前,先簡單介紹一下源代碼分析的主要優勢,然后通過圖表視圖將代碼可視化,展示出如何幫助開發人員從漏洞到漏洞的直觀洞察力,描繪出那些代碼的安全狀態,查看修復不同位置漏洞的影響,自動將超大代碼庫的結果縮小到可管理的數量。
實際上,使用這種方法,即使不查看代碼,也可以將WebGoat XSS漏洞的固定位置數量減少到僅有16個。
源代碼分析一般指源程序分析,源程序分析是對應某一個具體問題的軟件(計算、遍歷、查找及排序),分析程序功能的原子結構、分子結構(在數據結構中稱為聚合結構),最后用特定算法綜合得到程序框架。
靜態代碼分析是一種自動分析應用程序的源代碼和二進制代碼以查找安全漏洞的技術。根據Gartner的2011年靜態應用程序安全測試魔力象限(SAST),“對于所有開發或采購應用程序的IT組織,應將SAST視為強制性要求”。
實際上,近年來,我們已經看到了應用程序安全性的轉變,而代碼分析已成為引入安全軟件開發和衡量固有軟件風險的標準方法之一。此領域中存在兩種類別:
(1)二進制或字節碼分析(BCA)
分析由編譯器創建的二進制或字節碼。
(2)源代碼分析(SCA)
分析程序的實際源代碼,而無需檢索所有代碼即可進行編譯。這兩種產品都承諾提供安全性以及將安全性納入軟件開發生命周期(SDLC)的要求。
一方面,BCA節省了一些代碼分析工作,因為編譯器使工作的一部分自動化,例如解析代碼符號。然而另一方面,具有諷刺意味的是,正是這種編譯器的卸載帶來了BCA的根本缺陷。為了使用BCA,必須在掃描所有代碼之前對其進行編譯。這就帶來了許多問題,這些問題使SDLC進程推遲,給安全性造成了不好的作用。
主要問題包括:
(1)漏洞在運行中暴露得太晚
由于必須在掃描之前編譯所有代碼,因此安全性在SDLC中被推到了相對較晚的階段。在這一點上,掃描通常發現要處理的漏洞太多,沒有時間修復,并且銷售和市場團隊要求發布產品。結果,這些漏洞(盡管已被發現)被推送釋放。在實際項目中(例如在Linux OS發行版本中發生的掃描過程),實際的漏洞已經在掃描過程中逐漸消失。
(2)編譯器優化會損害結果的準確性
編譯器執行的許多任務之一是根據效率和大小來優化代碼。但是,這種優化可能會犧牲結果的準確性。例如,編譯器可能會刪除所謂的“無關”行,也就是無效代碼。這些是開發人員在調試過程中插入的代碼行。在編譯器刪除這些代碼段的同時,它們可能包含違反公司標準的代碼。
(3)PaaS提供程序無法檢索字節碼
在云計算場景中,PaaS提供者負責程序的驗證、專有編譯和執行。但是PaaS提供程序又無法檢索字節碼,或者沒有體現為字節碼或二進制。
通過掃描源代碼本身,可以將SCA順利集成到SDLC中,并提供有關代碼及其安全性的近乎實時的反饋。源代碼分析可以彌補BCA的不足,并提供有效、可行的替代方案。
(1)掃描代碼片段和非編譯代碼
SCA工具能夠掃描代碼片段,而不管由于語法或其他錯誤引起的編譯錯誤。審核員和開發人員都可以在開發過程中掃描不完整的代碼,而無需完成構建,最終可以在軟件開發生命周期(SDLC)的更早階段發現漏洞。
(2)支持云編譯語言
在云計算場景下已經開發了新的編碼語言。在這些情況下,開發人員使用PaaS提供程序的語言進行編碼,而PaaS提供程序負責驗證,專有編譯和執行程序。在這些情況下,代碼既不表現為字節碼也不表現為二進制,并且SCA必須在源代碼本身上完成。
比較典型的示例是Sales force.com提供的Force.com平臺,該平臺基于被稱為Apex的基于服務器的語言和VisualForce的基于客戶端的語言。只有SCA產品才能支持此新范例。
(3)評估非鏈接代碼的安全性
如果代碼引用缺少其源代碼的基礎結構庫,則BCA工具會立即在不幸的“缺少庫”消息上失敗。可能需要花費幾天時間為這些缺失的部分構建存根,如果只是為了使代碼得以編譯,這種大量的辛苦工作是沒有任何附加價值的。SCA產品可以輕松識別漏洞,例如SQL注入——即使缺少執行SQL函數調用的實際庫代碼。
(4)不可知的編譯器
通常情況下,在代碼審核員和大型公司中找到的多編譯器環境中,SCA標準提供了一種適合所有人的解決方案。這與BCA完全相反,后者必須支持無數的編譯器和版本。原因是什么呢?
每個編譯器都將源代碼轉換為自己的二進制或字節代碼版本,從而迫使BCA工具讀取,理解和分析不同編譯器的不同輸出。但是,由于SCA工具是在代碼本身上運行的,而不是在編譯后運行的,因此SCA提供了與編譯器版本或編譯器升級無關的單個標準。
(5)與平臺無關
將SCA集成到SDLC中時,可以使用完全相同的工具在任何地方掃描代碼,而無需考慮操作系統或開發環境。這消除了BCA固有的冗余性,后者必須為每個平臺提供單獨的掃描工具。
“知道您的敵人”是任何安全專業人員的口頭禪。它定義了我們所面對的,以及如何面對它并采用何種策略,它為所有未來成果奠定了基礎。對開發人員而言也是如此——敵人是易受攻擊的代碼。應用程序安全操作方法如下:
在安全編碼的實踐中,開發人員應大致了解其代碼的安全狀況,代碼中包含的漏洞數量以及如何將自己表現出來以達到利用的目的。這是圖表視圖將代碼可視化的基礎。
(1)基礎知識:數據流
最好將數據流描述為從漏洞源到可以利用它的點(也稱為“接收器”)的代碼路徑的可視化。如圖1所示,流程中的每個步驟都反映為圖中的一個節點。
傳統上,每個漏洞結果只有一個數據流,與其他結果無關。因此,對于眾多結果(例如14個不同的漏洞發現),我們可以查看具有14個獨立流的圖表視圖,如圖2所示。
顯然,這樣的圖對理解如何確定修復的優先次序沒有太大幫助。開發人員真正需要的是理解不同流程之間的關系,并盡可能簡化生成的圖表視圖。
(2)改善可見性:圖表視圖
圖表視圖采用這些單獨的數據流,并以易于呈現流之間關系的方式對其進行描述。建立圖表需要兩步的過程。
第一步:合并出現在多個路徑中的同一節點。換句話說,標識并合并實際上由同一數據流共享的那些代碼。從上方獲取14路徑圖,請考慮最左側的5個源共享同一節點的情況。反過來,此節點與位于其級別的另一個節點,共享一個更靠近接收器的節點,如圖3所示。

圖1 數據流流程示意圖

圖2 具有14個獨立流的圖表視圖
第二步:簡化圖表視圖以減少數據流級別的數量。這可以通過將看起來相似的數據流組合到單個節點來完成。對于熟悉圖論的人來說,您可能現在已經意識到,我們正在構建原始圖的“homeograph”,即結構相同但表示簡化的圖。我們首先將節點分組,如圖4所示。
隨著我們繼續這一過程,最終的圖表視圖結果如圖5所示。
通過簡化的圖表視圖流,我們現在就可以直觀地看到代碼的安全性,不再僅僅看代碼位和看似完全不同的代碼缺陷,圖表流實際上使我們能夠看到漏洞之間的相關性。

圖3 合并出現在多個路徑中的同一節點

圖4 將節點分組并簡化圖表視圖

圖5 最終圖表視圖簡化結果
此外,快速瀏覽一下圖表視圖,可以使我們深入了解某個漏洞對其余代碼的影響。這種關系實在是太復雜了,無法通過代碼審查來理解。
(3)蝴蝶效應:考慮修復方案
如果您將代碼固定在某個位置怎么辦?這將如何影響代碼?在另一個地方怎么樣?如果有了圖表視圖,我們就可以考慮所有這些情況,快速查看整體效果,并自行決定采取哪種路線。
讓我們再次看一下原始示例的簡化視圖(又稱“homeograph”)。箭頭所指的單個節點的修復導致修復了兩個單獨的路徑。如圖6所示。
另一方面,圖7顯示了如果我們嘗試修復其他節點會發生什么。在這種情況下,箭頭所指的節點只會導致路徑的部分固定,原因是該代碼的底部“分支”也受到尚未修復的其他節點的影響。

圖6 單個節點的修復情況

圖7 修復其他節點的情況

圖8 理想情況下的“最佳固定”位置
我們可以繼續與圖進行交互,并考慮不同的“假設”場景。它們不僅會向我們展示修復特定漏洞的連鎖反應,而且會在一段時間后養成這種習慣,我們會在不知不覺中了解某些漏洞的影響,并且始終會開始認識到我們自己的“最佳修復位置”。
(4)這是最好的:優化漏洞修復
在理想情況下,我們還希望能夠準確、自動地找出圖中的“最佳固定”位置。如圖8所示。
這要求采用圖表圖形論概念,特別是“最大流最小剪切”定理可幫助我們計算固定最大流量的最小節點更新量。將此計算應用于示例圖,我們就可以直觀地找到3個節點,這些節點如果固定就可以糾正整個流程圖。
考慮到我們從相當于70個節點的14路徑圖開始,是不是讓您感覺這真是太神奇了?
對于開發人員和安全專業人員而言,圖表視圖流是一種視覺上吸引人的一種非常好的方式,它可以完全理解代碼中不同部分之間的關系,以及受污染的代碼段向其接收器的傳播。
代碼的可視化提供了一個人機交互式的工具,它使開發人員可以主動考慮在不同位置修復各種漏洞的影響。最重要的是,圖表視圖流可以使我們能夠快速、有效和準確地找到最佳定位位置。