VPS 被駭客入侵怎麼辦?正確處理步驟
VPS 遭入侵後不要清理主機。先在供應商 firewall 隔離,建立 disk snapshot 保存證據,輪替所有 key,再以乾淨 image 重新建置。
不要清理遭入侵的 VPS
如果 VPS 遭到入侵,最重要的決定是在執行任何命令之前做出。不要嘗試清理該機器。先在供應商端將其隔離,建立磁碟快照作為證據,輪替該機器持有的所有憑證,然後使用信任來源在全新的伺服器上重新建置。
你無法證明 rootkit 已經移除,因為能夠證明這件事的工具,正是攻擊者所控制的工具。
這就是完整的理由。以下說明背後的機制。取得 root 權限的攻擊者可以替換 ps,讓某個 process ID 永遠不出現在其輸出中。/etc/ld.so.preload 中的一行設定即可將攻擊者的程式碼載入該主機上的每個動態連結程式,因此 ls、ss 和 find 都會以一致的方式回報錯誤。可載入的 kernel module 能在 system call 層級以下隱藏檔案,因此即使重新下載 binary,也會看到乾淨的磁碟。你刪除 miner,CPU 圖表下降,伺服器也停止顯示異常活動。但安靜同樣可能是運作中的 backdoor 狀態。
重新建置的成本通常沒有感覺中那麼高。典型的 VPS 只有少量套件、一個設定目錄和一組資料,因此重新建置是有明確終點的有限工作。追查攻擊者所做的每項變更則沒有明確範圍,也永遠無法達到證明已清除的程度。
確認確實遭到入侵
許多被回報為遭到駭客入侵的伺服器其實並沒有。每天數千次失敗的 SSH 登入通常只是網際網路背景雜訊,因為每個公開 IPv4 位址都會持續遭到掃描。lastb 輸出中充滿 root 和 admin 嘗試,表示掃描器找到了你的連接埠,但不代表有人已成功登入。
以下訊號確實表示有問題:
- 你無法說明來源的成功登入,例如
Accepted password for root from 203.0.113.7。 authorized_keys中出現你未加入的金鑰。- 主機代管商通知你,伺服器正在對外發送異常網路流量。
- CPU 使用率達到 100% 的程序,其名稱仿自 kernel thread。透過暴露的 Redis 和 Docker socket 植入的礦工,常見名稱包括
kdevtmpfsi和kinsing。 - 對任何服務都未使用的位址建立對外連線。
仿冒 kernel thread 有一個快速檢查方法。真正的 kernel thread 會在方括號內顯示名稱,且沒有對應的可執行檔,因此 sudo ls -l /proc/<pid>/exe 對它們會以 No such file or directory 失敗。如果顯示為 [kworker/0:2] 的程序,其 exe link 指向 /tmp 下的某個項目,則它是一般使用者程序,只是套用了 kernel 名稱。
執行這些檢查時,請假設該伺服器可能會向你隱瞞資訊。這些檢查足以判定系統有異常,但不足以判定系統完全沒有問題。
在供應商端切斷網路,不要從主機內部操作
隔離必須優先處理,因為只要攻擊者仍持有 shell,後續所有步驟都會失去意義。攻擊者仍在線監看時,讀取日誌、輪換金鑰與還原資料都沒有用。
請在供應商控制台中操作,使用作業系統外部的網路防火牆。拒絕輸入與輸出流量,並保留 web console 作為登入方式。由供應商端強制套用的規則,不會受磁碟內發生的任何變更影響。
不要從伺服器內部執行這項操作,原因有二。你在遭入侵的 kernel 內設定的防火牆,仍由該 kernel 強制執行,而 root 清除 nftables 規則的難度和你寫入規則一樣低。此外,透過 SSH 執行 sudo ip link set enp1s0 down 會先中斷你自己的工作階段,讓你無法再登入正在檢查的機器。
輸出與輸入流量都必須封鎖。reverse shell 會從你的主機向攻擊者撥出連線,因此只封鎖輸入流量,仍會讓現有連線正常運作。如果供應商只提供輸入規則,剩下的選項就是卸離網路介面,或關閉 instance。
現在不要重新開機。先確認 /var/log/journal 是否存在。如果該目錄不存在,journald 會將資料寫入 /run/log/journal;該位置位於記憶體中,因此重新開機會刪除入侵記錄。執行中的程序也會在重新開機時消失,而其 command line 通常是你能取得的最清楚證據。
在進行任何操作前建立磁碟 snapshot
這裡的 snapshot 和 backup 用途不同。現在建立的 snapshot 是遭入侵磁碟的副本:它是你的證據,也是唯一能在不慎覆寫資料後讓你回復的方式。較早建立的 backup 才是復原途徑。如果供應商的控制面板對這兩個詞的用法不嚴謹,請先閱讀VPS snapshot 與真正 backup 的差異,因為保留規則和還原行為並不相同。
再次登入前,先從供應商的控制面板建立 snapshot。執行中的 snapshot 具備當機一致性:它擷取的是該瞬間的磁碟狀態,效果等同於直接拔除電源。這對保留證據已經足夠。請使用不易誤解的名稱,避免有人誤將它還原。像 COMPROMISED-do-not-restore-2026-08-12 這樣直接的名稱就很合適。調查完成且與主機商之間的任何 abuse ticket 都已結案前,請保留這個 snapshot。
SSH 無法使用時如何登入
有兩種方式,兩者都在供應商控制台中。Web 主控台(VNC 或 serial)會將主機連接到終端機,效果就像您直接接上鍵盤。即使 sshd 已停止、防火牆設定錯誤,或攻擊者變更了 SSH 埠號,仍可使用。它會以本機密碼進行驗證,因此僅允許金鑰驗證的主機,可能必須先重設 root 密碼,主控台才有用。
Rescue mode 是較佳選項。它會啟動一個小型 live system,並連接您的磁碟,但不會啟動磁碟上的系統。因此執行的指令可信賴:遭入侵的 kernel 與遭入侵的 binaries 都不會執行。請以唯讀模式掛載磁碟。
lsblk -f
sudo mkdir -p /mnt/victim
sudo mount -o ro /dev/vda1 /mnt/victim如果 lsblk 顯示的是 LVM(logical volume manager)volume,而不是一般 partition,請先執行 sudo vgchange -ay 啟用這些 volume,再掛載 /dev/mapper/ 下出現的 device。
請勿對已掛載的磁碟執行 chroot 以便查看內容。chroot 會以您的權限執行攻擊者的 binaries,這會完全失去啟動 rescue mode 的目的。
收集仍可信任的證據
在 rescue mode 中執行以下命令,並將磁碟以唯讀方式掛載到 /mnt/victim。先從登入紀錄開始,因為這些紀錄可協助判定入侵時間。確定時間範圍後,其他工作會更容易進行。
sudo grep -aE 'Accepted (password|publickey)' /mnt/victim/var/log/auth.log
sudo last -f /mnt/victim/var/log/wtmp
sudo lastb -f /mnt/victim/var/log/btmp
sudo journalctl -D /mnt/victim/var/log/journal -u ssh --since "2026-07-01"缺少 /var/log/auth.log 本身不代表可疑。部分目前的 Ubuntu 映像未安裝 rsyslog,因此 sshd 只會將日誌寫入 journal,這就是 journalctl -D 行所讀取的內容。值得注意的是,原本連續的日誌出現中斷,或日誌檔案被截斷為 0 位元組。清除日誌很常見,而且通常處理得很粗糙。
接著檢查帳號與金鑰。
sudo find /mnt/victim/root /mnt/victim/home -name 'authorized_keys*' -exec ls -l {} +
sudo awk -F: '$3 == 0 {print $1}' /mnt/victim/etc/passwd
sudo lsattr /mnt/victim/root/.ssh/authorized_keysawk 行會列出所有使用者 ID 為 0 的帳號。該輸出中若有 root 以外的內容,表示存在第二個 root 帳號。find 模式刻意也會比對 authorized_keys2,因為 OpenSSH 預設會讀取這兩個檔名,而第二個檔名很容易被忽略。若 lsattr 在屬性清單中輸出 i,表示該檔案具備 immutable 屬性:攻擊者會設定此旗標,讓你嘗試刪除其金鑰時因 Operation not permitted 而失敗,疲憊的管理員則會以為修改已生效。
持久化通常藏在少數幾個位置,因此請全部檢查。
sudo ls -lt /mnt/victim/etc/systemd/system
sudo ls -l /mnt/victim/etc/cron.d /mnt/victim/var/spool/cron/crontabs
sudo cat /mnt/victim/etc/ld.so.preload
sudo grep -rnE 'curl|wget|base64|/dev/tcp' /mnt/victim/etc/update-motd.d /mnt/victim/etc/rc.local /mnt/victim/root/.bashrc /mnt/victim/root/.profile在正常的 Ubuntu 或 Debian 系統中,/etc/ld.so.preload 不存在,因此 No such file or directory 是正常結果;只要有任何內容,都值得你注意。登入檔案若將 base64 -d 的輸出管線傳給 shell,也是同樣的情況:合法設定不需要隱藏自身內容。
請根據變更時間,而不是修改時間,建立時間線。
sudo find /mnt/victim -xdev -newerct '2026-08-01' -type f -printf '%TF %TT %p\n' | sorttouch 可將修改時間設定為攻擊者指定的任意值,因此 mtime 很容易被偽造。任何 inode 變更都會更新變更時間(ctime),而 touch 無法將其往回調整,因此 -newerct 能列出最近寫入的內容,結果較為可信。但這仍不是證明,因為 root 可以調整系統時鐘,或直接寫入 block device。
套件完整性值得執行一個命令,但要注意其限制。在執行中的系統上,sudo dpkg --verify 會為每個 checksum 不再相符的套件檔案列出一行,並在 checksum 欄位顯示 5;安裝 debsums 套件後,sudo debsums -ac 也會執行相同工作,並包含設定檔。請只按照一個方向解讀結果。變更的 /usr/sbin/sshd 是實際證據。乾淨的報告則無法證明任何事情,因為替換二進位檔的同一個 root 帳號,也能修改 /var/lib/dpkg/info/ 下的 checksum 清單。rkhunter 與 chkrootkit 等 rootkit 掃描器也遵循相同原則:掃描命中代表取得資訊,掃描結果乾淨不代表系統已排除風險。
在進行任何具破壞性的操作前,先將已收集的內容複製到機器外部。
sudo tar --ignore-failed-read -C /mnt/victim -czf /root/evidence-2026-08-12.tgz \
var/log etc root/.ssh root/.bash_history home
sha256sum /root/evidence-2026-08-12.tgz將該 hash 記錄在伺服器外部的位置。如果日後成為保險理賠或警方報案的一部分,能夠證明該封存檔自收集後未曾變更,便是證據與一個檔案資料夾之間的差異。調查期間不慎刪除內容很常見,而 snapshot 加上這份封存檔,能讓事件仍可處理。事後復原錯誤的 rm 遠比多數人預期的困難,復原以 rm -rf 刪除的檔案對此有說明。
找出入侵者進入的途徑
未關閉入口的重建作業,會讓伺服器再次遭到入侵,通常在數天內就會發生,因為第一次找到你的掃描作業不會停止。單一伺服器遭到入侵,大多可歸因於以下4種入口。
SSH 密碼登入。 來自不明位址的 Accepted password for root 行本身就是答案。請在 /etc/ssh/sshd_config 中,以及 /etc/ssh/sshd_config.d/ 下的每個檔案中檢查 PasswordAuthentication。sshd 會採用首次取得的關鍵字值;在 Ubuntu 上,Include 行位於主要檔案頂端,因此後續加入的設定檔會悄悄覆寫你在檔案下方修改的設定。
未設定驗證的公開服務。 例如使用6379的 Redis、使用2375的 Docker API,或繫結至 0.0.0.0 而非 127.0.0.1 的資料庫。Docker 最容易造成意外。發布容器連接埠時,會插入 DNAT(目的地網路位址轉譯)規則,而這些規則會在 ufw chain 之前套用。因此,ufw status 可能顯示連接埠已封鎖,但後方的容器仍會回應整個網際網路的請求。請在重建前了解這點:為什麼 Docker 公開的連接埠會繞過 ufw 說明規則順序與修正方法。
未修補的 Web 應用程式。 在 Web 伺服器存取日誌中,查看最早可疑時間戳記附近的內容,尋找對上傳路徑或管理路徑發出的 POST,然後尋找 Web 根目錄下變更時間相符的檔案。上傳目錄中出現未預期的 PHP 檔案,是最典型的結果。
外洩的憑證。 例如提交至儲存庫的金鑰、貼入聊天內容的權杖,或由設定錯誤的 Web 伺服器以靜態檔案提供的 .env 檔案。自動化作業很容易意外造成這類問題,因此應遵循不要將秘密存放在 AI 代理程式及其設定檔中的原則。
如果完成上述檢查後仍無法確認入口,請假設是憑證外洩,並將該機器持有的所有秘密視為已公開。
輪替機器可能存取的所有憑證
先切斷網路,再進行輪替。攻擊者仍保持連線時進行輪替,只會將新的 secret 交給攻擊者。
- 伺服器上儲存的所有 SSH 私密金鑰,以及其他信任相應公開金鑰的帳戶。
- 使用
ssh -A轉送至該主機的任何金鑰。Agent forwarding 會在/tmp下建立 socket。只要工作階段仍開啟,該機器上的 root 就能使用此 socket,在任何接受該金鑰的位置進行驗證。 .env檔案、systemdEnvironment=行、CI 設定及 provider credentials 中的 API tokens。- 資料庫密碼,以及使用這些密碼的應用程式帳戶。
- 伺服器持有的 TLS (transport layer security) 私密金鑰。重新簽發憑證,並撤銷舊憑證。
- hosting account 密碼,並啟用雙因素驗證。該控制面板可以重建、建立 snapshot,並透過 console 連入你擁有的每台伺服器,因此它才是真正的周界。
- 在該主機遭入侵期間,於 shell 工作階段中輸入的任何密碼,因為 root 可以即時記錄 terminal 工作階段。
如果該機器上的密碼也用於其他位置,請一併在那些位置變更。重複使用密碼,會讓一台遭入侵的 VPS 進一步導致電子郵件帳戶遭入侵。
重建檢查清單
- 使用全新的發行版映像檔建立新伺服器。不要使用遭入侵伺服器的 snapshot,也不要還原整個 root filesystem。
- 從發行版套件庫安裝套件。絕對不要從舊磁碟複製 binary。
- 只從早於時間軸中最早證據的備份還原資料,例如資料庫 dump、上傳檔案與應用程式狀態。留下
/etc、/usr與舊的 unit files,不要還原。 - 手動輸入輪替後的 secrets。不要複製舊的
.env。 - 在再次提供任何還原的網頁內容前,先檢查其中是否有檔案是在入侵期間新增的。
- 在對外公開前先完成強化:僅允許以 key 登入 SSH、使用非 root 工作帳號、對入站流量採 default-deny 的 firewall,且服務公開的範圍不得超過必要程度。依序完成 新 VPS 的前十分鐘、正確強化 SSH,再在 Ubuntu 24.04 上加入 fail2ban 以降低登入雜訊。為每項服務設定 專用的最小權限帳號,避免下一個 foothold 直接取得 root 權限。
- 關閉舊伺服器,並保留其 snapshot,直到調查及任何 abuse ticket 都結案。
- 修正備份。如果第 3 步只能靠猜測,真正的教訓是備份歷程太短,無法回溯到入侵之前。具備長期保留功能的版本化 off-server backups,才能在下次提供乾淨的還原點:VPS 上的 restic backups 可同時滿足這兩項需求。
如果無法確定入侵日期,就無法選擇安全的備份。此時只能還原可人工檢查的資料,例如可讀取的 SQL dump,或可列出內容的圖片目錄。所有可執行內容都應視為可疑,並從套件庫重新安裝。
主機商發出的 abuse 通知代表什麼
大多數人是從服務供應商,而不是自己的監控系統得知伺服器已遭入侵。主機商會看到對外流量,例如針對其他網路的 SSH 暴力破解、port 25 上的垃圾郵件,或伺服器參與反射式攻擊。工單通常會附上時間戳記、連接埠、部分流量樣本,以及以小時為單位計算的處理期限。
請回覆工單,即使只能說明伺服器已隔離,並且正在重建。工單沒有回覆時,供應商可能會對伺服器設定 null route 或暫停服務,讓資安事件進一步演變成服務中斷。接著要求對方提供報告所依據的原始日誌行。這些時間戳記是在你的機器之外記錄的,因此是攻擊者無法修改的時間軸資訊;相較於磁碟上的任何資料,它們通常更能準確判定入侵時間。
對主機商而言,處理遭入侵的客戶伺服器是例行工作,不會因為你妥善處理事件而對你留下負面紀錄。至於 VPS 託管是否安全,主要取決於客戶如何設定環境,而這正是你現在需要從頭重新處理的部分。
何時應聯絡專業人員
- 伺服器儲存了其他人的個人資料。根據 GDPR (General Data Protection Regulation),個人資料外洩事件必須在無不當延誤的情況下通報監管機關;在可行的情況下,應於知悉事件後 72 小時內完成通報。判斷通報時限是否已開始起算屬於法律工作,不是系統管理工作。
- 處理範圍包含支付卡資料。卡片組織要求由核准的鑑識調查人員進行調查,而自行操作可能損害案件證據。
- 收到勒索要求,或資料已遭加密。
- 該主機可以連線到其他主機,例如內部網路、hypervisor,或持有 production 憑證的 CI runner。在證明並非如此之前,同一群組中有一台主機遭入侵,就應視為整個群組的事件。
- 證據必須能供保險公司或執法機關採信。完成 snapshot 後停止操作,建立完整磁碟映像,並記錄由誰在何時處理該映像。
如果是單一 VPS,僅執行你自己的服務,且其中沒有其他人的資料,上述處理流程就是完整工作內容。在 provider 端隔離主機。建立 snapshot 作為證據。收集目前仍可相信的資料。輪替所有項目。重新建立乾淨的環境。
FAQ
我可以清理遭入侵的 VPS,而不重新建置嗎?
無法有把握地這麼做,因為這等於要求遭入侵的系統自行回報狀況。遭替換的 ps 可隱藏程序,/etc/ld.so.preload 中的一行內容可將程式碼注入你執行的每個動態連結工具,而 kernel module 則可同時讓所有程式都看不到檔案。你可能找得到部分跡象,因此找到項目具有意義。但你無法證明不存在其他問題,所以沒有找到問題並不代表系統乾淨。只有在伺服器不存放任何重要資料,且你能接受它可能再次遭入侵時,清理才算合理。
遭入侵的伺服器應關機,還是讓它繼續執行?
先在供應商端切斷其網路,然後讓它繼續執行一段時間,以便擷取 snapshot 並查看執行中的程序。若 /var/log/journal 不存在,關機會摧毀程序清單,並完全刪除 journal,因為 journald 會將資料寫入 /run 下的記憶體。若伺服器正在主動攻擊其他網路,而你無法封鎖其對外流量,仍應將它關機。停止危害比保留證據更重要。
如何判斷攻擊者是在何時取得存取權?
在 /var/log/auth.log 或 journal 中,找出第一筆你無法解釋的 Accepted password 或 Accepted publickey 記錄。再以變更時間清單 find / -xdev -newerct 'YYYY-MM-DD' -type f 交叉比對,因為 ctime 比 mtime 更難偽造。接著將兩者與供應商 abuse ticket 中的時間戳記比較;這些時間是在機器外部記錄的,無法由該機器修改。選擇早於這 3 個日期中最早日期的 backup。如果時間無法對應,請假設入侵早於你的 backup 歷史,並且只還原你能檢查的資料。
遭入侵後,我的 backup 可以安全還原嗎?
資料通常可以,但必須先檢查。系統檔案則不安全。入侵後建立的 backup 可能包含 backdoor,因此還原整個 root filesystem 也會一併還原攻擊者。也要檢查 backup repository 本身:如果其 credentials 儲存在遭入侵的伺服器上,歷史資料可能已被刪除或修改,這正是應採用 append-only 或 pull-based backup target 的原因。先還原應用程式資料,再從 distribution repository 重新安裝軟體。
我是否必須告知他人 VPS 遭到入侵?
務必回覆主機供應商的 abuse notice。除此之外,取決於該機器上存放的是誰的資料。屬於他人的個人資料可能觸發法定通報義務,例如 GDPR 規定須在 72 小時內通知監管機關。如果伺服器儲存了使用者 credentials,請通知這些使用者,讓他們能在其他地方變更密碼。如果伺服器上的 keys 可授權存取第三方系統,例如 code host 或 cloud account,請通知相關供應商,讓他們檢查是否遭到濫用。只存放個人資料、沒有他人資料的伺服器,除了回覆 abuse ticket 外,通常沒有其他義務。