Cách kiểm tra VPS Linux có bị hack không
Kiểm tra VPS bị hack: đăng nhập, user, SSH key, tiến trình, kết nối mạng, cron, systemd, file hệ thống bị sửa và rootkit, kèm lệnh và dấu hiệu cần tìm.

Ý chính
- Kiểm tra đăng nhập, tài khoản và SSH key trước: chúng cho thấy kẻ tấn công vào bằng cách nào và định quay lại ra sao.
- Tìm tiến trình chạy từ /tmp hoặc /dev/shm, file chạy đã bị xoá và kết nối ra ngoài bất thường.
- Cơ chế bám trụ thường nằm trong cron, timer systemd, authorized_keys và /etc/ld.so.preload.
- Kết quả sạch không chứng minh server sạch; nếu root đã bị chiếm, hãy dựng lại thay vì tin vào nó.
Để kiểm tra VPS bị hack hay không, hãy xem bảy chỗ: lịch sử đăng nhập gần đây, tài khoản user và SSH key, tiến trình đang chạy, kết nối mạng, tác vụ định kỳ và dịch vụ, file hệ thống bị thay đổi, và email gửi ra. Dấu hiệu bị xâm nhập gồm đăng nhập từ IP lạ, tài khoản UID 0 mới, SSH key bạn không thêm, tiến trình chạy từ /tmp hoặc /dev/shm, kết nối tới máy lạ và file hệ thống không khớp checksum của gói cài đặt. Các lệnh dưới đây chạy trên Ubuntu và Debian, mất khoảng 20 phút.
Một lưu ý trước khi bắt đầu: nếu kẻ tấn công đã có root, họ có thể làm các công cụ nói dối. Các bước này bắt được những kiểu xâm nhập phổ biến như trình đào coin, script gửi spam và webshell, vốn thường để lại nhiều dấu vết, nhưng kết quả sạch không phải bằng chứng. Nếu thấy dấu hiệu bị chiếm quyền root, hãy dừng điều tra trên hệ thống đang chạy và làm theo kế hoạch dựng lại, như bài quy trình khôi phục khi server bị mã hoá ransomware.
Dấu hiệu VPS có thể đã bị hack
| Triệu chứng | Có thể là gì | Kiểm tra đầu tiên |
|---|---|---|
| CPU 100% dù không có truy cập | Trình đào coin | ps aux --sort=-%cpu |
| IP server nằm trong blacklist spam | Script spam hoặc website bị hack | Hàng đợi mail, ss -tnp ở cổng 25 |
| File lạ trong thư mục website | Webshell hoặc backdoor | Quét mã độc, find theo ngày |
| Nhà cung cấp gửi cảnh báo abuse vì quét cổng hoặc DDoS | Server bị dùng làm bot | ss -tupan, danh sách tiến trình |
| Mật khẩu bị đổi, không đăng nhập được | Bị chiếm tài khoản | last, log xác thực |
| Log bị mất hoặc bị cắt ngắn | Kẻ tấn công xoá dấu vết | journalctl --list-boots, kích thước log |
| Thiết lập tường lửa hoặc SSH bị đổi | Kẻ tấn công giữ đường vào | ufw status, sshd -T |
Trước khi bắt đầu
- Chụp snapshot ở nhà cung cấp VPS nếu có thể. Nó giữ nguyên bằng chứng phòng khi cần sau này.
- Làm việc bằng root qua SSH từ máy tính tin cậy, và lưu kết quả ra file ngoài thư mục web, ví dụ
script /root/ir-$(date +%F).log. - Chưa khởi động lại, chưa xoá gì cả. Xoá file đáng ngờ trước khi biết nó từ đâu tới là xoá mất manh mối tốt nhất.
Bước 1: ai đã đăng nhập, từ đâu?
last -F | head -30 # đăng nhập thành công, đủ ngày giờ
lastb -F | head -30 # đăng nhập thất bại (cần root)
who; w # ai đang đăng nhập lúc này
journalctl -u ssh --since "-7 days" | grep -E "Accepted|Invalid user" | tail -50
grep -E "Accepted (password|publickey)" /var/log/auth.log* 2>/dev/null | tail -50
Cần tìm: dòng Accepted password trong khi bạn chỉ dùng key, đăng nhập từ quốc gia hoặc nhà mạng bạn chưa bao giờ dùng, đăng nhập vào giờ bất thường, và các tài khoản lẽ ra không bao giờ đăng nhập như www-data hay một tài khoản hosting. Hàng nghìn lần đăng nhập thất bại là chuyện bình thường với mọi server công khai; một lần thành công từ IP lạ thì không. (Trên một số hệ thống, unit SSH tên là sshd thay vì ssh.)
Bước 2: tài khoản, quyền sudo và SSH key
awk -F: '$3 == 0 {print $1}' /etc/passwd # ngoài root ra đều đáng ngờ
awk -F: '$3 >= 1000 {print $1, $6, $7}' /etc/passwd
awk -F: '($2 == "") {print $1}' /etc/shadow # tài khoản mật khẩu rỗng
getent group sudo; ls -la /etc/sudoers.d/
find / -xdev -name authorized_keys -exec ls -la {} \; -exec cat {} \; 2>/dev/null
Tìm tài khoản UID 0 thứ hai, user bạn không tạo, file sudoers.d mới sửa gần đây và SSH key có ghi chú lạ. Thêm key vào authorized_keys là kỹ thuật bám trụ tiêu chuẩn, được MITRE ATT&CK ghi nhận là T1098.004. Kiểm tra key của root và của mọi user, không chỉ của bạn.
Bước 3: tiến trình
ps auxf --sort=-%cpu | head -30 # tiến trình tốn tài nguyên nhất, dạng cây
ls -l /proc/*/exe 2>/dev/null | grep -E "deleted|/tmp/|/dev/shm/|/var/tmp/"
ls -la /tmp /var/tmp /dev/shm
Dấu hiệu đáng lo:
- tiến trình chạy một file đã bị xoá khỏi ổ đĩa, mẹo ẩn mình kinh điển;
- file chạy từ
/tmp,/var/tmphoặc/dev/shm, những nơi ai cũng ghi được; - tên giả dạng luồng kernel (kiểu
[kworker]) nhưng lại có đường dẫn file chạy; - user web server hoặc PHP (
www-data, tài khoản hosting) chạybash,perl,python,nchaycurllặp đi lặp lại.
Với PID đáng ngờ, ls -l /proc/<PID>/cwd, cat /proc/<PID>/cmdline | tr '\0' ' ' và ls -l /proc/<PID>/fd cho biết nó chạy từ đâu, được khởi động thế nào và đang giữ file, socket nào.
Bước 4: kết nối mạng
ss -tulpn # cổng nào đang lắng nghe, tiến trình nào
ss -tupn state established # kết nối đang mở kèm tên tiến trình
Mỗi cổng lắng nghe phải ứng với một dịch vụ bạn biết: SSH, web server, mail, panel, database trên 127.0.0.1. Hãy điều tra cổng bạn không giải thích được, tiến trình lắng nghe chạy bằng user web, hoặc kết nối ra ngoài từ PHP hay tài khoản hosting tới cổng IRC, pool đào coin hoặc tới rất nhiều máy ở cổng 22 (server của bạn đang đi quét máy khác).
Bước 5: cron job, unit systemd và cơ chế bám trụ khác
Kẻ tấn công muốn quay lại sau khi reboot hoặc sau khi bị dọn. Kiểm tra mọi bộ lập lịch, không chỉ crontab của root:
for u in $(cut -d: -f1 /etc/passwd); do crontab -l -u "$u" 2>/dev/null | sed "s/^/$u: /"; done
ls -la /etc/cron.d /etc/cron.hourly /etc/cron.daily /var/spool/cron/crontabs 2>/dev/null
systemctl list-timers --all
find /etc/systemd /lib/systemd /usr/lib/systemd ~/.config/systemd -name "*.service" -mtime -14 2>/dev/null
cat /etc/ld.so.preload 2>/dev/null # bình thường file này không tồn tại
ls -la /etc/rc.local /etc/profile.d/ 2>/dev/null
Cron (T1053.003) và dịch vụ systemd (T1543.002) là chỗ quen thuộc. Để ý những dòng tải về rồi chạy (curl ... | sh, wget -q -O-), chuỗi base64 dài và dịch vụ có tên ngẫu nhiên. /etc/ld.so.preload ép một thư viện vào mọi chương trình; hiếm khi được dùng hợp lệ, và sửa nó là kỹ thuật chiếm luồng thực thi đã biết (T1574.006) có thể che file và tiến trình khỏi các công cụ khác.
Bước 6: file hệ thống bị thay đổi
Trên Debian và Ubuntu, trình quản lý gói biết checksum của mọi file nó đã cài:
dpkg --verify 2>/dev/null | grep -v " c /" # file bị đổi, bỏ qua file cấu hình
sudo apt install debsums && sudo debsums -s # cách khác: chỉ in khi có file khác
find /usr/bin /usr/sbin /bin /sbin -newer /etc/hostname -type f 2>/dev/null | head
Trong kết quả của dpkg, ký tự 5 ở cột thứ ba nghĩa là checksum của file không còn khớp với gói. Điều đó bình thường với file cấu hình bạn đã sửa, nên lệnh lọc bỏ các dòng đánh dấu c. Nó không bình thường với /usr/bin/ls, /usr/sbin/sshd hay ps. Lệnh -newer dựa vào một file mốc không bị đụng tới từ lúc cài; hãy chọn file phù hợp với server của bạn.
Sau đó xem các website, nơi phần lớn vụ xâm nhập bắt đầu:
find /var/www /home -name "*.php" -mtime -7 -type f 2>/dev/null | head -50
find /var/www /home -path "*uploads*" -name "*.php" -type f 2>/dev/null
grep -rlE "eval\(base64_decode|gzinflate\(base64_decode|assert\(\\\$_(POST|GET|REQUEST)" /var/www /home --include="*.php" 2>/dev/null | head
File PHP trong thư mục upload và file PHP mới sửa mà bạn không deploy đều cần xem kỹ. Với việc dọn WordPress, xem bài dọn website WordPress bị hack.
Bước 7: log, email và công cụ quét rootkit
journalctl --list-boots | tail # có reboot bất thường không?
ls -la /var/log/ | head -40 # log rỗng hoặc quá nhỏ?
cat /root/.bash_history | tail -50; ls -la /root/.bash_history
postqueue -p 2>/dev/null | tail -5 # hàng đợi mail (Postfix)
File history trỏ về /dev/null, log dừng đột ngột hay hàng đợi mail có hàng nghìn thư đều là dấu hiệu cần lần theo.
Cuối cùng, chạy công cụ quét rootkit như chkrootkit hoặc rkhunter. Cả hai đều có trong kho gói của Ubuntu và Debian. Coi kết quả là manh mối, không phải phán quyết: cả hai có thể báo nhầm trên hệ thống hiện đại, và không công cụ nào thấy được rootkit kernel được làm kỹ.
Nếu phát hiện điều bất thường thì làm gì?
- Đừng đánh động kẻ tấn công bằng cách xoá từng file khi họ vẫn đang kết nối. Chặn mạng ở nhà cung cấp trước, chỉ chừa IP của bạn.
- Tìm lối vào từ các mốc thời gian đã thu thập: lần đăng nhập lạ đầu tiên, webshell đầu tiên, file hệ thống bị sửa đầu tiên.
- Xác định phạm vi. Một webshell chạy bằng một tài khoản hosting, không có dấu hiệu chiếm root, thường dọn được bên trong tài khoản đó. Dấu hiệu bị chiếm root (file hệ thống bị sửa, user UID 0 mới, key hoặc crontab của root bị đổi, có
ld.so.preload) nghĩa là bạn dựng lại server và khôi phục dữ liệu từ backup trước thời điểm bị xâm nhập. - Đổi mọi thông tin đăng nhập từng nằm trên server, và vá chỗ đã cho họ vào. Bài chống brute force SSH nói về một lối vào phổ biến của server vẫn cho đăng nhập bằng mật khẩu.
Kiểm tra trên server ZoPanel
ZoPanel tự động hoá một phần công việc này. Quét mã độc kiểm tra file website của mọi tài khoản hosting vào 03:00 mỗi Chủ nhật và khi bạn bấm quét, tìm webshell, backdoor, PHP bị làm rối, JavaScript bị chèn và file PHP trong thư mục upload, rồi cho bạn cách ly (quarantine) file tìm thấy vào một thư mục chỉ root đọc được. Security Center, mô tả trong tài liệu bảo mật, kiểm tra tài khoản UID 0 thừa, mật khẩu rỗng, dịch vụ mở cổng công khai, thiết lập SSH, bản cập nhật đang chờ và nhật ký hoạt động có chuỗi hash còn nguyên vẹn không. Cảnh báo có thể báo cho bạn khi đăng nhập panel thất bại, có đăng nhập từ IP mới và khi phát hiện mã độc, qua email hoặc Telegram.
Những gì nó không làm: trình quét mã độc chỉ đọc file trong thư mục domains/ của mỗi tài khoản, tối đa 4 MB, với các đuôi file script đã biết, nên mã PHP giấu trong file .jpg hoặc nằm ngoài domains/ sẽ bị bỏ sót. Nó không phải công cụ phát hiện rootkit và không kiểm tra file hệ thống. Hãy chạy thêm các lệnh ở trên, nhất là sau mỗi cảnh báo. Cách ly tài khoản giúp website bị hack không lây sang chỗ khác; chúng tôi giải thích các lớp trong bài cách ly tài khoản hosting.
Kết luận
Để kiểm tra VPS bị hack, hãy đi lần lượt qua đăng nhập, tài khoản và key, tiến trình, mạng, cơ chế bám trụ, file bị sửa và log, đồng thời ghi lại những gì tìm thấy kèm thời gian. Các vụ xâm nhập phổ biến thường để lại dấu vết ở ít nhất một trong những chỗ đó. Nếu dấu vết chỉ tới quyền root, hãy dừng dọn dẹp và dựng lại.
Nếu bạn muốn có sẵn quét mã độc hằng tuần, các kiểm tra của Security Center và cảnh báo, hãy thử gói Free của ZoPanel: 3 tài khoản hosting, 10 website, 10 database, không giới hạn thời gian. Trang tính năng bảo mật liệt kê chi tiết các lớp bảo vệ.
Câu hỏi thường gặp
Làm sao biết có người đã truy cập VPS Linux của mình?
Xem last -F và log SSH (journalctl -u ssh hoặc /var/log/auth.log) để tìm lần đăng nhập thành công, rồi so IP và thời gian với của bạn. Kiểm tra cả authorized_keys của mọi user, vì kẻ tấn công đã thêm key có thể đăng nhập mà không cần mật khẩu.
Server bị hack có thể trông hoàn toàn bình thường không?
Có. Kẻ tấn công cẩn thận có root có thể che tiến trình, file và kết nối khỏi các công cụ thông thường, ví dụ bằng rootkit hoặc /etc/ld.so.preload. Vì vậy kết quả quét sạch không phải bằng chứng, và server có dấu hiệu bị chiếm root nên được dựng lại.
Công cụ nào quét mã độc cho server Linux?
Ở cấp server, chkrootkit và rkhunter tìm rootkit đã biết và thay đổi đáng ngờ, còn dpkg --verify hoặc debsums so file đã cài với checksum của gói. Với file website, hãy dùng trình quét hiểu webshell và PHP bị làm rối, như trình quét có sẵn trong control panel.
VPS bị hack thì việc đầu tiên cần làm là gì?
Chụp snapshot ở nhà cung cấp, giới hạn truy cập mạng chỉ còn IP của bạn, chưa reboot và chưa xoá file. Sau đó tìm lối vào, xác định root có bị chiếm không, rồi hoặc dọn tài khoản bị ảnh hưởng, hoặc dựng lại server từ backup sạch.
Vì sao CPU server lên 100% dù không có ai truy cập?
Trên server bị xâm nhập, nguyên nhân hay gặp là trình đào coin, thường chạy từ /tmp hoặc /dev/shm và được cron job khởi động lại. Chạy ps aux --sort=-%cpu, xem tiến trình đứng đầu chạy từ đâu bằng ls -l /proc/<PID>/exe, và kiểm tra crontab của mọi user.
Đọc tiếp

Checklist bảo mật VPS hosting: 40 mục cần kiểm tra
Checklist bảo mật VPS chạy website với 40 mục: cập nhật, SSH, tường lửa, control panel, cách ly tài khoản, lớp web và backup.

CyberPanel có an toàn không? Lịch sử lỗ hổng, cách kiểm tra và gia cố năm 2026
CyberPanel có an toàn không năm 2026? Các CVE từ đợt ransomware 2024 đến 2026, cách kiểm tra server bị xâm nhập và cách gia cố nếu tiếp tục dùng.

Cách chạy nhiều website trên 1 VPS mà vẫn tách biệt an toàn
Hướng dẫn chạy nhiều website trên 1 VPS với nginx: mỗi site một server block, user Linux, pool PHP-FPM, database, SSL riêng và giới hạn tài nguyên.