SSD Nodes Learn Hosting plans →
指南 Matt Connor作者: Matt Connor · 已更新 2026-09-14

檢查 Debian 或 Ubuntu 伺服器的已知 CVE

使用 debsecan 與 debvulns 比對 Debian 或 Ubuntu VPS 的套件版本,列出所有已知 CVE,並只針對值得重新開機的漏洞發出提醒。

目前有哪些已知 CVE 會影響此伺服器

若要確認目前有哪些已知 CVE 會影響伺服器,請將已安裝套件的版本與已發布的漏洞資訊源進行比對。CVE(common vulnerabilities and exposures)是已知安全性漏洞所使用的公開識別碼制度。在 Debian 上,這項比對可使用 debsecandebvulns。在 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 項目,每個版本欄位會包含 vulnerablefixedno DSApostponed 其中之一。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,並設定 SUITEMAILTOREPORT。該套件提供 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 --unfixable
Package         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-infraesm-apps 表示修正只存在於 Expanded Security Maintenance 中,必須將 Ubuntu Pro 訂閱附加至該機器。- 表示目前尚無任何修正,而該列相當於 Debian 的 no DSA

針對單一 CVE,以下兩個命令可提供完整資訊:

pro cve CVE-2024-5480
pro fix --dry-run CVE-2020-25686

pro 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 接受 criticalhighmediumlownegligible,並篩選輸出。
  • --format 接受 jsoncsv。預設值為 JSON。
  • --sort-by 接受 packagecve
  • --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.target
sudo 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、直譯器或函式庫。
  • 所有 pipnpmcargogo 相依套件,包括 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: 3

KCUR 是目前正在執行的 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;它在兩個發行版上的行為相同。

請依下列順序套用判斷規則:

  1. CVE 位於 shared library,已安裝修正套件,而 needrestart -r l 顯示仍在使用舊副本的服務。重新啟動這些服務。不需要重新開機。
  2. CVE 位於 kernel,且 KCURKEXP 不同。只有重新開機才能替換執行中的 kernel;但若使用 VPS 上的 live kernel patching,則可套用其中能在執行中系統修正的 kernel 更新。
  3. 目前的 release 沒有 CVE 修正程式。Debian 會顯示為 no DSA,Ubuntu 則會顯示為 -Origin。重新開機不會改變任何結果。請記錄暴露狀態,或關閉受影響的功能以降低風險。
  4. scanner 列出該 CVE,但沒有任何可連線的服務使用該套件。請在一般修補週期中處理。若某個 library 只有本機的 man 命令會連結使用,其中的漏洞不構成事件。

能持續一個月低活動期的執行節奏

選擇一種半年後仍會持續執行的節奏,因為這項工作的價值完全取決於是否反覆執行。

每天以無人介入的方式執行掃描。在 Debian 上,這可以使用已設定 REPORTdebsecan 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-fixedpro 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

#cve#debian#ubuntu#vulnerability-scanning#monitoring#security