Linux Security Hardening
Panduan hardening keamanan Linux secara bertahap — mulai dari konfigurasi minimum yang wajib di semua server produksi, hingga level maksimum untuk lingkungan kritis. Setiap section adalah satu lapisan keamanan independen yang bisa diimplementasikan secara progresif.
Fondasi Sistem — Level Minimum
Tiga langkah wajib sebelum semua yang lain: sistem selalu diperbarui, login root dinonaktifkan, dan setiap admin memiliki akun non-root dengan sudo.
Update sistem dan aktifkan pembaruan keamanan otomatis
# Debian / Ubuntu apt update && apt upgrade -y apt install unattended-upgrades apt-listchanges -y dpkg-reconfigure -plow unattended-upgrades # aktifkan interactive # atau langsung: echo 'Unattended-Upgrade::Automatic-Reboot "false";' >> /etc/apt/apt.conf.d/50unattended-upgrades systemctl enable --now unattended-upgrades # RHEL / Rocky / Alma / CentOS Stream dnf update -y dnf install dnf-automatic -y # /etc/dnf/automatic.conf → apply_updates = yes systemctl enable --now dnf-automatic-install.timer # Verifikasi timer berjalan systemctl list-timers | grep -E 'dnf|unattended'
Buat user admin non-root dan kunci akun root
sudo su - dengan sukses. Satu kesalahan bisa mengakibatkan lockout total.# Buat user baru useradd -m -s /bin/bash -G sudo aldo # Debian/Ubuntu (group sudo) useradd -m -s /bin/bash -G wheel aldo # RHEL/Rocky (group wheel) passwd aldo # Verifikasi akses sudo SEBELUM melanjutkan su - aldo sudo whoami # harus output: root exit # Kunci akun root (bukan hapus - tetap bisa di-restore) passwd -l root # kunci password root usermod -s /usr/sbin/nologin root # cabut shell login root # Verifikasi grep root /etc/passwd # shell harus /usr/sbin/nologin passwd -S root # status L = locked
Konfigurasi sudo dengan prinsip least privilege
# Selalu edit sudoers via visudo (syntax check otomatis) visudo # Di dalam file sudoers - contoh konfigurasi aman: # Require password for all sudo (default sudoers sudah begini) Defaults passwd_tries=3 Defaults badpass_message="Password salah, akses direkam." Defaults logfile="/var/log/sudo.log" Defaults log_input, log_output # catat semua sesi sudo Defaults requiretty # cegah sudo dari cron/script liar # User sudo dengan password (tidak pakai NOPASSWD) %sudo ALL=(ALL:ALL) ALL # Debian %wheel ALL=(ALL:ALL) ALL # RHEL # Jika perlu NOPASSWD, batasi perintah spesifik saja: aldo ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart nginx # Verifikasi sudoers tidak ada syntax error visudo -c
SSH Hardening — Level Minimum
SSH adalah titik masuk utama ke server. Konfigurasi yang lemah di sini membatalkan semua lapisan keamanan lainnya.
Konfigurasi sshd_config kritis
cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak cat >> /etc/ssh/sshd_config << 'EOF' # === Security Hardening === Port 2222 # ganti port default (obscurity, bukan keamanan utama) PermitRootLogin no # larang login langsung sebagai root PasswordAuthentication no # wajib key-based, nonaktifkan password PubkeyAuthentication yes AuthorizedKeysFile .ssh/authorized_keys PermitEmptyPasswords no ChallengeResponseAuthentication no UsePAM yes X11Forwarding no # matikan X11 forwarding AllowAgentForwarding no AllowTcpForwarding no # matikan jika tidak butuh port forwarding PermitTunnel no MaxAuthTries 3 # maksimal 3 percobaan login MaxSessions 5 LoginGraceTime 30 # timeout handshake 30 detik ClientAliveInterval 300 # kirim keepalive tiap 5 menit ClientAliveCountMax 2 # putus koneksi jika tidak ada respons 2x # Whitelist algoritma kuat (SSH modern) KexAlgorithms curve25519-sha256,ecdh-sha2-nistp521 Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com MACs hmac-sha2-512,hmac-sha2-256 # Batasi akses ke user/group tertentu AllowUsers aldo deploy # hanya user ini yang boleh SSH # AllowGroups sshusers # atau via group EOF # Validasi konfigurasi sshd -t # dry-run, tampilkan error jika ada # Restart (pastikan ada sesi backup!) systemctl restart sshd systemctl status sshd
Setup SSH key dan deploy ke server
ed25519 sebagai algoritma key. Lebih kecil, lebih cepat, dan secara kriptografi lebih kuat dari RSA-2048.# === Di MESIN LOKAL === # Generate key ed25519 ssh-keygen -t ed25519 -C "aldo@laptop-$(date +%Y%m%d)" -f ~/.ssh/id_ed25519_server # Copy public key ke server (sebelum menonaktifkan password auth!) ssh-copy-id -i ~/.ssh/id_ed25519_server.pub -p 22 aldo@<server-ip> # atau manual: cat ~/.ssh/id_ed25519_server.pub | ssh aldo@<server-ip> "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys" # Test login dengan key sebelum restart sshd ssh -i ~/.ssh/id_ed25519_server -p 22 aldo@<server-ip> # === Di SERVER === # Pastikan permissions authorized_keys benar chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys restorecon -Rv ~/.ssh # SELinux: restore context # Verifikasi setelah ganti port ssh -i ~/.ssh/id_ed25519_server -p 2222 aldo@<server-ip>
Hardening tambahan: banner dan banner legal
# Buat banner peringatan legal cat > /etc/ssh/banner << 'EOF' ******************************************************************* AKSES TIDAK SAH DILARANG — Aktivitas direkam dan dimonitor. Dengan login, Anda menyetujui kebijakan penggunaan sistem ini. ******************************************************************* EOF # Tambahkan ke sshd_config echo "Banner /etc/ssh/banner" >> /etc/ssh/sshd_config systemctl reload sshd
Firewall — Level Minimum
Default deny untuk semua koneksi masuk — hanya port yang eksplisit diizinkan yang bisa diakses. Pilih UFW (Debian/Ubuntu) atau firewalld (RHEL).
UFW — Debian / Ubuntu
apt install ufw -y # Aturan default ufw default deny incoming ufw default allow outgoing ufw default deny forward # Izinkan port yang dibutuhkan ufw allow 2222/tcp comment "SSH" ufw allow 80/tcp comment "HTTP" ufw allow 443/tcp comment "HTTPS" # Izinkan dari IP/subnet spesifik saja (lebih aman) ufw allow from 10.0.0.0/8 to any port 2222 # Rate limiting SSH (cegah brute force) ufw limit 2222/tcp # Aktifkan ufw enable ufw status verbose # Tambah / hapus rule ufw deny 3306/tcp # blokir MySQL dari luar ufw delete allow 80/tcp # hapus rule ufw reload
Firewalld — RHEL / Rocky / Alma
systemctl enable --now firewalld # Set zone default ke drop (tolak semua tanpa respons) firewall-cmd --set-default-zone=drop # Tambahkan service/port ke zone public firewall-cmd --permanent --zone=public --add-port=2222/tcp firewall-cmd --permanent --zone=public --add-service=http firewall-cmd --permanent --zone=public --add-service=https # Hapus service default yang tidak dibutuhkan firewall-cmd --permanent --zone=public --remove-service=dhcpv6-client firewall-cmd --permanent --zone=public --remove-service=cockpit # Batasi SSH hanya dari IP tertentu firewall-cmd --permanent --zone=drop --add-rich-rule=' rule family="ipv4" source address="10.0.0.0/8" port port="2222" protocol="tcp" accept' firewall-cmd --reload firewall-cmd --list-all
Verifikasi port yang mendengarkan
ss -tulnp # semua listening ports + proses ss -tulnp | grep LISTEN # filter hanya yang listen netstat -tulnp 2>/dev/null || ss -tulnp # Port yang tidak dikenal? selidiki prosesnya lsof -i :<port> fuser <port>/tcp
Proteksi Brute Force — Level Minimum
Fail2ban memantau log dan memblokir IP yang melakukan terlalu banyak percobaan login gagal. Perlindungan pertama terhadap serangan dictionary/brute-force otomatis.
Install dan konfigurasi dasar Fail2ban
apt install fail2ban -y # Debian/Ubuntu dnf install fail2ban -y # RHEL # Selalu buat jail.local — jangan edit jail.conf langsung cat > /etc/fail2ban/jail.local << 'EOF' [DEFAULT] # Waktu ban default: 1 jam bantime = 1h # Jendela waktu penghitungan retry findtime = 10m # Maks percobaan gagal sebelum ban maxretry = 3 # Jangan ban IP lokal ignoreip = 127.0.0.1/8 ::1 10.0.0.0/8 # Backend untuk monitoring log backend = auto # Email notifikasi (opsional) # destemail = admin@example.com # sender = fail2ban@example.com # action = %(action_mwl)s [sshd] enabled = true port = 2222 logpath = %(sshd_log)s backend = %(sshd_backend)s maxretry = 3 bantime = 24h # ban 24 jam untuk SSH (lebih keras dari default) EOF systemctl enable --now fail2ban
Tambah jail untuk service lain
# Tambahkan di /etc/fail2ban/jail.local [nginx-http-auth] enabled = true port = http,https logpath = /var/log/nginx/error.log maxretry = 5 [nginx-limit-req] enabled = true port = http,https logpath = /var/log/nginx/error.log maxretry = 10 [postfix-sasl] enabled = true port = smtp,submission,imap,imaps logpath = %(postfix_log)s systemctl reload fail2ban
Manajemen ban dan monitoring
fail2ban-client status # status semua jail fail2ban-client status sshd # detail jail SSH: banned IPs, total # Unban IP secara manual fail2ban-client set sshd unbanip 1.2.3.4 # Lihat log fail2ban tail -f /var/log/fail2ban.log grep "Ban " /var/log/fail2ban.log | tail -20 # Test apakah IP dibanned fail2ban-client get sshd banned fail2ban-client get sshd banip 1.2.3.4 # cek status 1 IP
Kernel & Sysctl Hardening — Level Menengah
Parameter kernel untuk menutup celah jaringan umum: IP spoofing, ICMP redirect, SYN flood, dan membatasi informasi sensitif kernel yang bisa dibaca oleh proses biasa.
Hardening jaringan (network stack)
cat > /etc/sysctl.d/99-security.conf << 'EOF' # ─── Jaringan IPv4 ─────────────────────────────────────────── # Nonaktifkan IP forwarding (kecuali server ini adalah router/VPN) net.ipv4.ip_forward = 0 net.ipv6.conf.all.forwarding = 0 # Blokir source routing (paket dengan rute yang ditentukan pengirim) net.ipv4.conf.all.accept_source_route = 0 net.ipv4.conf.default.accept_source_route = 0 # Tolak ICMP redirect (cegah rerouting jahat) net.ipv4.conf.all.accept_redirects = 0 net.ipv4.conf.default.accept_redirects = 0 net.ipv4.conf.all.secure_redirects = 0 net.ipv4.conf.all.send_redirects = 0 net.ipv6.conf.all.accept_redirects = 0 # Log paket dari luar yang mengklaim IP internal (martian packets) net.ipv4.conf.all.log_martians = 1 net.ipv4.conf.default.log_martians = 1 # Proteksi SYN flood net.ipv4.tcp_syncookies = 1 net.ipv4.tcp_max_syn_backlog = 2048 # Reverse path filtering (cegah IP spoofing) net.ipv4.conf.all.rp_filter = 1 net.ipv4.conf.default.rp_filter = 1 # Abaikan broadcast ping (amplification attack) net.ipv4.icmp_echo_ignore_broadcasts = 1 net.ipv4.icmp_ignore_bogus_error_responses = 1 # Nonaktifkan IPv6 jika tidak digunakan net.ipv6.conf.all.disable_ipv6 = 1 net.ipv6.conf.default.disable_ipv6 = 1 net.ipv6.conf.lo.disable_ipv6 = 1 EOF
Hardening memori dan informasi kernel
cat >> /etc/sysctl.d/99-security.conf << 'EOF' # ─── Memori & Kernel ──────────────────────────────────────── # ASLR — Address Space Layout Randomization (level 2 = full randomisasi) kernel.randomize_va_space = 2 # Batasi akses ke dmesg (log kernel) hanya untuk root kernel.dmesg_restrict = 1 # Sembunyikan pointer kernel dari userspace (/proc, /sys) kernel.kptr_restrict = 2 # Nonaktifkan SysRq magic key (berbahaya jika akses fisik/serial) kernel.sysrq = 0 # Tambahkan PID ke core dump filename kernel.core_uses_pid = 1 # Batasi akses ke perf events (data microarchitecture bisa bocorkan info) kernel.perf_event_paranoid = 3 # Nonaktifkan core dumps untuk setuid programs fs.suid_dumpable = 0 # Batasi symlink dan hardlink traversal (cegah TOCTOU attacks) fs.protected_symlinks = 1 fs.protected_hardlinks = 1 fs.protected_fifos = 2 fs.protected_regular = 2 EOF # Apply semua perubahan sysctl -p /etc/sysctl.d/99-security.conf # Verifikasi satu nilai sysctl kernel.randomize_va_space sysctl net.ipv4.tcp_syncookies
Audit & Logging — Level Menengah
Auditd mencatat siapa yang mengubah file kritis, menjalankan perintah privileged, atau mencoba eskalasi. Tanpa audit trail, investigasi insiden adalah tebak-tebakan.
Install auditd dan atur rules kritis
-e 2 di akhir membuat konfigurasi immutable sampai reboot. Ini mencegah attacker menghapus rules setelah masuk — tapi juga berarti Anda perlu reboot untuk mengubah rules.apt install auditd audispd-plugins -y # Debian/Ubuntu dnf install audit audit-libs -y # RHEL systemctl enable --now auditd cat > /etc/audit/rules.d/hardening.rules << 'EOF' # Hapus rules yang ada dan set buffer -D -b 8192 -f 1 # ─── Identity & Access ──────────────────────────────────────── -w /etc/passwd -p wa -k identity -w /etc/shadow -p wa -k identity -w /etc/group -p wa -k identity -w /etc/gshadow -p wa -k identity -w /etc/sudoers -p wa -k sudoers -w /etc/sudoers.d/ -p wa -k sudoers -w /var/log/auth.log -p wa -k auth_log # Debian -w /var/log/secure -p wa -k auth_log # RHEL # ─── SSH & PAM ──────────────────────────────────────────────── -w /etc/ssh/sshd_config -p wa -k sshd_config -w /etc/pam.d/ -p wa -k pam_config # ─── Privileged commands ───────────────────────────────────── -a always,exit -F arch=b64 -S execve -F uid=0 -F auid!=unset -k root_commands -a always,exit -F path=/usr/bin/sudo -F perm=x -k sudo_exec -a always,exit -F path=/usr/bin/su -F perm=x -k su_exec -a always,exit -F path=/usr/sbin/useradd -F perm=x -k user_mgmt -a always,exit -F path=/usr/sbin/userdel -F perm=x -k user_mgmt -a always,exit -F path=/usr/sbin/usermod -F perm=x -k user_mgmt -a always,exit -F path=/usr/bin/passwd -F perm=x -k user_mgmt # ─── Kernel modules ────────────────────────────────────────── -w /sbin/insmod -p x -k modules -w /sbin/rmmod -p x -k modules -w /sbin/modprobe -p x -k modules -a always,exit -F arch=b64 -S init_module,finit_module,delete_module -k modules # ─── File & directory changes di lokasi sensitif ───────────── -w /bin/ -p wa -k bin_changes -w /sbin/ -p wa -k sbin_changes -w /etc/cron.d/ -p wa -k cron -w /etc/crontab -p wa -k cron -w /var/spool/cron/ -p wa -k cron # ─── Eskalasi privilege & SUID ─────────────────────────────── -a always,exit -F arch=b64 -S setuid,setgid,setreuid,setregid -k privilege_escalation -a always,exit -F arch=b64 -S chmod,fchmod,fchmodat -F auid>=1000 -k file_perm_change # Immutable — harus reboot untuk mengubah rules di atas -e 2 EOF # Load rules augenrules --load auditctl -l # verifikasi rules aktif
Query dan analisis audit log
# Cari event berdasarkan key ausearch -k sudoers --interpret # perubahan sudoers ausearch -k user_mgmt -ts today # manajemen user hari ini ausearch -k sshd_config -ts recent # perubahan SSH config # Laporan ringkas aureport --summary # ringkasan semua event aureport --login # semua event login aureport --auth --failed # semua autentikasi gagal aureport --exec # semua eksekusi program aureport --file --summary # file paling sering diakses # Filter berdasarkan waktu dan user ausearch -ua aldo -ts "01/01/2025 00:00:00" -te "31/01/2025 23:59:59" # Cek log audit secara langsung tail -f /var/log/audit/audit.log | grep -E 'key=|type=EXECVE'
Sentralisasi log ke remote server
# /etc/rsyslog.d/10-remote.conf (di server sumber) # Kirim semua log ke log server (port 514 TCP terenkripsi lebih baik) *.* action(type="omfwd" target="logserver.internal" port="514" protocol="tcp") # Pastikan log tidak bisa dihapus attacker dengan chattr +a chattr +a /var/log/auth.log chattr +a /var/log/syslog chattr +a /var/log/audit/audit.log # Verifikasi lsattr /var/log/auth.log # harus tampil 'a' flag systemctl restart rsyslog
File System & Integritas — Level Menengah
Cari dan perbaiki file berbahaya (SUID/world-writable), hardening mount point dengan flag noexec/nosuid/nodev, dan pasang AIDE untuk deteksi perubahan file yang tidak sah.
Audit file SUID, SGID, dan world-writable
passwd atau ping akan merusak fungsionalitas.# Temukan semua file SUID (jalankan sebagai root) find / -perm /4000 -type f -ls 2>/dev/null | sort -k11 # Temukan semua file SGID find / -perm /2000 -type f -ls 2>/dev/null | sort -k11 # Temukan world-writable files (kecuali /proc dan /sys) find / -perm -002 -type f \ -not -path "/proc/*" \ -not -path "/sys/*" \ -not -path "/dev/*" \ 2>/dev/null # Temukan world-writable directories tanpa sticky bit find / -perm -002 -type d -not -perm -1000 \ -not -path "/proc/*" -not -path "/sys/*" 2>/dev/null # Hapus SUID dari program yang tidak perlu chmod u-s /usr/bin/at # contoh: 'at' jarang dibutuhkan chmod u-s /usr/bin/newgrp # Simpan baseline untuk referensi find / -perm /4000 -type f 2>/dev/null > /root/suid-baseline.txt
Hardening mount point di /etc/fstab
/tmp membungkam sebagian besar teknik privilege escalation.# Tambahkan/update entri di /etc/fstab # Backup dulu! cp /etc/fstab /etc/fstab.bak # Tambahkan flag keamanan ke partisi yang ada: # (sesuaikan UUID/device dengan output 'blkid') # # /tmp — tidak ada alasan untuk menjalankan binary dari /tmp tmpfs /tmp tmpfs defaults,nodev,nosuid,noexec,size=1G 0 0 # /dev/shm — memory-mapped shared memory, sering dieksploitasi tmpfs /dev/shm tmpfs defaults,nodev,nosuid,noexec 0 0 # /home — tidak perlu device files UUID=xxxx /home ext4 defaults,nodev,nosuid 0 2 # /var/tmp — persistent temp, sama dengan /tmp UUID=xxxx /var/tmp ext4 defaults,nodev,nosuid,noexec 0 2 # Remount tanpa reboot mount -o remount /tmp mount -o remount /dev/shm mount | grep -E '/tmp|/dev/shm' # verifikasi flag aktif
Permissions file konfigurasi kritis
# File password — hanya root yang boleh baca chmod 640 /etc/shadow chmod 640 /etc/gshadow chown root:shadow /etc/shadow chown root:shadow /etc/gshadow # File konfigurasi — semua user boleh baca (untuk lookup) chmod 644 /etc/passwd chmod 644 /etc/group # Sudoers — hanya root chmod 440 /etc/sudoers chown root:root /etc/sudoers # SSH host keys — private key hanya root chmod 600 /etc/ssh/ssh_host_*_key chmod 644 /etc/ssh/ssh_host_*_key.pub chown root:root /etc/ssh/ssh_host_* # Verifikasi ls -la /etc/shadow /etc/passwd /etc/sudoers /etc/ssh/ssh_host_ed25519_key
AIDE — File Integrity Monitoring
apt install aide aide-common -y # Debian/Ubuntu dnf install aide -y # RHEL # Build database awal (berjalan lama ~10-30 menit) aideinit # Debian: database tersimpan di /var/lib/aide/aide.db.new # RHEL: database tersimpan di /var/lib/aide/aide.db.new.gz # Aktifkan database (rename menjadi database aktif) cp /var/lib/aide/aide.db.new /var/lib/aide/aide.db # Debian # cp /var/lib/aide/aide.db.new.gz /var/lib/aide/aide.db.gz # RHEL # Cek integritas (bandingkan sistem sekarang dengan baseline) aide --check # Output: Added/Removed/Changed files # Update database setelah patch/update sistem yang sah aide --update cp /var/lib/aide/aide.db.new /var/lib/aide/aide.db # Jadwalkan cek harian via cron cat > /etc/cron.d/aide-check << 'EOF' MAILTO=admin@example.com 0 3 * * * root /usr/bin/aide --check 2>&1 | grep -E "^(AIDE|Changed|Added|Removed)" EOF
Kebijakan Akun & Password — Level Menengah
Password yang lemah dan akun tidak aktif adalah pintu belakang yang sering diabaikan. Enforcing complexity, aging, dan lockout via login.defs dan PAM.
Password aging policy di /etc/login.defs
# Edit /etc/login.defs
sed -i 's/^PASS_MAX_DAYS.*/PASS_MAX_DAYS 90/' /etc/login.defs
sed -i 's/^PASS_MIN_DAYS.*/PASS_MIN_DAYS 7/' /etc/login.defs
sed -i 's/^PASS_WARN_AGE.*/PASS_WARN_AGE 14/' /etc/login.defs
# Terapkan ke user yang sudah ada (tidak otomatis untuk user lama)
chage -M 90 -m 7 -W 14 aldo
chage -l aldo # verifikasi
# Kunci akun otomatis setelah N hari tidak aktif (sejak password kadaluarsa)
useradd -D -f 30 # default untuk user baru
chage -I 30 aldo # atau per-user
# Audit semua user: cek yang tidak punya password expiry
awk -F: '{ print $1 }' /etc/shadow | while read user; do
exp=$(chage -l "$user" 2>/dev/null | grep "Maximum number" | awk '{print $NF}')
echo "$user: $exp"
donePAM — kompleksitas password
/etc/pam.d/common-password, RHEL gunakan /etc/pam.d/system-auth dan /etc/pam.d/password-auth.apt install libpam-pwquality -y # Debian/Ubuntu dnf install libpwquality -y # RHEL (sudah tersedia biasanya) # /etc/security/pwquality.conf cat > /etc/security/pwquality.conf << 'EOF' # Panjang minimum 14 karakter minlen = 14 # Minimal 3 dari 4 kelas karakter (upper, lower, digit, special) minclass = 3 # Maksimal 3 karakter yang sama berturut-turut maxrepeat = 3 # Maksimal 4 karakter berurutan (abc, 1234) maxsequence = 4 # Cek terhadap nama di kolom GECOS /etc/passwd gecoscheck = 1 # Cek terhadap dictionary words dictcheck = 1 # Cek terhadap username usercheck = 1 # Tolak jika password mirip password lama difok = 5 EOF # Debian — /etc/pam.d/common-password # Pastikan baris ini ada: # password requisite pam_pwquality.so retry=3 # RHEL — /etc/pam.d/system-auth dan password-auth # Ganti baris pam_pwquality.so dengan: # password requisite pam_pwquality.so try_first_pass local_users_only retry=3 authtok_type=
PAM — lockout akun setelah percobaan gagal
# pam_faillock: lock akun setelah N percobaan gagal # Debian — tambahkan ke /etc/pam.d/common-auth: # SEBELUM baris pam_unix.so # auth required pam_faillock.so preauth silent deny=5 unlock_time=900 # auth [success=1 default=bad] pam_unix.so # auth [default=die] pam_faillock.so authfail # auth sufficient pam_faillock.so authsucc # RHEL — /etc/security/faillock.conf (lebih modern, kernel 5+) cat > /etc/security/faillock.conf << 'EOF' deny = 5 unlock_time = 900 fail_interval = 900 even_deny_root root_unlock_time = 60 EOF # Cek status lockout user faillock --user aldo # Reset lockout manual faillock --user aldo --reset
Nonaktifkan akun dan shell yang tidak dibutuhkan
# Set shell /usr/sbin/nologin untuk akun sistem yang tidak perlu login
NOLOGIN_USERS="daemon bin sys sync games man lp mail news uucp nobody www-data backup operator list irc gnats"
for u in $NOLOGIN_USERS; do
id "$u" &>/dev/null && usermod -s /usr/sbin/nologin "$u" && echo "nologin: $u"
done
# Audit user dengan shell login aktif (seharusnya hanya admin manusia)
awk -F: '$7 ~ //(bash|sh|zsh|fish|ksh|csh)$/ { print $1, $7 }' /etc/passwd
# Kunci akun yang sudah tidak aktif
passwd -l olduser
usermod -e 1 olduser # set expiry ke epoch = kadaluarsa sekarang
# Cek user tanpa password (berbahaya!)
awk -F: '($2 == "" || $2 == "!") { print $1 }' /etc/shadowSELinux & AppArmor — Level Tinggi
Mandatory Access Control membatasi apa yang boleh dilakukan setiap proses, bahkan jika proses tersebut sudah dikompromis. SELinux untuk RHEL/Fedora, AppArmor untuk Debian/Ubuntu.
SELinux — RHEL / Rocky / Alma / Fedora
disabled. Jika ada masalah, gunakan permissive sementara untuk investigasi, lalu kembali ke enforcing. Menonaktifkan SELinux sepenuhnya membutuhkan reboot dan relabeling penuh.# Cek status sestatus getenforce # Enforcing / Permissive / Disabled # Set ke enforcing (berlaku langsung, tanpa reboot) setenforce 1 # Persistent — /etc/selinux/config sed -i 's/^SELINUX=.*/SELINUX=enforcing/' /etc/selinux/config # Buat permissive sementara untuk investigasi setenforce 0 # ... investigate ... setenforce 1 # Lihat denial terbaru ausearch -m avc -ts recent ausearch -m avc -ts recent | audit2why # Buat dan load policy custom dari denial ausearch -m avc -ts recent | audit2allow -M mypolicy semodule -i mypolicy.pp semodule -l | grep mypolicy # verifikasi # Context pada file ls -Z /etc/passwd # lihat SELinux context restorecon -Rv /var/www/html # restore context default chcon -t httpd_sys_content_t /srv/web # ubah context satu file
AppArmor — Debian / Ubuntu
apt install apparmor apparmor-utils apparmor-profiles -y # Cek status aa-status systemctl status apparmor # Set semua profil ke enforce mode aa-enforce /etc/apparmor.d/* # Lihat profil dalam complain mode (log tanpa blokir) aa-complain /etc/apparmor.d/usr.sbin.nginx # Update profil berdasarkan log (interaktif) aa-logprof # Lihat denial AppArmor grep "apparmor" /var/log/kern.log | grep DENIED | tail -20 grep "apparmor" /var/log/syslog | grep DENIED | tail -20 # Generate profil baru untuk aplikasi aa-genprof /usr/bin/myapp # ikuti wizard interaktif
Investigasi dan debug denial
# SELinux: gunakan sealert untuk analisis human-readable (RHEL) dnf install setroubleshoot-server -y sealert -a /var/log/audit/audit.log sealert -l "*" # semua alert # AppArmor: lihat log kernel dmesg | grep apparmor | grep DENIED # Test apakah suatu aksi akan diblokir # SELinux: sesearch --allow -s httpd_t -t var_log_t # cek aturan yang ada # AppArmor: cek dengan --dry-run apparmor_parser -T /etc/apparmor.d/usr.sbin.nginx
2FA, Rootkit & Audit CIS — Level Maksimum
Lapisan terakhir untuk lingkungan kritis: autentikasi multi-faktor, deteksi rootkit, audit benchmark CIS, dan monitoring aktif proses serta koneksi jaringan.
Two-Factor Authentication (TOTP) untuk SSH
apt install libpam-google-authenticator -y # Debian/Ubuntu dnf install google-authenticator-libpam -y # RHEL # Setup TOTP per user (jalankan sebagai user itu sendiri, BUKAN root) su - aldo google-authenticator # Ikuti prompt: pilih y untuk time-based, y untuk update .google_authenticator, # y untuk disallow multiple uses, n untuk 30-second window (atau y untuk toleransi lebih), # y untuk rate limiting. Scan QR code dengan Google Authenticator / Authy / etc. # SIMPAN emergency scratch codes! # Konfigurasi PAM — /etc/pam.d/sshd # Tambahkan di baris PERTAMA (sebelum @include): # auth required pam_google_authenticator.so nullok # Konfigurasi SSH — /etc/ssh/sshd_config # Ganti atau tambahkan: AuthenticationMethods publickey,keyboard-interactive KbdInteractiveAuthentication yes # Debian: ChallengeResponseAuthentication yes (flag lama) systemctl restart sshd # Test: login harus meminta key + TOTP code # ssh -p 2222 aldo@<server> → masukkan key → masukkan TOTP code
Rootkit scanner — rkhunter & chkrootkit
apt install rkhunter chkrootkit -y # Debian/Ubuntu dnf install rkhunter -y # RHEL (chkrootkit dari EPEL) # Setup rkhunter rkhunter --update # update database signatures rkhunter --propupd # simpan properti file sebagai baseline # Scan penuh rkhunter --check --sk --rwo # --sk: skip key prompts, --rwo: report warnings only rkhunter --check --sk 2>&1 | grep -E "Warning|Infected|Possible" # chkrootkit chkrootkit # scan semua chkrootkit lrk5 # scan rootkit spesifik # Jadwalkan scan mingguan cat > /etc/cron.d/rootkit-scan << 'EOF' MAILTO=admin@example.com 0 4 * * 0 root rkhunter --check --sk --rwo 2>&1 0 5 * * 0 root chkrootkit 2>&1 | grep -v "not infected" EOF
CIS Benchmark audit dengan Lynis
apt install lynis -y # Debian/Ubuntu dnf install lynis -y # RHEL (atau dari EPEL) # Full audit sistem lynis audit system # Output penting di akhir: # Hardening index: 67 [############# ] # Tests performed: 267 # Plugins enabled: 2 # Review rekomendasi lynis audit system 2>&1 | grep -E "^\[WARNING\]|Suggestion" cat /var/log/lynis.log | grep "SUGGESTION" cat /var/log/lynis-report.dat | grep "warning" # Detail test spesifik lynis show details AUTH-9262 # cek detail test PAM lynis show tests | grep AUTH # daftar semua test AUTH # Quick mode (lebih cepat, kurang detail) lynis audit system --quick
Monitoring proses dan koneksi aktif
# ─── Koneksi jaringan ─────────────────────────────────────────
ss -tulnp # semua listening ports + nama proses
ss -tnp state established # koneksi yang sedang aktif
lsof -i -P -n | grep LISTEN # listening processes via lsof
# Proses yang melakukan koneksi ke luar
lsof -i 4 -n -P | grep -v LISTEN
ss -tnp | awk 'NR>1 {print $5, $6}' | sort | uniq -c | sort -rn
# ─── Proses mencurigakan ─────────────────────────────────────
ps auxf # process tree dengan user
ps aux --sort=-%cpu | head -15 # top CPU consumers
ps aux --sort=-%mem | head -15 # top memory consumers
# Binary yang berjalan dari lokasi tidak biasa
ls -la /proc/*/exe 2>/dev/null | grep -v '/usr|/bin|/sbin|/lib|/opt'
# ─── Cron dan startup tersembunyi ────────────────────────────
crontab -l # cron user saat ini
cat /etc/crontab
ls -la /etc/cron.d/ /etc/cron.daily/ /etc/cron.weekly/
systemctl list-units --state=enabled --type=service # service aktif
# ─── File yang baru dimodifikasi ─────────────────────────────
find /etc /bin /sbin /usr/bin /usr/sbin -newer /etc/passwd -type f 2>/dev/null
find /tmp /dev/shm /var/tmp -type f -newer /proc/1 2>/dev/null # file baru di /tmpChecklist verifikasi akhir hardening
# ─── Ringkasan cek cepat — jalankan setelah hardening selesai ──
echo "=== 1. SSH ==="
sshd -T | grep -E "permitrootlogin|passwordauthentication|maxauthtries|port"
echo "=== 2. Firewall ==="
ufw status verbose 2>/dev/null || firewall-cmd --list-all 2>/dev/null
echo "=== 3. Fail2ban ==="
fail2ban-client status sshd 2>/dev/null
echo "=== 4. Listening ports ==="
ss -tulnp | grep LISTEN
echo "=== 5. Sysctl kritis ==="
sysctl kernel.randomize_va_space net.ipv4.tcp_syncookies kernel.dmesg_restrict
echo "=== 6. SUID files baru ==="
find / -perm /4000 -type f 2>/dev/null > /tmp/suid-now.txt
diff /root/suid-baseline.txt /tmp/suid-now.txt && echo "OK - tidak ada SUID baru"
echo "=== 7. Auditd ==="
systemctl is-active auditd
auditctl -l | wc -l
echo "=== 8. SELinux/AppArmor ==="
getenforce 2>/dev/null || aa-status --enabled 2>/dev/null && echo "MAC: aktif"
echo "=== 9. User dengan shell aktif ==="
awk -F: '$7 ~ //(bash|sh|zsh)$/ { print $1 }' /etc/passwd