Tháng 3 năm ngoái, mình nhận cuộc gọi lúc 2 giờ sáng — một production server đang chạy CPU 100%, traffic đi ra ngoài mà không ai biết tại sao. Không có playbook, không có checklist, mọi người chạy loạn. Kết quả: mất 6 tiếng để xử lý một incident mà đúng ra chỉ cần 90 phút nếu có quy trình rõ ràng.
Qua 10+ server production mình đã audit, hầu hết đều mắc chung một điểm — không phải về kỹ thuật, mà về quy trình. Tool thì đủ, kiến thức thì có, nhưng khi incident thật sự xảy ra, không ai biết nên làm gì trước, làm gì sau. Đây là quy trình mình đang dùng thực tế, kèm lệnh cụ thể để bạn áp dụng ngay.
Incident Response là gì — và tại sao cần quy trình riêng?
Nói thẳng: Incident Response (IR) chỉ là câu trả lời có trình tự cho một câu hỏi đơn giản — khi bị hack, bạn làm gì đầu tiên? Detect, contain, investigate, recover. Nghe đơn giản, nhưng thiếu quy trình thì loạn thật.
Lý do cần quy trình cố định thay vì ứng xử theo bản năng:
- Dưới áp lực, người ta thường bỏ sót bước quan trọng — ví dụ backup log trước khi xóa malware
- Không có checklist dẫn đến team làm trùng nhau hoặc bỏ sót hoàn toàn
- Không document → sau incident không biết chính xác chuyện gì đã xảy ra, không cải thiện được
Mô hình IR phổ biến nhất là PICERL của SANS: Preparation → Identification → Containment → Eradication → Recovery → Lessons Learned. Mình sẽ đi thẳng vào phần thực chiến theo đúng thứ tự này.
Bước 1: Phát hiện và xác nhận sự cố
Trước khi làm bất cứ điều gì, cần xác nhận đây có thực sự là incident không — hay chỉ là false alarm do spike traffic bình thường.
Kiểm tra process bất thường
# Xem process đang chạy, sort theo CPU
ps aux --sort=-%cpu | head -20
# Kiểm tra process ẩn (PID không liên tục = dấu hiệu đáng ngờ)
ls /proc | grep -E '^[0-9]+$' | sort -n > /tmp/proc_pids.txt
ps aux | awk '{print $2}' | sort -n > /tmp/ps_pids.txt
diff /tmp/proc_pids.txt /tmp/ps_pids.txt
# Xem cây process, phát hiện shell spawn bất thường
pstree -a -p
Kiểm tra kết nối mạng
# Kết nối đang active
ss -tulnp
netstat -antp | grep ESTABLISHED
# Xem traffic đi ra ngoài theo process
lsof -i -n -P | grep -v LISTEN
Kiểm tra user đang login
who
w
last -n 20 # 20 lần login gần nhất
lastb -n 20 # 20 lần login thất bại gần nhất
Thấy process lạ ngốn CPU/bandwidth, kết nối đến IP nước ngoài không rõ nguồn gốc, hoặc user không quen đang online lúc 3 giờ sáng — đây là incident thật, chuyển sang bước tiếp theo ngay.
Bước 2: Cô lập hệ thống ngay lập tức
Bước này bị bỏ qua nhiều nhất — và thường là sai lầm đắt giá nhất. Nhiều team nhảy thẳng vào điều tra trong khi attacker vẫn đang kết nối, tiếp tục exfiltrate dữ liệu. Nguyên tắc cứng: cô lập trước, điều tra sau.
# Block toàn bộ traffic, chỉ giữ kết nối từ IP của bạn
YOUR_IP="1.2.3.4" # Thay bằng IP thật của bạn
iptables -F && iptables -X
# Cho phép IP của bạn
iptables -A INPUT -s $YOUR_IP -j ACCEPT
iptables -A OUTPUT -d $YOUR_IP -j ACCEPT
# Cho phép loopback
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
# Block tất cả còn lại
iptables -A INPUT -j DROP
iptables -A OUTPUT -j DROP
iptables -A FORWARD -j DROP
Tại sao không tắt server ngay? RAM đang chứa rất nhiều thứ quý: process đang chạy, encryption keys, network state — tất cả mất sạch khi shutdown. Cô lập network giữ nguyên evidence, attacker không vào được nữa.
Trường hợp buộc phải tắt — ví dụ ransomware đang mã hóa file — hãy cắt nguồn cứng thay vì chạy shutdown. Lý do: attacker thường nhúng cleanup script chạy khi hệ thống shutdown gracefully.
Bước 3: Thu thập bằng chứng và điều tra
Khi mạng đã bị cô lập, thu thập evidence theo thứ tự ưu tiên: volatile data (RAM, network state) trước, non-volatile (disk, logs) sau. Đừng đảo ngược.
Thu thập thông tin hệ thống
# Tạo thư mục evidence với timestamp
EVIDENCE_DIR="/tmp/ir-$(date +%Y%m%d-%H%M%S)"
mkdir -p $EVIDENCE_DIR
date > $EVIDENCE_DIR/timestamp.txt
uname -a > $EVIDENCE_DIR/sysinfo.txt
uptime >> $EVIDENCE_DIR/sysinfo.txt
ps auxf > $EVIDENCE_DIR/processes.txt
ss -tulnp > $EVIDENCE_DIR/network.txt
netstat -rn > $EVIDENCE_DIR/routes.txt
lsof -n > $EVIDENCE_DIR/open_files.txt
Tìm file bị thay đổi gần đây
# File thay đổi trong 24 giờ qua (bỏ qua /proc, /sys, /dev)
find / -not \( -path /proc -prune \) \
-not \( -path /sys -prune \) \
-not \( -path /dev -prune \) \
-mtime -1 -type f 2>/dev/null > $EVIDENCE_DIR/recent_files.txt
# File SUID/SGID bất thường
find / -perm /6000 -type f 2>/dev/null > $EVIDENCE_DIR/suid_files.txt
Phân tích logs tìm dấu hiệu xâm nhập
# Brute force SSH và login thành công bất thường
grep "Failed password" /var/log/auth.log \
| awk '{print $11}' | sort | uniq -c | sort -rn | head -20
grep "Accepted password\|Accepted publickey" /var/log/auth.log | tail -50
# Crontab/at job mới được thêm
grep -i "cron\|atd" /var/log/syslog | tail -50
Kiểm tra persistence mechanisms
# Crontab của tất cả user
for user in $(cut -d: -f1 /etc/passwd); do
echo "=== $user ==="
crontab -u $user -l 2>/dev/null
done
# Systemd services lạ đang chạy
systemctl list-units --type=service --state=running
# SSH authorized_keys — tìm key lạ được thêm vào
find /home /root -name "authorized_keys" \
-exec echo "=== {} ===" \; -exec cat {} \; 2>/dev/null
# User mới được tạo (không phải system account)
grep -v "nologin\|false" /etc/passwd
Bước 4: Xóa bỏ mối đe dọa
Chỉ bắt đầu xóa khi đã biết chính xác vấn đề. Không xóa theo cảm tính — mỗi thao tác cần timestamp để có incident report thực sự dùng được sau này.
# Xóa user giả mạo
userdel -r suspicious_username
# Xóa SSH key lạ khỏi authorized_keys
# Mở file, tìm và xóa dòng chứa key không nhận ra
nano /root/.ssh/authorized_keys
# Kill process malware theo PID
kill -9 <PID>
# Xóa crontab của user bị compromise
crontab -r -u www-data
# Reinstall binary có thể bị replace bởi attacker
apt-get install --reinstall openssh-server nginx
Lỗi mình thấy lặp đi lặp lại: team xóa malware xong mới nhớ ra chưa lấy hash hay sample. Lúc đó muốn phân tích thêm cũng không còn gì. Backup evidence trước, xóa sau — không có ngoại lệ.
Bước 5: Khôi phục hệ thống an toàn
Restore từ backup mà không hiểu attack vector thì chỉ là câu giờ. Lỗ hổng vẫn còn đó, bạn sẽ lặp lại incident sau 2–3 tuần — mình đã thấy điều này xảy ra ít nhất 3 lần với các server mình audit.
Checklist trước khi đưa server trở lại production:
- Xác nhận attack vector đã được vá (patch CVE, đổi credential bị lộ, fix misconfiguration)
- Restore từ backup trước thời điểm nghi ngờ bị compromise
- Verify integrity của backup bằng checksum
- Reset password toàn bộ user liên quan
# Force đổi password khi login lần tới
chage -d 0 username
# Regenerate SSH host keys (quan trọng nếu key cũ bị lộ)
rm /etc/ssh/ssh_host_*
dpkg-reconfigure openssh-server
# Enable auditd để theo dõi sau khi restore
systemctl enable --now auditd
Chuẩn bị trước để incident nhẹ nhàng hơn
80% độ phức tạp của mọi incident mình từng xử lý đến từ việc không chuẩn bị trước. Ba thứ nên làm ngay hôm nay, không đợi đến khi cần:
Baseline system — snapshot trạng thái bình thường
# Chạy định kỳ (cron hàng tuần), lưu để so sánh sau
mkdir -p /var/lib/ir-baseline
md5sum /usr/sbin/* /usr/bin/* > /var/lib/ir-baseline/bin_hashes.txt
ss -tulnp > /var/lib/ir-baseline/network.txt
ps auxf > /var/lib/ir-baseline/processes.txt
crontab -l > /var/lib/ir-baseline/crontab.txt
Đưa log ra ngoài server ngay
Attacker thường xóa log local sau khi xâm nhập. Gửi log đến syslog server bên ngoài ngay từ đầu:
# Thêm vào /etc/rsyslog.conf
echo "*.* @your-syslog-server:514" >> /etc/rsyslog.conf
systemctl restart rsyslog
IR toolkit — cài sẵn trước khi cần
apt-get install -y chkrootkit rkhunter tcpdump strace lsof auditd
Thứ tạo ra sự khác biệt lớn nhất sau tất cả: document lại mọi incident, dù nhỏ. Post-mortem không phải để tìm người đổ lỗi — mà để lần sau xử lý nhanh hơn 50%. Mình đang giữ một file incidents.md ghi lại timeline, attack vector, và lessons learned của từng lần. Sau 1 năm, đó là tài liệu training tốt nhất mình có.

