檢查 Debian 或 Ubuntu 伺服器的已知 CVE
使用 debsecan 與 debvulns 比對 Debian 或 Ubuntu VPS 的套件版本,列出所有已知 CVE,並只針對值得重新開機的漏洞發出提醒。
目前有哪些已知 CVE 會影響此伺服器
若要確認目前有哪些已知 CVE 會影響伺服器,請將已安裝套件的版本與已發布的漏洞資訊源進行比對。CVE(common vulnerabilities and exposures)是已知安全性漏洞所使用的公開識別碼制度。在 Debian 上,這項比對可使用 debsecan 或 debvulns。在 Ubuntu 上則使用 pro cves,因為 Ubuntu 維護自己的追蹤器,而 Debian 工具會讀取錯誤的追蹤器。
套用更新與確認目前暴露的風險是兩項不同的工作。apt upgrade 只能回答一個問題:是否有較新的套件可用。它不會告訴你這台機器有哪些 CVE 尚未修復,也不會告訴你其中哪些 CVE 在目前的版本中永遠不會獲得修復。第二項工作需要使用掃描器,而使用掃描器前,必須確切了解它比對的內容。
套件掃描器實際比較的內容
其運作機制很簡單。掃描器會從 dpkg 資料庫讀取已安裝套件清單。接著將每個 binary package 對應回其建置來源的 source package,因為漏洞資料是以 source package 為記錄單位。掃描器會下載一份 feed,內容列出每個 CVE 與 source package 在各個 suite 中修正問題的版本。然後,掃描器會使用與 dpkg --compare-versions 相同的版本排序方式,比較目前已安裝的版本與修正版本。
Debian 或 Ubuntu 上的 CVE 掃描器,本質上是將版本與快取的 feed 進行比較。除此之外,沒有更多,也沒有更少。
人們常略過 binary-to-source 對應,但這會導致遺漏漏洞。openssl source package 在 Debian 13 與 Ubuntu 24.04 會建置出名為 libssl3t64 的 binary package。針對 openssl 提出的 CVE,不會符合直接搜尋 binary package 名稱的結果。因此 debvulns 會要求 python3-apt:APT 快取包含這項對應資訊;若缺少該資訊,工具會退回使用 dpkg-query,可能遺漏 source name 與 binary name 不同的問題。
feed 也會針對每個版本提供狀態,而不是單純的是或否。開啟某個 source package 的 tracker 頁面,例如 Debian security tracker 中的 openssl 項目,每個版本欄位會包含 vulnerable、fixed、no DSA 或 postponed 其中之一。no DSA 表示 security team 已檢視該問題,並判定不需要針對 stable 發布更新,因此該修正不會進入你的版本。只要該版本仍受支援,掃描器每次執行都會回報這個 CVE,無論執行多少次 apt upgrade 都無法清除它。這是人們放棄使用這些工具最常見的原因,而不是工具本身的錯誤。
使用 debsecan 掃描 Debian 伺服器
debsecan 位於 Debian 套件庫中,不需要額外的套件庫。
sudo apt update && sudo apt install -y debsecan
debsecan --suite trixie每一行輸出代表一個已安裝二進位套件涉及的一個 CVE:
CVE-2016-2776 bind9-host (remotely exploitable, high urgency)
CVE-2016-8864 libdns-export100 (fixed, remotely exploitable, medium urgency)嚴重性與 remotely exploitable 標記直接來自 Debian tracker。fixed 表示套件庫中已有修正版本,因此今天升級即可清除該行。沒有 fixed 的項目則無法關閉。
請傳入 --suite,否則約有一半的輸出會不正確。debsecan 只使用套件套件組來判斷是否已有修正套件,以及套件是否已過時。套件套件組設定錯誤時,CVE 清單仍然正確,但 fixed 標記與過時套件警告會不正確。請使用實際執行版本的代號:Debian 13 使用 trixie,Debian 12 使用 bookworm。
以下兩種檢視方式適合放入腳本:
debsecan --suite trixie --only-fixed --format packages
debsecan --suite trixie --only-fixed --format detail--format packages 只輸出二進位套件名稱,每行一個。這就是可以直接處理的清單。--format detail 會輸出該問題在資料來源中包含的所有內容。--only-fixed 會排除上述的 no DSA 項目,讓輸出縮減為尚待處理的工作。
若要排程執行,請編輯 /etc/default/debsecan,並設定 SUITE、MAILTO 與 REPORT。該套件提供 debsecan-create-cron,會建立一個每小時執行、但在隨機分鐘觸發的 cron 項目。每小時執行的項目不代表每小時都掃描:debsecan --cron 會檢查資料今天是否已下載;若已下載便結束。使用隨機分鐘是為了避免所有 Debian 機器在同一秒存取 tracker。
為何 debsecan 在 Ubuntu 上會回報錯誤資訊
debsecan 位於 Ubuntu 的 universe 儲存庫中(24.04 版為 0.4.20.1)。它能正常安裝,也會輸出看似可信、但不應直接採信的結果。它使用 Debian security tracker 作為資料來源,而該追蹤器不追蹤 Ubuntu。Ubuntu 專屬的問題不會出現在其中。Ubuntu 的版本字串(例如 3.0.13-0ubuntu3.4)通常無法符合 Debian 的修正版本,debsecan 也會將無法辨識的版本與 Debian unstable 比較。結果是:對 Canonical 數月前已修補的問題發出警報,對實際存在的問題卻不發出警報。Launchpad bug #95925 自 2007 年起便記錄了這項問題。
過去曾有一個轉接方案。ust2dsa 專案會將 Ubuntu CVE tracker 的資料轉換為 debsecan 格式,並每六小時重新發布一次。該專案已於 2021 年 10 月封存。現在若將 --source 指向該來源,取得的資料來源已停止更新五年;這比完全沒有掃描器更糟,因為過時的資料來源會回報系統沒有問題。
列出 Ubuntu 伺服器上的 CVE:使用 pro cves
Ubuntu 將相關資訊提供在 ubuntu-pro-client 中。Version 35 新增了 pro cves,可列出受已知 CVE 影響的已安裝套件。
pro cves
pro cves --fixable
pro cves --unfixablePackage Priority Origin Vulnerability
firefox medium esm-infra CVE-2020-6852
openssh low standard CVE-2021-3188
vim critical esm-infra CVE-2011-3374
vim-tiny high - CVE-2011-3380先查看 Origin 欄位,因為它決定你可以採取的處置。standard 表示修正已包含在一般 Ubuntu security pocket 中,執行一般升級即可安裝。esm-infra 或 esm-apps 表示修正只存在於 Expanded Security Maintenance 中,必須將 Ubuntu Pro 訂閱附加至該機器。- 表示目前尚無任何修正,而該列相當於 Debian 的 no DSA。
針對單一 CVE,以下兩個命令可提供完整資訊:
pro cve CVE-2024-5480
pro fix --dry-run CVE-2020-25686pro fix --dry-run 不會變更任何內容,並會準確顯示目前狀態:
CVE-2020-25686: Dnsmasq vulnerabilities
- https://ubuntu.com/security/CVE-2020-25686
1 affected package is installed: dnsmasq
(1/1) dnsmasq:
A fix is available in Ubuntu standard updates.
{ apt update && apt install --only-upgrade -y dnsmasq }
✔ CVE-2020-25686 is resolved.未受影響的機器會改為輸出 No affected source packages are installed.。沒有可用修正的機器會輸出類似 ✘ CVE-2017-9233 is not resolved. 的列。移除 --dry-run 後,同一個命令就會執行升級。pro security-status 是搭配使用的檢視方式:它會依 repository 統計已安裝套件,並回報待處理的 security updates 數量。這很重要,因為 Main 和 Universe 的支援承諾不同。
安裝 debvulns 並鎖定版本
debvulns 是以 Debian security tracker 為基礎建立的 Python 工具組。它提供命令列掃描器,以及使用相同資料的 Prometheus exporter。截至 2026 年 8 月,目前版本為 0.2.2。
在 Debian 12 或更新版本上執行 pip install debvulns 會失敗並顯示 error: externally-managed-environment,因為系統 Python 由 dpkg 管理。請安裝到仍可存取系統 python3-apt 的虛擬環境中:
sudo apt update && sudo apt install -y python3-venv python3-apt
sudo python3 -m venv --system-site-packages /opt/debvulns
sudo /opt/debvulns/bin/pip install debvulns==0.2.2
/opt/debvulns/bin/debvulns --severity high --format json | head -40--system-site-packages 是關鍵旗標。沒有這個旗標,虛擬環境就無法匯入 python3-apt,debvulns 會改用 dpkg-query,而且不會顯示錯誤訊息,導致失去 binary 對應 source 的資訊。也請鎖定版本。如果掃描器的行為會在兩個星期二之間改變,就無法與上週的掃描結果比較。
以下是會使用的旗標:
--severity接受critical、high、medium、low或negligible,並篩選輸出。--format接受json或csv。預設值為 JSON。--sort-by接受package或cve。--suite覆寫自動偵測到的 Debian codename。--no-cache略過快取的 feed,並下載新的 feed。-v將工具的執行狀態記錄到 stderr,包括它擷取的 URL。
debvulns 也會下載 EPSS(exploit prediction scoring system)分數,並為每個發現附加一個分數。EPSS 是每天發布的估計值,用來表示某個 CVE 在接下來三十天內遭到利用的機率。相較於 CVSS(common vulnerability scoring system)base score,EPSS 是很有用的另一項參考。CVSS 說明漏洞遭利用時可能造成的嚴重程度,而 EPSS 說明有人實際利用該漏洞的可能性。
與 debsecan 相同,這裡也適用同一項警告。這個 feed 來自 Debian,因此請在 Debian 上執行 debvulns。在 Ubuntu 上,pro cves 才是與你的 archive 相符的工具。
將 CVE 數量匯出至 Prometheus
如果你已經在執行監控,exporter 會將這項資訊轉成可設定告警的數值,而不是一份沒有人會開啟的報告。
sudo useradd --system --no-create-home --shell /usr/sbin/nologin debvulns寫入 /etc/systemd/system/debvulns-exporter.service:
[Unit]
Description=debvulns Prometheus exporter
Wants=network-online.target
After=network-online.target
[Service]
Type=simple
User=debvulns
ExecStart=/opt/debvulns/bin/debvulns-exporter --port 9222 --refresh-interval 21600 --cache-dir /var/cache/debvulns-exporter
CacheDirectory=debvulns-exporter
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
Restart=on-failure
RestartSec=30
[Install]
WantedBy=multi-user.targetsudo systemctl daemon-reload
sudo systemctl enable --now debvulns-exporter
curl -s localhost:9222/-/ready
curl -s localhost:9222/metrics | grep -c debvulns_CacheDirectory=debvulns-exporter 是讓 ProtectSystem=strict 可正常運作的關鍵:systemd 會建立由服務使用者擁有的 /var/cache/debvulns-exporter,而這是該程序唯一可寫入的路徑。第一次掃描完成前,/metrics 會回傳 HTTP 503;完成後,/-/ready 才會回傳 200。這可避免 exporter 發布尚未實際測量的 0。程序存活後,/-/healthy 立即回傳 200,因此請使用該項目檢查 liveness,並使用 /-/ready 檢查 scrape readiness。
值得用來建立規則的 metrics:
debvulns_vulnerabilities_total是依嚴重性、是否有可用修補程式,以及問題是否可從遠端連線標記的彙總數量。debvulns_vulnerability_info會為每個 CVE 與套件建立一個 series,並以 CVE id 作為 label。debvulns_vulnerability_epss_score是每個 CVE 的 EPSS 機率。debvulns_scan_status在上次掃描成功時為 1,失敗時為 0。debvulns_last_scan_timestamp_seconds記錄該次掃描的執行時間。
建立規則前,請先從你自己的主機讀取確切的 label 值。因為沒有匹配任何項目的 selector 永遠不會觸發,看起來會與狀態正常的伺服器完全相同:
curl -s localhost:9222/metrics | grep '^debvulns_vulnerabilities_total'接著建立兩個規則:
groups:
- name: debvulns
rules:
- alert: FixableCriticalCVE
expr: sum by (instance) (debvulns_vulnerabilities_total{severity="critical", fix_available="true"}) > 0
for: 6h
annotations:
summary: "A critical CVE with an available fix has stayed open for six hours"
- alert: CVEScanStale
expr: time() - debvulns_last_scan_timestamp_seconds > 172800
for: 30m
annotations:
summary: "CVE data on this host is more than two days old"for: 6h 子句是維持第一個告警可信度的關鍵。若沒有這項條件,你會因為某個 CVE 而收到通知,但自動升級作業可能在 20 分鐘後就已經修正它。告警在你讀完前自行恢復,會讓你下次忽略其他告警。加入這項條件後,你只會收到仍未被自動修補的問題。
第二個規則常被遺漏。停止掃描的 scanner 會回報 0 個漏洞,而在儀表板上,0 看起來與狀態正常完全相同。除了監控資料內容,也要根據資料的存在時間建立告警。
套件掃描器無法看見的內容
這項界線比多數人預期的更明確。這些工具會將已安裝的套件版本與漏洞資訊來源比對,而它們取得的所有資訊都來自 dpkg 資料庫。任何不是透過套件管理器安裝的內容,掃描器都無法看見。
這包括:
- Docker image 內的所有內容。掃描器只能看見主機上的
docker.io套件,不知道容器內的 userland、直譯器或函式庫。 - 所有
pip、npm、cargo與go相依套件,包括 image 在建置時下載的相依套件。 - 靜態二進位檔,以及從 tarball 或
curl ... | sh行安裝的任何內容,因為這些內容完全沒有套件中繼資料。 - 你自行編譯的軟體,即使其版本與發行版套件相同。
針對 image,應在建置位置使用 image scanner 掃描,而不是在主機上掃描。至於語言套件相依性,其風險模型本來就不同:常見問題是套件遭劫持或含有惡意內容,而不是使用具有已知 CVE 的舊版本。伺服器上的 npm 供應鏈攻擊涵蓋了問題的這一半,而這並不是 debsecan 原本能夠偵測的部分。
你的答案新鮮度取決於快取的 feed
這裡的每個工具都會使用快取。debvulns 能下載時會將資料寫入 /var/cache/debvulns,無法下載時則改用 ~/.cache/debvulns;只有在快取超過 24 小時後,才會重新下載。debsecan --cron 每個日曆日只下載一次。exporter 預設每 24 小時重新整理一次,且拒絕低於 3600 秒的值。
因此,答案可能已經過時一天;網路故障時,工具會提供舊答案,而不是回報錯誤。調查特定問題時,請強制重新讀取:
/opt/debvulns/bin/debvulns --no-cache --severity critical
ls -l --time-style=long-iso /var/cache/debvulns上述 CVEScanStale 規則會在所有主機上替你完成這項設定。這是「沒有重大 CVE」與「自星期四起就沒有資料」之間的差異。兩者在圖表上看起來相同,但實際情況完全不同。
CVE 何時足以要求重新開機
磁碟上的套件已修正,不代表記憶體中的程序也已修正。apt upgrade 會替換檔案,但長時間執行的程序仍會使用啟動時對應的檔案副本。needrestart 可找出這些程序。
sudo apt install -y needrestart
sudo needrestart -r l
sudo needrestart -b -k-r l 會列出需要重新啟動的項目,但不會執行任何變更。-b 是批次模式,會輸出可供機器讀取的行,而不是顯示對話框:
NEEDRESTART-KCUR: 6.12.48-amd64
NEEDRESTART-KEXP: 6.12.57-amd64
NEEDRESTART-KSTA: 3KCUR 是目前正在執行的 kernel。KEXP 是磁碟上已安裝的最新 kernel。兩者不同時,KSTA 會回報 3,表示需要重新開機。若希望擷取指標而不是剖析輸出,needrestart -o 會以 OpenMetrics 格式輸出相同資訊。
Ubuntu 也會在套件的 post-installation script 判定需要重新開機時建立 /var/run/reboot-required,並在 /var/run/reboot-required.pkgs 中列出負責的套件。該路徑位於 tmpfs,因此設計上會在每次開機時消失。pro system reboot-required 會以一個單字回答相同問題;如果 livepatch 已套用至執行中的 kernel,也會另外回報。Debian 預設不會建立這個檔案。請安裝 reboot-notifier(Debian 13 中的版本為 0.12)以取得相容的等效功能,或使用 needrestart;它在兩個發行版上的行為相同。
請依下列順序套用判斷規則:
- CVE 位於 shared library,已安裝修正套件,而
needrestart -r l顯示仍在使用舊副本的服務。重新啟動這些服務。不需要重新開機。 - CVE 位於 kernel,且
KCUR與KEXP不同。只有重新開機才能替換執行中的 kernel;但若使用 VPS 上的 live kernel patching,則可套用其中能在執行中系統修正的 kernel 更新。 - 目前的 release 沒有 CVE 修正程式。Debian 會顯示為
no DSA,Ubuntu 則會顯示為-的Origin。重新開機不會改變任何結果。請記錄暴露狀態,或關閉受影響的功能以降低風險。 - scanner 列出該 CVE,但沒有任何可連線的服務使用該套件。請在一般修補週期中處理。若某個 library 只有本機的
man命令會連結使用,其中的漏洞不構成事件。
能持續一個月低活動期的執行節奏
選擇一種半年後仍會持續執行的節奏,因為這項工作的價值完全取決於是否反覆執行。
每天以無人介入的方式執行掃描。在 Debian 上,這可以使用已設定 REPORT 的 debsecan cron 項目,或使用匯出器本身的重新整理迴圈。讓 無人介入升級自行依排程安裝安全性修補,使掃描器的工作是回報自動化機制未能修補的問題,而不是成為唯一的防禦措施。
針對單一數值發出警示,不要針對整份報告發出警示。可修正且嚴重性為 critical、持續 6 小時的問題,是大多數單一伺服器每年會遇到幾次的門檻。這種情況並不常見,因此警示送達時,你確實會閱讀內容。其他所有問題都應放在儀表板上,並於 每月伺服器維護作業期間檢視。
在需要之前先記錄重新開機規則,因為你可能會在不便的時段套用這些規則。核心的 CVE 若具有不同的 KEXP,表示需要排程重新開機。函式庫的 CVE 則表示重新啟動 needrestart 所列出的服務。若沒有可用的修補程式,請記錄問題,並於下個月再次檢查。
每季重新檢視一次排除項目。位於 dpkg 管理範圍外的項目只會增加:有人新增的容器、放入 /usr/local/bin 的二進位檔。每個項目都代表掃描器因無法查看而回報正常的範圍。在伺服器群組中,請將這份清單與用於管理多部 Linux 伺服器的工具或文件放在一起,讓不只一人能看見這些例外。
FAQ
如何列出影響 Debian 伺服器的 CVE?
安裝 debsecan,並使用實際執行版本的代號來執行 debsecan --suite trixie。每一行輸出會列出一個 CVE 與一個已安裝的 binary package;括號中的 fixed 表示套件庫中已有修正版。加入 --only-fixed --format packages,即可將輸出縮減為目前可升級的套件名稱。若要取得 JSON 輸出與 EPSS 分數,請在使用 --system-site-packages 建立的虛擬環境中安裝 debvulns,讓它能匯入 python3-apt。
為什麼掃描器持續回報 apt 無法修復的 CVE?
因為 Debian security team 已將該問題標記為 no DSA,表示他們判定問題影響太小,不會納入 stable 更新,因此不會提供修正版套件。Ubuntu 的對應結果,是在 pro cves 輸出中將 - 標示為 Origin。該 CVE 確實仍在你的系統上開放,掃描器持續列出它是正確的。使用 debsecan --only-fixed 或 pro cves --fixable,只查看目前可以處理的項目,並在例行維護時檢查其餘項目。
CVE 掃描器能看到 Docker 容器內的漏洞嗎?
不能。這些工具只讀取主機的 dpkg 資料庫,因此只能看到 docker.io 套件,不知道映像檔內的作業系統或程式庫。相同的盲點也涵蓋所有 pip 或 npm 相依套件,以及從 tarball 安裝的任何內容。請在建置容器映像檔的環境中使用映像檔掃描器進行掃描,並將語言相依套件視為另一個問題,因為其故障模式不同。
CVE 何時才需要重新開機?
只有修正內容位於 kernel 中時才需要。執行 sudo needrestart -b -k,並比較執行中的 kernel NEEDRESTART-KCUR 與已安裝的最新 kernel NEEDRESTART-KEXP。如果兩者不同,NEEDRESTART-KSTA 會回報 3,表示等待重新開機。若 CVE 位於 shared library,修正版檔案已存在於磁碟中,只需重新啟動仍在使用舊檔案副本的程序;sudo needrestart -r l 會列出這些程序。
可以在 Ubuntu 伺服器上執行 debsecan 嗎?
它會從 universe 安裝,但回報結果不正確。debsecan 讀取 Debian security tracker,而該追蹤器不追蹤 Ubuntu 問題,也不辨識 3.0.13-0ubuntu3.4 等 Ubuntu 版本字串。因此,它會針對 Canonical 很久以前已修補的問題產生誤報,卻不會回報僅存在於 Ubuntu 的問題。曾經將 Ubuntu 資料轉換為 debsecan 格式的 ust2dsa bridge 已於 October 2021 封存,其資料來源也不再更新。請在 Ubuntu 上使用 pro cves。