前言
有這樣一個工具, 可以對鏡像進行掃描, 拿出其中包含的軟件包、lib庫(pip包等)、危險文件等, 並能夠識別出哪些包是存在漏洞的. 比如trivy
工具. 那麼他們是如何做到這件事情的呢?
正好最近在研究這塊, 索性就簡單談一談(其實原理很簡單).
獲取包含內容
對於鏡像的存儲, 層之間的關係, 以及如何將多層數據進行聚合, 可以看之前的這篇文章.
掃描單層軟件包
掃描單層的數據, 說白了就是文件掃描. 比如:
- 獲取系統版本
- 從
etc/os-release
文件獲取系統版本 - 從
etc/debian_version
文件獲取debian
的版本 - 從
etc/lsb-release
文件獲取ubuntu
版本 - 從
etc/alpine-release
文件獲取alpine
的版本
- 從
- 獲取系統包
- 從
lib/apk/db/installed
文件獲取安裝的所有apk
包 - 從
var/lib/dpkg/status
文件獲取安裝的所有dpkg
包
- 從
- 獲取依賴庫
- 依據
.jar
後綴拿到所有jar
包 - 依據
go.mod
文件名獲取依賴的庫 - 從
requirements.txt
文件拿到依賴的pip
庫
- 依據
- 獲取風險文件
- 通過一些文件識別的掃描庫, 可實現對惡意文件的識別. 比如yara
通過對本層所有文件的掃描, 就能夠將當前層包含的信息全部拿到了.
多層合併
在拿到每一層的數據之後, 接下來就是將多層的數據進行聚合了. 軟件包的聚合規則與文件的聚合規則相同. 可以回這篇文章複習一下文件是如何聚合的.
- 覆蓋: 對於單文件內容, 上層覆蓋下層, 比如:
- 系統包.
apk/dpkg
等, 在信息修改後, 其對應的單位件會覆蓋
- 系統包.
- 合併: 將多層內容進行合併. 比如:
jar
文件, 每層增加一個, 在最後將所有jar
包合併到一起
- 移除: 之前說過, 當文件刪除的時候, 會保留一個
without
文件. 因此, 當上層將下層內容刪除時, 需要在最終聚合的時候去掉.
經過以上步驟, 整個鏡像的完整信息就已經拿到了.
識別漏洞
如何識別漏洞呢? 就更簡單了, 在本地數據庫中維護一份漏洞庫, 標識了某個系統的某個軟件的某個版本, 存在某個漏洞. 然後拿着匹配到的結果一個一個找就行了.
總結
以上, 就是鏡像的靜態掃描原理了. 看完之後是不是發現特別的簡單?
但其實寫起來並沒有想象中那麼簡單, 比如合併的操作就比較繁瑣. 不過這裏只介紹原理, 知道是怎麼回事就行了.
還有一些掃描是動態掃描, 會將鏡像啓動, 然後通過攻擊行爲來判斷是否存在某種漏洞. 不在本文的說明範圍內.