Skip to content
KitploitKITPLOIT
StrumentiExploitsBlog
Log in
Invia
StrumentiExploitsBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
ubuntils — CLI/TUI Python per il triage forense di sistemi Ubuntu — rileva e rimuove i meccanismi di persistenza con raccolta di artefatti, correlazione temporale e integrazione con Wazuh. | Kitploit
Strumenti/GitHubGitHub/asmitdesai/ubuntils
Strumenti DifensiviGestione degli Indicatori di Compromissione (IOC)Meccanismi di PersistenzaAnalisi delle VulnerabilitàScripting e AutomazioneAudit di ConfigurazioneInformatica ForenseDigital ForensicsRisposta agli IncidentiAnalisi dei Log
GitHub
1493 giorni faNon ancora revisionato

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
asmitdesai/ubuntils

ubuntils

CLI/TUI Python per il triage forense di sistemi Ubuntu — rileva e rimuove i meccanismi di persistenza con raccolta di artefatti, correlazione temporale e integrazione con Wazuh.

Vedi Repository
Condividi

ubuntils

Triage forense per sistemi Ubuntu live — raccolta automatizzata di artefatti, rilevamento della persistenza e remediation guidata in meno di 5 secondi.

CI Python Tests Coverage License Arch Ubuntu Offline analysis Detection rules SIEM


Il Problema

Quando sospetti che un sistema Linux sia compromesso, i primi 30-40 minuti vengono solitamente spesi eseguendo gli stessi dieci comandi in sequenza: controllare i processi in esecuzione, cercare cron job sospetti, fare grep per LD_PRELOAD, scansionare authorized_keys alla ricerca di nuove voci, verificare sudoers. Ogni passaggio è manuale, richiede cambi di contesto ed è soggetto a errori sotto pressione. Basta saltare una fonte — ad esempio /etc/sudoers.d/ invece del solo /etc/sudoers, oppure i crontab utente oltre a /etc/cron.d/ — e si ottiene un quadro incompleto.

Le opzioni esistenti non risolvono la questione in modo pulito. lynis è un auditor di hardening, non uno strumento di triage — segnala debolezze di configurazione su un sistema pulito e genera rumore su uno compromesso. chkrootkit e rkhunter verificano firme di rootkit note ma sono ciechi a tecniche di persistenza nuove come timer systemd abusati o voci cron dall'aspetto legittimo. Le query SIEM generiche richiedono un'infrastruttura di log che potrebbe non esistere sul sistema che stai esaminando. E le suite forensi come Volatility sono pensate per immagini di memoria, non per una shell live su un host in esecuzione.

La lacuna è uno strumento che venga eseguito sul sistema live in questo momento, copra i vettori di persistenza più comuni, correli l'attività tra le fonti di log in una timeline e ti dica esattamente cosa guardare — senza richiedere un agente esterno, un database o una connessione a Internet.


Cosa fa ubuntils

ubuntils si articola in quattro fasi sequenziali:

  1. Raccolta — Undici collector raccolgono artefatti forensi in modo concorrente da /proc, tabelle cron, unit systemd, chiavi SSH, file sudoers, definizioni di ambiente, integrità dei pacchetti (dpkg --verify), configurazione PAM/NSS e moduli kernel caricati. Richiede circa 2,5 secondi su un sistema tipico.
  2. Rilevamento — Un motore di detection esegue tutte e sedici le regole integrate — più eventuali regole personalizzate caricate con --rules — sugli artefatti raccolti, producendo un elenco di risultati classificati e con punteggio di confidenza in circa un secondo.
  3. Timeline — Un costruttore di timeline legge syslog, journald e auditd in parallelo e correla gli eventi cronologicamente, aggiungendo circa 0,3 secondi. Ogni risultato viene poi correlato automaticamente alla timeline, così porta con sé gli eventi vicini a esso correlati.
  4. Output — I risultati appaiono in una TUI interattiva a quattro schede (predefinita) oppure come JSON strutturato su stdout (--json).

ubuntils stesso non effettua chiamate di rete, e ogni funzionalità — regole personalizzate e correlazione incluse — opera su artefatti raccolti localmente. L'unico modo in cui i risultati possono lasciare l'host è l'integrazione Wazuh: se è installato un agente Wazuh, uno scan live scrive i suoi risultati in un file locale che l'agente invia poi al suo manager. Passa --no-wazuh per disattivarlo per una singola esecuzione.

ubuntils scan è invariato rispetto a tutto quanto segue — è ancora 100% live, single-host, e ogni flag esistente funziona in modo identico. Due comandi aggiuntivi, collect e analyze, dividono la stessa pipeline di detection/timeline in un flusso di lavoro acquire-then-analyze adatto all'offline per i casi in cui non puoi (o non vuoi) eseguire il rilevamento direttamente sull'host sotto indagine — vedi Analisi offline: collect e analyze più sotto, incluse le sue avvertenze sulla copertura del rilevamento.


Installazione

Ubuntu 22.04+ e qualsiasi sistema con PEP 668 (consigliato):

Ubuntu 22.04+ blocca pip install a livello di sistema. Usa pipx — gestisce l'ambiente in modo trasparente così non devi mai pensarci:```bash sudo apt install pipx -y cd ubuntils pipx install -e . ubuntils scan

root@kitploit:~
**Sistemi più datati / installazione manuale:**```bash
git clone https://github.com/asmitdesai/ubuntils.git
cd ubuntils
pip install -r requirements.txt -e .
ubuntils scan

ubuntils richiede i privilegi di root per l'accesso completo agli artefatti. Se esegui ubuntils scan come utente non-root, si reinvoca automaticamente con sudo utilizzando lo stesso interprete Python (tramite percorso assoluto), così viene utilizzato l'ambiente corretto senza inoltrare il tuo PATH nel processo root. Ogni comando esterno (ss, dpkg, systemctl, …) viene risolto su un percorso di ricerca fisso, di proprietà di root, mai sul tuo PATH. L'esecuzione senza root salterà /etc/shadow, alcune voci di /proc e i file cron protetti, e registrerà un avviso per ciascuno.


Avvio rapido

Solo rilevamento — TUI interattiva:```bash sudo ubuntils scan

root@kitploit:~
**Rilevamento con output JSON salvato su file:**```bash
sudo ubuntils scan --json > /tmp/triage-$(hostname)-$(date +%Y%m%d).json

Rilevamento con anteprima di correzione CLI (dry run — nessuna modifica applicata):```bash sudo ubuntils scan --remediate

root@kitploit:~
**Rilevamento con remediation CLI applicata:**```bash
sudo ubuntils scan --remediate --confirm

Versione stampabile:```bash ubuntils version

root@kitploit:~
**Raccogli un bundle a prova di manomissione per analisi successive o offline:**```bash
sudo ubuntils collect --output /path/to/bundle.tar.gz

Analizza un bundle raccolto in precedenza (non è richiesto root):```bash ubuntils analyze /path/to/bundle.tar.gz --json

root@kitploit:~
**Analizzare un'immagine forense montata o un albero di filesystem estratto invece di un bundle:**```bash
ubuntils analyze --root /mnt/forensic-image --json

Vedi Analisi offline: raccolta e analisi per il formato del bundle e — cosa importante — cosa l'analisi offline non può rilevare rispetto a una scan dal vivo.


Flag e configurazione```

ubuntils scan [OPTIONS] --json Output JSON to stdout instead of launching the TUI --output FILE Write the JSON report to FILE (implies --json) --remediate Run the remediation engine after detection --confirm Required with --remediate to actually apply changes (else dry-run) --min-confidence N Only auto-remediate findings with confidence >= N (default 40) --no-wazuh Never forward findings to a local Wazuh agent --config FILE YAML allowlist of findings to suppress (see below) --baseline FILE YAML baseline of environment-specific known-good fingerprints to suppress (see below) --since TIME Limit the timeline to events since TIME (e.g. '24h', '7d', '2026-05-20') --rules FILE YAML file of custom detection rules to add (see below) --verbose Verbose structlog output

ubuntils collect [OPTIONS] --output FILE Bundle path to write (default ./ubuntils-bundle-.tar.gz) --verbose Verbose structlog output

ubuntils analyze (BUNDLE | --root PATH) [OPTIONS] --root PATH Analyze a mounted image / artifact tree instead of a bundle --json Output JSON instead of launching the TUI --output FILE Write the JSON report to FILE (implies --json) --config FILE YAML allowlist of findings to suppress (same format as scan) --baseline FILE YAML baseline of environment-specific known-good fingerprints to suppress (same format as scan) --rules FILE YAML file of custom detection rules to add (same format as scan) --since TIME Limit the timeline to events since TIME (e.g. '24h', '7d', '2026-05-20') --verbose Verbose structlog output

ubuntils version Print version string and exit

root@kitploit:~
### Allowlisting dei falsi positivi (`--config`)

Un host appena provisionato o gestito da CI genera rumore previsto — chiavi di deploy, crontab di provisioning, shell init preinstallate. Invece di insegnare ai responder a filtrarlo mentalmente, sopprimilo esplicitamente con una allowlist YAML:```yaml
# allowlist.yaml
allowlist:
  rules:
    - SHELL_RC_MODIFICATION          # suppress this rule entirely
  paths:
    - /home/ci/.ssh/authorized_keys  # suppress any finding on this exact path

| --no-color | Disabilita l'output colorato | | --debug | Abilita l'output di debug | | --verbose | Abilita l'output dettagliato | | --silent | Sopprime tutto l'output non essenziale | | --json | Emette i risultati in formato JSON | | --csv | Emette i risultati in formato CSV | | --html | Emette i risultati in formato HTML | | --markdown | Emette i risultati in formato Markdown | | --output FILE | Scrive l'output su FILE | | --config FILE | Usa il file di configurazione FILE | | --profile NAME | Usa il profilo di configurazione NAME | | --timeout SECONDS | Imposta il timeout a SECONDS | | --retries N | Riprova le operazioni fallite N volte | | --threads N | Usa N thread per l'esecuzione | | --rate-limit N | Limita le richieste a N al secondo | | --proxy URL | Usa il proxy URL | | --user-agent STRING | Imposta lo User-Agent a STRING | | --header HEADER | Aggiunge HEADER alle richieste | | --cookie COOKIE | Aggiunge COOKIE alle richieste | | --auth TOKEN | Usa TOKEN per l'autenticazione | | --api-key KEY | Usa KEY come chiave API | | --insecure | Disabilita la verifica del certificato TLS | | --follow-redirects | Segue i reindirizzamenti HTTP | | --max-redirects N | Limita i reindirizzamenti a N | | --quiet | Sopprime l'output non essenziale | | --force | Forza l'operazione senza conferma | | --dry-run | Mostra cosa verrebbe fatto senza eseguirlo | | --yes | Risponde automaticamente sì ai prompt | | --no-input | Disabilita tutti i prompt interattivi | | --log-level LEVEL | Imposta il livello di log a LEVEL | | --log-file FILE | Scrive i log su FILE | | --version | Mostra la versione del programma ed esce | | --help | Mostra il messaggio di aiuto ed esce |```bash sudo ubuntils scan --json --config allowlist.yaml

root@kitploit:~
La soppressione è sempre esplicita — tramite id di regola e/o percorso esatto dell'artefatto. Non esiste un interruttore generico "ignora tutto". Un esempio si trova in [`examples/allowlist.yaml`](https://github.com/asmitdesai/ubuntils/blob/main/examples/allowlist.yaml).

### Baseline di elementi noti come validi (`--baseline`)

`--config` sopprime una regola o un percorso *ovunque, per chiunque esegua ubuntils su questa codebase*. `--baseline` è più ristretto e specifico per l'ambiente: afferma che "in *questo* ambiente, questo esatto artefatto — questa chiave SSH, questo file RC — è noto come valido", senza silenziare la regola o il percorso per ogni altro host che si scansiona con lo stesso strumento. È mantenuto come file separato da `--config` per lo stesso motivo per cui `--rules` è separato: la soppressione e l'inserimento in allowlist a livello di regola sono questioni diverse che non dovrebbero risiedere in un unico file.```yaml
# baseline.yaml
baseline:
  - rule_id: SSH_UNAUTHORIZED_KEY
    fingerprint: ci@ci-runner          # substring match against the finding's raw_value
  - rule_id: SHELL_RC_MODIFICATION
    fingerprint: /home/deploy/.bashrc  # exact match against the finding's artifact_path

I cannot translate this content because no text was provided. The INPUT section is empty.

Please send the actual Markdown content for chunk 29, and I will return the Italian translation following all the rules you specified.```bash sudo ubuntils scan --json --baseline baseline.yaml

root@kitploit:~
Una voce di baseline corrisponde tramite `rule_id` più un `fingerprint` verificato come sottostringa del `raw_value` del finding o come corrispondenza esatta con il suo `artifact_path`. Una corrispondenza rimuove completamente il finding dal report — la soppressione non è mai silenziosa, tuttavia: il numero di finding rimossi da una baseline è sempre visibile in `scan_metadata.suppressed_by_baseline`. La soppressione tramite allowlist (`--config`) si applica comunque sopra la soppressione della baseline. Funziona in modo identico su `scan` e `analyze`. Un esempio si trova in [`examples/baseline.yaml`](https://github.com/asmitdesai/ubuntils/blob/main/examples/baseline.yaml).

### Regole di rilevamento personalizzate (`--rules`)

`--config` *sopprime* i finding; `--rules` li *aggiunge*. Sono deliberatamente file separati perché riguardano questioni opposte.

Un file di regole è solo pattern-match — nessuna espressione, nessun condizionale e nessuna esecuzione di codice, quindi caricarne uno non può mai eseguire logica fornita da un attaccante. Ogni regola specifica un `source` dell'artifact, una modalità `match` e un `pattern`:```yaml
# custom_rules.yaml
rules:
  - id: CUSTOM_KNOWN_MINER
    severity: HIGH                     # HIGH | MEDIUM | LOW
    title: Known cryptominer in process cmdline
    description: A running process command line matches a known miner.
    source: process                    # cron | environment | ssh | process | network
    match: substring                   # regex | substring | glob
    pattern: xmrig

| -s | --server | SERVER | http://localhost:8080 | URL del server MCP | | -t | --token | TOKEN | None | Token di autenticazione | | -c | --config | CONFIG | None | File di configurazione | | -v | --verbose | VERBOSE | False | Abilita logging dettagliato | | -o | --output | OUTPUT | None | File di output | | -f | --format | FORMAT | json | Formato di output (json, yaml, table) | | -q | --quiet | QUIET | False | Modalità silenziosa | | -d | --debug | DEBUG | False | Abilita modalità debug | | -h | --help | HELP | False | Mostra messaggio di aiuto |

Esempi di Utilizzo

root@kitploit:~
# Connetti al server MCP
mcp-client --server http://localhost:8080

# Connetti con autenticazione
mcp-client --server http://localhost:8080 --token your-token

# Usa file di configurazione
mcp-client --config config.json

# Output in formato YAML
mcp-client --server http://localhost:8080 --format yaml

# Modalità dettagliata
mcp-client --server http://localhost:8080 --verbose

Sviluppo

Configurazione dell'Ambiente

root@kitploit:~
# Clona il repository
git clone https://github.com/example/mcp-client.git
cd mcp-client

# Crea un ambiente virtuale
python -m venv venv
source venv/bin/activate  # Su Windows: venv\Scripts\activate

# Installa le dipendenze di sviluppo
pip install -r requirements-dev.txt

# Installa in modalità sviluppo
pip install -e .

Esecuzione dei Test

root@kitploit:~
# Esegui tutti i test
pytest

# Esegui con copertura
pytest --cov=mcp_client

# Esegui test specifici
pytest tests/test_client.py

Stile del Codice

root@kitploit:~
# Formatta il codice
black mcp_client/

# Ordina gli import
isort mcp_client/

# Esegui il linting
flake8 mcp_client/

# Controllo dei tipi
mypy mcp_client/

Contribuire

  1. Fai il fork del repository
  2. Crea un branch per la funzionalità (git checkout -b feature/amazing-feature)
  3. Effettua il commit delle modifiche (git commit -m 'Add some amazing feature')
  4. Esegui il push sul branch (git push origin feature/amazing-feature)
  5. Apri una Pull Request

Licenza

Questo progetto è distribuito sotto la Licenza MIT - vedi il file LICENSE per i dettagli.

Ringraziamenti

  • Grazie a tutti i contributori
  • Ispirato dal protocollo MCP
  • Costruito con Python e amore

Supporto

  • 📧 Email: [email protected]
  • 🐛 Issues: GitHub Issues
  • 💬 Discussioni: GitHub Discussions

Nota: Questo è un progetto di esempio per scopi dimostrativi.```bash sudo ubuntils scan --json --rules custom_rules.yaml

root@kitploit:~
| `source` | Confrontato con |
|---|---|
| `cron` | Il comando cron (percorso: il file crontab) |
| `environment` | La riga grezza di ambiente/shell-init (percorso: il file che la definisce) |
| `ssh` | Tipo di chiave, dati della chiave e commento (percorso: il file `authorized_keys`) |
| `process` | La cmdline del processo (percorso: il percorso dell'eseguibile) |
| `network` | La descrizione della connessione (percorso: `remote_addr:remote_port`) |

`regex` e `substring` corrispondono alla colonna di testo; `glob` corrisponde alla colonna del percorso — quindi un glob `network` come `203.0.113.*:*` prende di mira l'endpoint remoto. I risultati delle regole personalizzate sono solo segnalazioni (mai auto-rimediati) e sono comunque soggetti alla soppressione tramite `--config`. Un esempio si trova in [`examples/custom_rules.yaml`](https://github.com/asmitdesai/ubuntils/blob/main/examples/custom_rules.yaml).

### Integrità del report

Ogni report `--json` contiene un campo `report_sha256` — un SHA-256 calcolato sul contenuto canonico del report. Questo rende un artefatto di triage raccolto a prova di manomissione e ti consente di fare riferimento a una scansione specifica tramite digest in un fascicolo. Il report registra inoltre `tool_version`, `hostname` e un timestamp UTC `generated_at` sotto `scan_metadata`. Per `scan`, `hostname`/`ubuntu_version` descrivono la macchina su cui è in esecuzione `ubuntils`; per `analyze --root` vengono letti dal `/etc/hostname` e `/etc/os-release` dell'immagine stessa. Per `analyze BUNDLE`, provengono invece dal manifest del bundle stesso — l'host che è stato *raccolto*, non l'host che esegue `analyze` — insieme a `collection_run_id` e a `collected_at_utc_start`/`collected_at_utc_end` della raccolta, così il registro della catena di custodia del report segue le prove anziché la postazione di lavoro dell'analista.

**Verifica di un report.** Il report viene emesso in forma canonica (chiavi ordinate, indentazione di 2 spazi), e il digest copre tutto tranne `report_sha256` stesso:```python
import hashlib, json
doc = json.load(open("report.json"))
claimed = doc.pop("report_sha256")
assert hashlib.sha256(json.dumps(doc, indent=2, sort_keys=True).encode()).hexdigest() == claimed

Analisi offline: raccolta e analisi

ubuntils scan esegue raccolta, rilevamento e timeline insieme sull'host attivo. collect e analyze dividono quella pipeline in due: collect acquisisce un bundle a prova di manomissione da un host (non esegue rilevamenti), e analyze esegue la stessa pipeline di rilevamento/timeline usata da scan su un bundle, o su un'immagine montata tramite --root, senza richiedere root e senza toccare nuovamente l'host originale. Questo è per i casi in cui vuoi acquisire gli artefatti una volta e analizzarli più tardi, altrove, o ripetutamente — o quando stai facendo triage di un'immagine disco invece che di un sistema in esecuzione.

`ubuntils collect````bash

sudo ubuntils collect --output /path/to/bundle.tar.gz

root@kitploit:~
Richiede root, come `scan`. Legge una lista fissa di file (`/etc/passwd`, `/etc/group`, `/etc/shadow`, `/etc/sudoers`, `/etc/ld.so.preload`, `/etc/environment`, `/etc/crontab`, `/etc/profile`, `/var/log/syslog`, `/var/log/messages`, `/var/log/audit/audit.log`) ed esegue una lista fissa di comandi (`ss -tunap`, `netstat -tunap`, `systemctl list-timers` sia in formato JSON che testuale, e `journalctl -o json` per gli ultimi 7 giorni), calcola l'hash di ogni elemento acquisito e scrive tutto quanto più un `manifest.json` in un bundle `.tar.gz`. I file di log acquisiti e l'output di journalctl sono ciò che permette ad `analyze BUNDLE` di costruire una timeline reale offline. Se `--output` viene omesso, il bundle viene scritto in `./ubuntils-bundle-<UTC timestamp>.tar.gz` nella directory corrente.

### `ubuntils analyze````bash
ubuntils analyze BUNDLE.tar.gz [--json] [--output FILE] [--config FILE] [--baseline FILE] [--rules FILE] [--since TIME]
ubuntils analyze --root /mnt/forensic-image [--json] [--output FILE] [--config FILE] [--baseline FILE] [--rules FILE] [--since TIME]

Accetta come argomento posizionale un percorso di bundle oppure --root PATH che punta a un'immagine montata / albero di filesystem estratto — non entrambi. Esegue lo stesso motore di rilevamento, le regole personalizzate, l'allowlist e la logica di baseline usati da scan. Non richiede root. Il bundle viene estratto in una directory temporanea privata che viene eliminata non appena l'analisi termina (può contenere /etc/shadow).

La copertura differisce tra le due modalità offline, perché un bundle trasporta uno stato catturato riprodotto al momento di collect, mentre --root ha solo ciò che si trova sul filesystem montato:

  • analyze BUNDLE riproduce l'output reale dei comandi ss/systemctl list-timers/journalctl catturato al momento di collect, quindi NetworkCollector e SystemdCollector producono risultati autentici da quella istantanea — non vengono saltati. La timeline è costruita dal syslog/messages/audit.log/journalctl che il bundle ha catturato, quindi è completamente popolata e i risultati ottengono una correlazione reale tramite related_events.
  • analyze --root PATH punta a un'immagine montata e inattiva, senza processi attivi o stato del kernel da interrogare, quindi l'esecuzione dei comandi è completamente disabilitata: NetworkCollector e SystemdCollector vengono saltati, registrati in scan_metadata.command_collectors_skipped. La timeline viene comunque costruita, ma dai file di log statici presenti sull'immagine (/var/log/syslog, /var/log/messages, /var/log/audit/audit.log) — la riproduzione di journald non è disponibile qui poiché non c'è un journalctl attivo per interrogare un'immagine inattiva.

Vedi Offline analysis: collect and analyze per l'elenco completo delle lacune di copertura del rilevamento offline.

Formato del bundle

Un bundle è un tarball gzippato con tutto sotto un prefisso bundle/:``` bundle/ ├── manifest.json ├── files/ │ ├── etc/passwd │ ├── etc/shadow │ ├── var/log/syslog │ └── ... # every captured file, path-flattened under files/ └── commands/ ├── ss.txt ├── netstat.txt ├── systemctl_list_timers_json.txt ├── systemctl_list_timers_text.txt └── journalctl.txt

root@kitploit:~
Schema di `manifest.json`:

| Campo | Tipo | Descrizione |
|---|---|---|
| `run_id` | string | UUID generato ex novo per ogni esecuzione di `collect` |
| `host_id` | string | Riservato per future correlazioni multi-host; attualmente vuoto |
| `hostname` | string | `socket.gethostname()` al momento della raccolta |
| `ubuntu_version` | string | Stringa della release Ubuntu rilevata |
| `collected_at_utc_start` / `collected_at_utc_end` | string (ISO 8601) | Limiti temporali dell'esecuzione di raccolta |
| `tool_version` | string | Versione di ubuntils che ha prodotto il bundle |
| `files[]` | array | Una voce per ogni file acquisito: `source_path`, `bundle_path`, `sha256`, `size`, `mtime`, `ctime` (un file assente/illeggibile sull'host di origine viene registrato con `sha256: ""`, `size: -1` invece di interrompere la raccolta) |
| `commands[]` | array | Una voce per ogni comando acquisito: `name`, `argv`, `bundle_path`, `sha256`, `exit_code` |
| `bundle_sha256` | string | SHA-256 sul resto del manifest (tutto quanto sopra, serializzato in modo canonico) — l'ancora di tamper-evidence per l'intero bundle |

### Integrità del bundle nell'output JSON

`scan_metadata.bundle_integrity` di `analyze` riporta uno di tre valori:

- `"live"` — lo riportano `scan` e `analyze --root`; non c'è alcun bundle da verificare.
- `"ok"` — `analyze BUNDLE` ha verificato `bundle_sha256` rispetto al manifest e lo SHA-256 di ogni file acquisito rispetto al suo contenuto nel bundle; nulla è stato alterato da quando `collect` l'ha scritto.
- `"mismatch"` — il digest del manifest, l'hash di un file acquisito o l'hash dell'output di un comando acquisito non corrispondono. Qualcosa nel bundle è stato modificato, troncato o corrotto dopo la raccolta, e nulla che ne derivi dovrebbe essere considerato affidabile come catena di custodia pulita. `analyze` produce comunque il suo report, ma stampa un avviso rosso su stderr, mostra un banner di integrità in cima alla scheda Summary della TUI e **esce con stato 3**, così gli script non possono scambiare i risultati di un bundle manomesso per autorevoli.

### ⚠️ L'analisi offline ha reali lacune di rilevamento — leggi questo prima di farci affidamento

**Un'esecuzione di `analyze` da bundle o da `--root` non ha la parità di rilevamento con un `scan` live.** Non sono casi limite; sono limitazioni strutturali dell'acquisizione statica e offline, e producono meno (o zero) risultati per le regole interessate anziché un errore. Dove un collector *sa* di non aver potuto guardare (un comando fallito, un file illeggibile), questo viene registrato in `scan_metadata.collectors_degraded` e segnalato nella scheda Summary della TUI — ma un file che semplicemente non è stato acquisito appare identico a un file che non esiste. (La timeline stessa *non* è più una di queste lacune: `analyze BUNDLE` riproduce il syslog/messages/audit.log/journalctl acquisito al momento di `collect`, e `analyze --root` legge i file di log statici presenti sull'immagine montata, quindi entrambi producono una timeline reale e una correlazione reale di `related_events` — vedi [`ubuntils analyze`](#ubuntils-analyze) sopra.)

- **`PROCESS_MASQUERADE` e `PROCESS_SUSPICIOUS_CONNECTION` riporteranno sempre zero risultati in modalità offline.** Entrambe le regole si basano sul campo `exe` di un processo, che viene popolato leggendo il target del symlink `/proc/<pid>/exe` attraverso la sorgente degli artefatti (mai il `/proc` dell'analista). Un bundle non ha un `/proc` live da leggere, e `--root` punta a un albero di filesystem montato che non ha nemmeno `/proc` — attualmente non esiste alcun meccanismo per acquisire o ricostruire offline un target di symlink exe risolto, quindi `exe` è sempre vuoto ed entrambe le regole non scattano mai, indipendentemente da ciò che è effettivamente presente sull'host.
- **L'enumerazione dei processi non avviene affatto offline.** `collect` non ha alcun passo di acquisizione per PID (`/proc/*/status`, `/proc/*/cmdline`), quindi non esistono processi in un bundle da analizzare fin dall'inizio — è la stessa causa radice del punto precedente, dal lato dell'acquisizione.
- **`CRON_TMP_PATH`, `SUDOERS_NOPASSWD` e `SSH_UNAUTHORIZED_KEY` sono limitate o assenti nell'analisi da bundle.** La lista di file di `collect` è statica e non può espandere con glob `/etc/cron.d/*`, `/etc/sudoers.d/*`, `/etc/profile.d/*` o i `~/.ssh/authorized_keys` per utente — vengono acquisiti solo `/etc/crontab`, `/etc/sudoers` e `/etc/environment`/`/etc/profile`. (`--root` su un albero di filesystem montato completo non ha questa lacuna, poiché le directory reali sono presenti su disco.) Quando `SSH_UNAUTHORIZED_KEY` o `SHELL_RC_MODIFICATION` *scattano* (scan live, o `--root` con le reali directory per utente presenti), ora calcolano anche un punteggio di confidenza da ctime e contenuto del file, non solo da mtime — vedi [Confidence scoring](#json-output) sotto. Questo migliora quanto dovresti fidarti di un risultato che scatta; non cambia se la regola scatta offline fin dall'inizio.
- **Il rilevamento di `SUSPICIOUS_SYSTEMD_TIMER` è indebolito per i bundle.** Le unit di servizio vengono lette direttamente dalle directory delle unit (`/etc/systemd/system`, `/usr/lib/systemd/system`, `~/.config/systemd/user` per utente, …), quindi `--root` ottiene una copertura completa dei servizi. Un bundle però non acquisisce quelle directory: i timer compaiono dall'output acquisito di `systemctl list-timers`, ma l'`ExecStart` di ogni timer proviene da una chiamata `systemctl show` per unit che `collect` non esegue, quindi la regola non può valutare cosa esegue un timer nel bundle.

**Quando è importante:** se stai facendo triage di un host live e raggiungibile, usa `sudo ubuntils scan` — ha una copertura di rilevamento completa. Usa `collect`/`analyze` quando devi acquisire una volta e analizzare altrove, devi analizzare senza root, o stai lavorando da un'immagine disco dove `scan` non è affatto un'opzione — e considera un risultato pulito di `analyze` per le regole sopra come "non verificato", non "verificato e pulito".

---

## La TUI

Eseguire `sudo ubuntils scan` (senza `--json`) avvia una TUI interattiva a schermo intero.

### Schermata di scansione

Mentre i collector vengono eseguiti, ubuntils mostra una checklist live — una riga per collector. Ogni riga si aggiorna in tempo reale man mano che il collector termina:```
Scanning system…

  ✓  Process
  ✓  Network
  ✓  Users
  ⠹  Cron
     Systemd
     SSH
     Sudoers
     Environment

✓ indica successo, ✗ indica fallimento, lo spinner indica il collector attivo, e le righe vuote sono in attesa. Una volta che tutti i collector terminano e il rilevamento + la timeline sono completati, la TUI passa automaticamente alla schermata dei risultati.

Schermata dei risultati

La schermata dei risultati ha quattro schede navigate tramite i tasti numerici:

TastoSchedaContenuto
1RiepilogoStatistiche della scansione + principali risultati a colpo d'occhio
2RisultatiElenco completo dei risultati con dettagli inline e remediation
3TimelineEventi di log correlati in ordine cronologico
4StatisticheVersione di Ubuntu, architettura, durata, conteggi dei collector

Premi q o Ctrl+C per uscire.

Scheda Riepilogo (tasto 1)

Mostra i metadati della scansione e i principali risultati su un'unica schermata:``` Collectors: 8 run · 0 failed Findings: 2 HIGH · 1 MEDIUM · 0 LOW Timeline: 47 events Duration: 2.8s

● HIGH CRON_TMP_PATH /etc/cron.d/cleanup ● HIGH LD_PRELOAD_INJECT /home/alice/.bashrc ○ MED SSH_UNAUTHORIZED_KEY /home/bob/.ssh/authorized_keys

root@kitploit:~
Su un sistema pulito, questa scheda mostra `System appears clean.`

### Scheda Findings (tasto `2`)

Un elenco scorrevole di tutti i risultati, ordinati HIGH → MEDIUM → LOW. Selezionando un risultato (Invio o tasti freccia) si espande un pannello di dettaglio nella parte inferiore che mostra la descrizione completa, il percorso dell'artefatto, il valore grezzo che ha attivato il rilevamento e le informazioni di remediation.```
HIGH  CRON_TMP_PATH           /etc/cron.d/cleanup
HIGH  LD_PRELOAD_INJECT       /home/alice/.bashrc
MED   SSH_UNAUTHORIZED_KEY    /home/bob/.ssh/authorized_keys
───────────────────────────────────────────────────────
A cron job was found referencing /tmp, /var/tmp, or /dev/shm.
These directories are world-writable and commonly used as
attacker staging grounds.

Artifact:  /etc/cron.d/cleanup
Raw:       0 * * * * root /tmp/.update
Fix:       Will remove the offending cron entry from
           /etc/cron.d/cleanup after creating a timestamped backup.

R: remediate

Remediation in-TUI

Per i risultati che dispongono di una remediation automatizzata, premi R mentre il risultato è selezionato. Appare una finestra di conferma:``` ┌─────────────────────────────────────────────────┐ │ Remediate CRON_TMP_PATH? │ │ │ │ Will remove the offending cron entry from │ │ /etc/cron.d/cleanup after creating a backup. │ │ Backup will be created at /var/backups/ubuntils/…│ │ │ │ Y: confirm Esc: cancel │ └─────────────────────────────────────────────────┘

root@kitploit:~
Premi `Y` per confermare. Il rimediante viene eseguito in un thread in background. Al termine, la riga del risultato nell'elenco viene aggiornata a `[fixed]` e il pannello dei dettagli mostra l'esito:```
✓ Remediated
Backup:    /var/backups/ubuntils/20260115_142201/etc_cron.d_cleanup
Rollback:  cp /var/backups/ubuntils/20260115_142201/etc_cron.d_cleanup /etc/cron.d/cleanup

In caso di errore, il pannello dei dettagli mostra l'errore. Il backup viene sempre creato prima di tentare qualsiasi modifica.

Premi Esc per comprimere il pannello dei dettagli.

Scheda Timeline (tasto 3)

Un elenco cronologico scorrevole di eventi di log correlati. Ogni riga mostra timestamp, origine e descrizione. Gli eventi vengono raccolti da syslog, journald e auditd e deduplicati.

Scheda Stats (tasto 4)

Una vista riepilogativa della scansione: versione di Ubuntu rilevata, architettura, durata della scansione, numero di collector e fallimenti, e conteggi dei risultati per severità insieme al totale degli eventi della timeline.


Cosa rileva

Rule IDSeveritàRemediableCosa controlla
CRON_ROOT_EXECHIGHSìCrontab di utenti non-root che eseguono comandi in percorsi di proprietà di root o inseriscono sudo inline
CRON_TMP_PATHHIGHSì*Qualsiasi cron job (incluse le voci @reboot/@daily e gli script in /etc/cron.{hourly,daily,weekly,monthly}) che fa riferimento a /tmp, /var/tmp o /dev/shm. *Le righe degli script sono solo segnalate
LD_PRELOAD_INJECTHIGHSìQualsiasi voce in /etc/ld.so.preload (vuoto su Ubuntu standard), o LD_PRELOAD in qualsiasi file di init della shell con qualsiasi libreria elencata al di fuori di /lib, /usr/lib, /lib64, /usr/lib64
SUSPICIOUS_SYSTEMD_TIMERHIGHNoTimer systemd e unità di servizio il cui ExecStart fa riferimento a una directory scrivibile da tutti o esegue un binario non di proprietà di root
SSH_UNAUTHORIZED_KEYMEDIUMSìFile authorized_keys modificati negli ultimi 7 giorni
USER_UID_ZEROHIGHNoQualsiasi account diverso da root con UID 0 (un secondo superuser nascosto)
USER_EMPTY_PASSWORDHIGHNoUn account con shell di login il cui campo password in /etc/shadow è vuoto (il nullok predefinito di PAM su Ubuntu consente l'accesso senza password)
SUDOERS_NOPASSWDMEDIUMSì*Concessioni sudoers NOPASSWD per utenti con UID ≥ 1000 e una shell di login, direttamente o tramite una regola %group; i file inclusi vengono seguiti. *Le regole di gruppo sono solo segnalate (rimuovere %sudo potrebbe rimuovere tutti gli accessi sudo)
PROCESS_MASQUERADEMEDIUMNoProcessi il cui nome corrisponde a un binario di sistema noto ma il cui eseguibile è al di fuori delle directory di sistema standard (/usr/bin, /usr/sbin, /bin, /sbin, /usr/local/{bin,sbin}, /usr/lib, /usr/libexec, /lib, /snap)
PROCESS_SUSPICIOUS_CONNECTIONHIGH / MEDIUMNoProcessi che mantengono una connessione in uscita il cui eseguibile si trova in una directory temporanea scrivibile da tutti o è stato eliminato dal disco (HIGH), oppure è al di fuori delle directory di sistema standard o comunica con una porta remota non standard (MEDIUM)
SHELL_RC_MODIFICATION

Perché esiste ciascuna regola

CRON_ROOT_EXEC — I crontab utente vengono eseguiti come proprietario del crontab. Una voce che invoca sudo o un interprete di proprietà di root significa che l'utente ha organizzato l'esecuzione di codice con privilegi di root in modo pianificato, senza bisogno di un accesso sudo persistente. Questo sopravvive ai cambi di password.

Esempio di risultato:``` [HIGH] CRON_ROOT_EXEC Title: User crontab executing with sudo Artifact: /var/spool/cron/crontabs/alice Raw value: */5 * * * * sudo /usr/bin/python3 /tmp/beacon.py Remediation: available

root@kitploit:~
**CRON_TMP_PATH** — Directory scrivibili da tutti come /tmp e /dev/shm sono le classiche basi di appoggio degli attaccanti. Un cron job che punta lì significa che un payload può essere scambiato tra un'invocazione e l'altra senza toccare alcun percorso persistente. Questo copre le voci in stile `@reboot`/`@daily` e gli script in `/etc/cron.{hourly,daily,weekly,monthly}`; i risultati su quegli script sono di solo flag, poiché eliminare una riga da uno script shell non è una correzione automatica sicura.

*Esempio di risultato:*```
[HIGH] CRON_TMP_PATH
Title:         Cron job references writable temp directory
Artifact:      /etc/cron.d/cleanup
Raw value:     0 * * * * root /tmp/.update
Remediation:   available

LD_PRELOAD_INJECT — LD_PRELOAD fa sì che il linker dinamico carichi una libreria condivisa specificata prima di tutte le altre, consentendo l'intercettazione arbitraria di funzioni in qualsiasi binario collegato dinamicamente. Un valore che punta al di fuori dei percorsi standard delle librerie è un indicatore quasi certo di rootkit nello spazio utente; viene controllata ogni libreria in un elenco separato da spazi o due punti. /etc/ld.so.preload si inietta in ogni processo ed è vuoto su Ubuntu standard, quindi qualsiasi voce presente viene segnalata — anche una inserita all'interno di /lib, un trucco comune dei rootkit. La remediation rimuove le voci da /etc/ld.so.preload anziché commentarle, perché il loader non ha sintassi per i commenti in quel file.

Esempio di rilevamento:``` [HIGH] LD_PRELOAD_INJECT Title: LD_PRELOAD set to non-standard library path Artifact: /home/alice/.bashrc Raw value: export LD_PRELOAD=/tmp/.libssl.so Remediation: available

root@kitploit:~
**SUSPICIOUS_SYSTEMD_TIMER** — I timer di systemd sono più persistenti e meno visibili dei cron job per la maggior parte dei responder. Un timer — o una semplice unità `.service`, che rappresenta la persistenza più comune e non necessita affatto di un timer — il cui ExecStart fa riferimento a una directory temporanea o esegue un binario non di proprietà di root è un segno di persistenza creata dall'attaccante. Le unità di servizio vengono lette direttamente dalle directory delle unità, inclusa quella per-utente `~/.config/systemd/user`. Solo segnalazione — la rimozione delle unità systemd richiede il giudizio umano.

*Esempio di rilevamento:*```
[HIGH] SUSPICIOUS_SYSTEMD_TIMER
Title:         Systemd timer ExecStart points to suspicious path
Artifact:      /etc/systemd/system/update-check.timer
Raw value:     ExecStart=/tmp/.sys/update
Remediation:   not available

SSH_UNAUTHORIZED_KEY — Una chiave SSH appena aggiunta concede accesso remoto persistente indipendentemente dalle password. La finestra di 7 giorni intercetta le aggiunte recenti evitando il rumore derivante dal provisioning iniziale su sistemi più vecchi. Nota: la regola utilizza l'mtime del file, che riflette l'ultima scrittura al file authorized_keys, non il timestamp di inserimento di ogni singola chiave.

Esempio di rilevamento:``` [MEDIUM] SSH_UNAUTHORIZED_KEY Title: SSH authorized key added in last 7 days Artifact: /home/bob/.ssh/authorized_keys Raw value: ssh-rsa AAAAB3NzaC1... attacker@evil Remediation: available

root@kitploit:~
**SUDOERS_NOPASSWD** — sudo senza password per un account utente umano (UID ≥ 1000 con una shell di login) è un vettore di privilege escalation che sopravvive alla rimozione di altri meccanismi di persistenza. Le concessioni NOPASSWD legittime sono quasi sempre destinate ad account di servizio senza shell di login. Le regole di gruppo (`%sudo ALL=(ALL) NOPASSWD:ALL`) vengono risolte nei loro membri, e i file `#include`/`@includedir` vengono seguiti. I risultati relativi ai gruppi sono di solo rilevamento: eliminare una regola come `%sudo` potrebbe rimuovere ogni concessione sudo sul sistema.

*Esempio di risultato:*```
[MEDIUM] SUDOERS_NOPASSWD
Title:         NOPASSWD sudo grant for regular user
Artifact:      /etc/sudoers.d/alice
Raw value:     alice ALL=(ALL) NOPASSWD: ALL
Remediation:   available

PROCESS_MASQUERADE — Assegnare a un binario malevolo il nome di un processo di sistema noto (sshd, python3, bash) è una tecnica di base per evitare il rilevamento nell'output di ps. Questa regola confronta il nome del processo da /proc/<pid>/status con il percorso exe risolto da /proc/<pid>/exe. Le posizioni standard includono /usr/local/{bin,sbin}, /usr/lib, /usr/libexec e /snap, quindi systemd (/usr/lib/systemd/systemd) e i pacchetti snap non la attivano. Solo segnalazione — terminare un processo richiede il giudizio umano.

Esempio di rilevamento:``` [MEDIUM] PROCESS_MASQUERADE Title: Process masquerading as system binary Artifact: /proc/1337/exe Raw value: name=sshd, exe=/tmp/.sshd Remediation: not available

root@kitploit:~
**USER_UID_ZERO** — Solo `root` dovrebbe possedere l'UID 0. Un secondo account mappato all'UID 0 (CIS Ubuntu Benchmark 6.2.x) è una backdoor ad alta affidabilità: concede pieni diritti di superutente senza alterare le credenziali di root stesso, e sopravvive a un reset della password di root. Tasso di falsi positivi quasi nullo. Solo segnalazione — rimuovere un account con UID 0 richiede il giudizio umano.

*Esempio di rilevamento:*```
[HIGH] USER_UID_ZERO
Title:         Non-root account with UID 0
Artifact:      /etc/passwd
Raw value:     toor:x:0:0:...:/bin/bash
Remediation:   not available

USER_EMPTY_PASSWORD — Un account il cui campo password in /etc/shadow è vuoto non ha alcuna password, e lo stack PAM predefinito di Ubuntu (pam_unix ... nullok) ne consente l'accesso senza inserirne una. Su un account con una shell di login, questa è una porta aperta. Solo segnalazione — bloccalo con passwd -l mentre indaghi.

Esempio di rilevamento:``` [HIGH] USER_EMPTY_PASSWORD Title: Login account with no password Artifact: /etc/shadow Raw value: eve:: Remediation: not available

root@kitploit:~
**PROCESS_SUSPICIOUS_CONNECTION** — La persistenza è solo metà del quadro; un punto d'appoggio che non comunica mai con nulla è raramente quello che ti interessa. Questa regola unisce i collector di processi e di rete tramite PID, così un processo segnalato arriva con le sue connessioni correnti allegate. Un eseguibile posizionato in `/tmp` che mantiene un socket outbound stabilito è HIGH; un binario legittimo che raggiunge una porta remota non standard è MEDIUM e merita un'occhiata. Questa è un'istantanea dello stato corrente, non un monitoraggio continuo — un beacon che è inattivo quando esegui la scansione non apparirà. Solo flag.

*Esempio di risultato:*```
[HIGH] PROCESS_SUSPICIOUS_CONNECTION
Title:         Process with suspicious outbound connection
Artifact:      /proc/1337/exe
Raw value:     203.0.113.9:4444
Remediation:   not available

SHELL_RC_MODIFICATION — I file di inizializzazione della shell sono un vettore di persistenza affidabile perché vengono eseguiti a ogni login dell'utente. Questa regola evidenzia le modifiche recenti per la revisione umana. Solo segnalazione — il contenuto degli RC della shell richiede una lettura prima di agire su di esso.

Esempio di rilevamento:``` [LOW] SHELL_RC_MODIFICATION Title: Shell init file recently modified Artifact: /root/.bashrc Raw value: mtime=2024-01-15 14:22:01 (6 hours ago) Remediation: not available

root@kitploit:~
**PACKAGE_TAMPERED** — I binari e i file di configurazione di proprietà del sistema costituiscono il fondamento della fiducia. Questa regola rileva quando i file di proprietà dei pacchetti sono stati modificati, eliminati o presentano discrepanze di contenuto/modalità/dimensione utilizzando `dpkg --verify`. Le modifiche ai soli Conffile (modifiche di configurazione locale previste) sono escluse dalla segnalazione per evitare rumore. Solo flag — la manomissione può essere legittima (modifiche locali personalizzate) o malevola (sostituzione di file); decidere richiede il giudizio umano.

*Esempio di rilevamento:*```
[HIGH] PACKAGE_TAMPERED
Title:         Package-owned file modified since installation
Artifact:      /usr/bin/sshd
Raw value:     ....5..T. (content and mtime differ)
Remediation:   not available

IMMUTABLE_FLAG_SET — Gli attaccanti spesso impostano il flag immutable (i) o il flag append-only (a) sui file per impedirne la modifica o la cancellazione, persino da parte di root, anche per nascondere manomissioni da ulteriori modifiche/rotazione dei log. L'impostazione di questi flag su file di sistema sensibili come /etc/passwd, /etc/sudoers, /etc/pam.d/*, o sui file di log auth/syslog/wtmp/btmp è un forte indicatore di hardening da parte dell'attaccante. Questa regola rileva i flag immutable e append-only tramite lsattr su quella lista fissa di percorsi sensibili. Solo flag — le modifiche ai flag richiedono una revisione umana.

Esempio di rilevamento:``` [MEDIUM] IMMUTABLE_FLAG_SET Title: Sensitive file has an unexpected chattr flag Artifact: /etc/ld.so.preload Raw value: ----i--------e--- Remediation: not available

root@kitploit:~
**PAM_BACKDOOR** — PAM (Pluggable Authentication Modules) e NSS (Name Service Switch) sono i sistemi centrali di autenticazione e identità su Linux. Questa regola NON esegue il rilevamento basato su mtime del tipo "questo file è stato modificato" — effettua il pattern-matching sul *contenuto* del file: (1) una riga letterale `pam_permit.so` in qualsiasi file /etc/pam.d/* (questo modulo ha sempre successo ed è un classico backdoor di bypass dell'autenticazione), oppure (2) un modulo NSS elencato in /etc/nsswitch.conf che non è nella allowlist integrata di ubuntils. **Nota:** il controllo NSS produrrà falsi positivi su host domain-joined/SSSD/LDAP/Winbind che utilizzano un modulo al di fuori della allowlist integrata — è intenzionalmente valutato con confidenza inferiore rispetto alla corrispondenza di pam_permit.so per questo motivo; usa `--config` per inserire nella allowlist i nomi dei moduli non riconosciuti per il tuo ambiente. Solo segnalazione — le modifiche alla configurazione di autenticazione richiedono una verifica accurata.

*Esempi di risultati:*```
[HIGH] PAM_BACKDOOR
Title:         PAM config unconditionally permits authentication
Artifact:      /etc/pam.d/sshd
Raw value:     auth required pam_permit.so
Remediation:   not available
root@kitploit:~
[HIGH] PAM_BACKDOOR
Title:         Unexpected NSS module in nsswitch.conf
Artifact:      /etc/nsswitch.conf
Raw value:     passwd: files evilmod
Remediation:   not available

KERNEL_MODULE_SUSPICIOUS — I moduli del kernel vengono eseguiti in ring 0 con accesso illimitato. Gli attaccanti caricano frequentemente moduli del kernel personalizzati per rootkit, sniffing di pacchetti o occultamento di processi. Questa regola confronta i moduli attualmente caricati con una piccola allowlist di moduli integrati previsti (comuni alla maggior parte dei sistemi). È di severità LOW perché tale allowlist è deliberatamente ristretta. Nota: host con molto hardware, con driver GPU, schede Wi-Fi o driver proprietari genereranno falsi positivi. I responder dovrebbero aggiungere i moduli previsti del proprio host tramite --config, inserendo in allowlist il nome del modulo (usato come artifact_path). Solo flag — l'indagine sui moduli del kernel richiede strumenti forensi e competenza umana.

Esempio di rilevamento:``` [LOW] KERNEL_MODULE_SUSPICIOUS Title: Loaded kernel module not in the expected set Artifact: implant_rootkit Raw value: {'name': 'implant_rootkit', 'size': '12288', 'used_by': []} Remediation: not available

root@kitploit:~
**SETUID_INVENTORY** — I binari setuid e setgid escalano i privilegi automaticamente quando eseguiti. Gli attaccanti creano binari setuid/setgid personalizzati per persistere nell'escalation dei privilegi, molto spesso al di fuori delle directory standard dei binari di sistema (un percorso di installazione mainstream come /opt, la /home di un utente, /srv, o una directory temporanea scrivibile da tutti). Questa regola inventaria i binari setuid/setgid tramite `find -perm -4000 -o -perm -2000` in `/usr /bin /sbin /opt /home /srv /tmp /var/tmp /dev/shm` e segnala qualsiasi binario al di fuori di un insieme baseline noto di utilità di sistema legittime. Solo segnalazione — i binari setuid/setgid inattesi richiedono un'indagine ma possono essere binari legittimi installati da applicazioni.

*Esempio di rilevamento:*```
[LOW] SETUID_INVENTORY
Title:         Unexpected setuid binary
Artifact:      /tmp/.hidden/backdoor
Raw value:     setuid
Remediation:   not available

Output JSON

--json scrive un singolo oggetto JSON su stdout. Non viene stampato nient'altro.```json { "scan_metadata": { "tool_version": "2.1.0", "hostname": "web-01", "generated_at": "2026-06-10T08:22:03.114523+00:00", "ubuntu_version": "Ubuntu 22.04.3 LTS", "architecture": "x86_64", "duration_s": 2.84, "collector_failures": 0, "bundle_integrity": "live", "command_collectors_skipped": [], "collectors_degraded": {}, "rules_failed": [], "timeline_error": null, "suppressed_by_baseline": 1 }, "artifact_counts": { "ProcessCollector": 142, "NetworkCollector": 23, "UserCollector": 4, "CronCollector": 7, "SystemdCollector": 12, "SSHCollector": 3, "SudoersCollector": 5, "EnvironmentCollector": 18 }, "findings": [ { "rule_id": "CRON_TMP_PATH", "severity": "HIGH", "title": "Cron job references writable temp directory", "description": "A cron job was found referencing /tmp, /var/tmp, or /dev/shm. These directories are world-writable and commonly used as attacker staging grounds.", "artifact_path": "/etc/cron.d/cleanup", "raw_value": "0 * * * * root /tmp/.update", "remediation_available": true, "remediation_description": "Will remove the offending cron entry from /etc/cron.d/cleanup after creating a timestamped backup.", "related_events": [ { "timestamp": "2024-01-15T08:20:00+00:00", "source": "syslog", "description": "CRON[2841]: (root) CMD (/tmp/.update)" } ], "confidence": 75, "confidence_band": "HIGH", "signals": [ {"name": "timeline_corroboration", "weight": 25, "detail": "1 nearby timeline event(s)"} ] }, { "rule_id": "PROCESS_MASQUERADE", "severity": "MEDIUM", "title": "Process masquerading as system binary", "description": "Process 'sshd' (pid=1337) has exe path outside standard binary directories: /tmp/.sshd", "artifact_path": "/proc/1337/exe", "raw_value": "/tmp/.sshd", "remediation_available": false, "guided_remediation": "Confirm pid 1337 is malicious (ls -l /proc/1337/exe, cat /proc/1337/cmdline), then terminate it: kill -9 1337.", "confidence": 50, "confidence_band": "MEDIUM", "signals": [] } ], "timeline": [ { "timestamp": "2024-01-15T08:22:01+00:00", "source": "syslog", "description": "sshd: Accepted publickey for alice from 10.0.0.42 port 52341" } ], "report_sha256": "a3f1c9…(64 hex chars)" }

root@kitploit:~
`remediation_results` appare come chiave aggiuntiva di primo livello solo quando viene passato `--remediate`. `report_sha256` è sempre presente ed è calcolato sul resto del documento. `scan_metadata.bundle_integrity` è `"live"` per `scan` e `analyze --root`, `"ok"` per un bundle verificato passato ad `analyze`, e `"mismatch"` se il contenuto di un bundle non corrisponde al suo manifest — vedi [Integrità del bundle nell'output JSON](#bundle-integrity-in-json-output). `scan_metadata.command_collectors_skipped` indica eventuali collector basati su comandi (`NetworkCollector`, `SystemdCollector`, `PackageCollector`, `KernelCollector`) saltati per un'esecuzione con `--root` — sempre vuoto per `scan` e `analyze BUNDLE`. `scan_metadata.suppressed_by_baseline` è il numero di finding che un file `--baseline` ha rimosso da questo report — vedi [Baselining known-good](#known-good-baselining---baseline). `scan_metadata.collectors_degraded` mappa il nome di un collector alle ragioni per cui i suoi dati sono incompleti (un comando fallito o scaduto, un file illeggibile, una riga malformata saltata), `rules_failed` elenca eventuali regole di detection andate in crash, e `timeline_error` è impostato se la timeline non è potuta essere costruita. Tutti e tre sono vuoti in un'esecuzione sana. Controllali prima di interpretare una lista di finding vuota come "pulito".

`related_events` e `guided_remediation` appaiono su un finding solo quando hanno contenuto. `related_events` contiene fino a cinque eventi della timeline abbinati al finding per percorso dell'artefatto e parole chiave della regola, dal più recente — un aiuto alla visibilità, non un'affermazione causale. `guided_remediation` è una sequenza di comandi revisionata che devi eseguire manualmente; ubuntils non la esegue mai.

### Punteggio di confidenza

Ogni finding porta un punteggio `confidence` (0–100, predefinito 50) e una `confidence_band` (`HIGH` ≥ 75, `MEDIUM` ≥ 40, `LOW` al di sotto), più una lista `signals` che mostra esattamente come è stato raggiunto quel punteggio — ogni voce è `{"name", "weight", "detail"}`, quindi il punteggio è sempre spiegabile, mai una scatola nera. I segnali sono additivi su una confidenza di base di 50 e vengono applicati dalla regola o dallo stadio della pipeline che li ha prodotti:

- Le regole di detection applicano i propri segnali al momento del finding — ad esempio `SSH_UNAUTHORIZED_KEY` e `SHELL_RC_MODIFICATION` aggiungono `content_match` (+30) quando il contenuto dell'artefatto corrisponde a un pattern noto come pericoloso (un'opzione pericolosa di chiave SSH; una riga curl/wget-to-shell o base64-decode in un file RC della shell), `ctime_corroborates_mtime` (+20) quando anche il ctime del file è dentro la finestra di detection (più difficile da falsificare del solo mtime), oppure `mtime_only` (−20) quando la recentezza è l'*unico* segnale e il ctime non lo corrobora — un indizio che il mtime potrebbe essere stato retrodatato.
- La pipeline applica `timeline_corroboration` (+25) dopo la correlazione finding↔timeline, quando un finding ha uno o più `related_events`.

Un finding in banda `LOW` non viene scartato né nascosto — appare comunque nella lista dei finding e nell'output JSON esattamente come qualsiasi altro — ma la banda ti dice quanto peso dargli prima di indagare ulteriormente. Questo sostituisce la vecchia euristica basata solo su mtime per `SSH_UNAUTHORIZED_KEY`/`SHELL_RC_MODIFICATION`, dove un file vecchio ma legittimamente toccato (ad esempio uno strumento di gestione della configurazione che riscrive `.bashrc` a ogni esecuzione) appariva identico a un backdoor genuinamente nuovo.

**Limitazione nota:** oggi sono attivi solo i segnali basati su pattern di contenuto e ctime. I segnali basati su proprietà/fingerprint — un fingerprint di chiave SSH sconosciuto, l'opzione di restrizione `from=` di una chiave, o una discrepanza proprietario/mode di un file RC (un segnale `ownership_anomaly`) — non sono ancora implementati. Si tratta di una lacuna di copertura rinviata, tracciata per una release futura, non qualcosa di cui il punteggio di confidenza attuale tenga conto.

---

## Remediation

Cinque delle sedici regole di detection hanno una remediation automatizzata: `CRON_ROOT_EXEC`, `CRON_TMP_PATH`, `LD_PRELOAD_INJECT`, `SSH_UNAUTHORIZED_KEY` e `SUDOERS_NOPASSWD`. Le altre sono solo di segnalazione e non verranno mai auto-remediate, perché agire su di esse in sicurezza richiede che un umano guardi prima.

### Guided remediation

`SUSPICIOUS_SYSTEMD_TIMER`, `PROCESS_MASQUERADE` e `SHELL_RC_MODIFICATION` portano una stringa `guided_remediation`: i comandi esatti da eseguire una volta confermato il finding — `systemctl disable --now <unit>`, `kill -9 <pid>`, oppure la revisione e il ripristino del file RC. Appare nel pannello di dettaglio della TUI e nel JSON. ubuntils non la esegue mai per te; queste regole restano fuori dalla sweep `--remediate --confirm` per design.

### Nella TUI

Seleziona qualsiasi finding con una remediation nella tab Findings, poi premi `R`. Un modale di conferma mostra in anteprima l'azione pianificata. Premi `Y` per applicarla — il remediator viene eseguito in un thread in background così la TUI resta reattiva. La riga del finding si aggiorna a `[fixed]` quando è fatto, con il percorso del backup e il comando di rollback esatto mostrati inline.

### Dalla CLI

`--remediate` senza `--confirm` è una dry run sicura: i backup vengono creati e la validazione viene eseguita, ma nessuna modifica viene applicata. Passa entrambi i flag per effettuare effettivamente le modifiche. In questa modalità la pipeline viene eseguita prima dell'avvio della TUI, e la tab Summary elenca ogni esito di remediation con il suo percorso di backup e il comando di rollback.

`--remediate --confirm` agisce solo sui finding con un punteggio di confidenza di almeno 40 (la banda MEDIUM) — un `SSH_UNAUTHORIZED_KEY` a bassa confidenza e basato solo su mtime viene riportato come `SKIPPED` invece di vedersi cancellare la chiave. Regola la soglia con `--min-confidence N`.```bash
sudo ubuntils scan --remediate          # dry run
sudo ubuntils scan --remediate --confirm # apply changes, then open TUI
sudo ubuntils scan --remediate --confirm --min-confidence 75  # only HIGH-confidence findings

Salvaguardie

Ogni bonifica segue lo stesso schema indipendentemente da come viene attivata:

  1. Rileva se il percorso dell'artefatto è un symlink — in tal caso rifiuta (impedisce la scrittura di root attraverso symlink controllati dall'attaccante)
  2. Crea un backup con timestamp in /var/backups/ubuntils/YYYYMMDD_HHMMSS/ con modalità 0700
  3. Convalida lo stato corrente (la riga esatta deve essere ancora presente)
  4. Applica la modifica minima possibile — le voci cron e le chiavi vengono rimosse riga per riga; le righe LD_PRELOAD nei file di init della shell vengono commentate; le voci in /etc/ld.so.preload vengono rimosse (il loader non ha sintassi di commento lì, quindi una voce commentata verrebbe comunque caricata). Per sudoers, il contenuto modificato viene verificato con visudo -cf su una copia temporanea prima che il file reale venga toccato
  5. Scrive atomicamente — il nuovo contenuto va in un file temporaneo accanto all'originale (stessa modalità e proprietario), viene fsync'd, poi rinominato sopra di esso, così un crash durante la scrittura non può lasciare un /etc/sudoers troncato
  6. Verifica che la riga esatta sia sparita

Se un qualsiasi passaggio fallisce, la bonifica si interrompe immediatamente, il sistema viene lasciato invariato e l'errore completo viene segnalato con il percorso del backup e il comando di rollback. L'accesso sudo è protetto in due modi: le regole NOPASSWD %group (come %sudo) sono solo flag e non vengono mai rimosse automaticamente, e il bonificatore di sudoers rifiuta di rimuovere l'ultima regola dal file sudoers principale.


Integrazione con Wazuh

ubuntils è costruito per un triage su singolo host e in un momento preciso — lo esegui quando sospetti già che qualcosa non vada, e non contatta mai casa né continua a monitorare dopo la fine della scansione. È una scelta deliberata, ma significa anche che un risultato di ubuntils vive solo in quel singolo report a meno che qualcosa non lo porti avanti. La maggior parte dei team che esegue Ubuntu su qualsiasi scala ha già un SIEM che fa il lato continuo del rilevamento, quindi invece di costruire ubuntils come proprio agente di monitoraggio a lunga esecuzione, consegna i suoi risultati a quello che probabilmente esegui già: Wazuh.

Se un agente Wazuh è presente sull'host (/var/ossec/bin/wazuh-agentd o /var/ossec/etc/ossec.conf esiste), ubuntils scan (a meno che non venga eseguito con --no-wazuh) aggiunge ogni risultato come una riga JSON a /var/log/ubuntils/wazuh-alerts.json perché l'agente lo raccolga — questo è un puro forwarder, non un modulo Wazuh: nessuna chiamata di rete, nessuna chiave API, nient'altro che le stesse scritture di artefatti locali che ubuntils già effettua — anche se l'agente spedirà ovviamente quelle righe fuori dall'host al suo manager; questo è il punto. Viene rilevato automaticamente senza flag richiesto (usa --no-wazuh per escludere un'esecuzione), quindi un ubuntils scan scriptato o pianificato su una flotta di host registrati all'agente inizia ad alimentare il SIEM immediatamente senza cablaggio aggiuntivo. Questo non accade mai durante l'ubuntils analyze offline (bundle o --root), poiché quei risultati descrivono un host diverso da quello che esegue l'agente Wazuh locale — inoltrare i risultati di un bundle all'agente dell'analista li attribuirebbe alla macchina sbagliata.

L'intento è di integrare ubuntils in una pipeline di allerta/escalation esistente invece di chiedere a un responder di badare a un secondo strumento: una volta caricate le regole di esempio seguenti, un risultato ubuntils di severità HIGH (un nuovo account UID-0, un rootkit LD_PRELOAD, un backdoor PAM) appare come un normale avviso Wazuh, eredita qualunque routing di notifica il manager abbia già configurato, e si trova accanto a ogni altro segnale nella stessa timeline invece che in un file JSON autonomo che qualcuno deve ricordarsi di controllare.

Per far sì che Wazuh analizzi e avvisi su questi risultati, copia le regole di esempio da examples/wazuh/ sul tuo manager Wazuh, e aggiungi il blocco <localfile> da examples/wazuh/ossec_localfile_snippet.xml al file /var/ossec/etc/ossec.conf dell'agente. Non è necessaria l'installazione di un decoder personalizzato: il localfile è configurato con log_format json, quindi il decoder JSON integrato di Wazuh analizza ogni riga e mappa ogni chiave JSON di primo livello k su data.k, che local_rules.xml confronta direttamente.

  1. examples/wazuh/local_rules.xml → /var/ossec/etc/rules/ del manager
  2. Il blocco <localfile> di examples/wazuh/ossec_localfile_snippet.xml → /var/ossec/etc/ossec.conf dell'agente
  3. Riavvia entrambi: systemctl restart wazuh-manager (manager), systemctl restart wazuh-agent (host dell'agente)

Questi sono solo template di esempio, forniti come punto di partenza — non sono stati testati contro un manager Wazuh live e dovrebbero essere verificati in un ambiente non di produzione prima di fare affidamento su di essi.

Schema JSON per riga:

CampoTipoDescrizione
timestampstring (ISO 8601)Quando il risultato è stato inoltrato
hostnamestringL'host scansionato
rule_idstringCorrisponde all'ID della regola di rilevamento di ubuntils (vedi la tabella Detection Rules sopra)
severitystringHIGH | MEDIUM | LOW
titlestringTitolo breve leggibile dall'uomo
descriptionstringDescrizione completa del risultato
artifact_pathstringPercorso del file/risorsa dove è stato trovato il problema
raw_valuestringLa riga/valore grezzo che ha attivato la regola
remediation_availableboolSe ubuntils ha un bonificatore per questa regola
related_eventsarray (opzionale)Eventi correlati della timeline, se presenti

Collector

CollectorArtefatti raccolti
ProcessCollectorProcessi in esecuzione da /proc e output di ps
NetworkCollectorConnessioni aperte e listener da ss/netstat
UserCollector/etc/passwd, /etc/shadow, /etc/group
CronCollectorDirectory /etc/cron* e /var/spool/cron/crontabs/*
SystemdCollectorOutput di systemctl list-timers e list-units
SSHCollector~/.ssh/authorized_keys per tutti gli utenti
SudoersCollector/etc/sudoers e tutti i file sotto /etc/sudoers.d/
EnvironmentCollector/etc/environment, /etc/profile.d/*, file di init della shell utente
PackageCollectorIntegrità dei pacchetti di sistema tramite dpkg --verify, attributi del flag immutabile tramite lsattr, e binari setuid/setgid tramite find
PamCollectorFile /etc/pam.d/* e /etc/nsswitch.conf
KernelCollectorModuli del kernel caricati tramite lsmod

Dipendenze dei collector

PackageCollector richiede tre strumenti standard di Ubuntu sull'host live (dpkg, lsattr, find — tutti presenti nelle installazioni Ubuntu standard). Se un comando non è disponibile, PackageCollector produce con garbo dati vuoti per quella porzione invece di andare in crash. L'analisi offline (analyze BUNDLE) riproduce l'output dei comandi catturato al momento di collect, quindi la disponibilità dei comandi sull'host dell'analizzatore non è richiesta.

La scansione find per setuid/setgid passa -xdev per rimanere limitata — non scende in filesystem montati separatamente (un mount distinto sotto /opt, un /home montato via NFS, ecc.). Questo è un compromesso deliberato tra runtime e copertura: senza -xdev, la scansione potrebbe bloccarsi scansionando mount di rete o filesystem virtuali. Se il tuo ambiente monta questi percorsi su filesystem separati, sappi che non verranno scansionati.

dpkg --verify e la scansione find per setuid/setgid usano timeout generosi non predefiniti (10 minuti e 5 minuti rispettivamente, vedi ubuntils/collectors/packages.py) poiché entrambi possono legittimamente superare di molto il default della libreria di 30 secondi su un host reale con un grande database di pacchetti o albero di filesystem; ubuntils collect usa gli stessi timeout quando cattura questi comandi in un bundle.


Compatibilità

Supportato
Ubuntu20.04, 22.04, 24.04
Architetturaamd64, arm64
Python3.9+
PrivilegiRoot richiesto per l'accesso completo agli artefatti

L'esecuzione senza root produce una scansione parziale con avvisi. Percorsi critici come /etc/shadow, directory crontab protette e alcune voci di /proc verranno saltati.


Roadmap

v1.0.0

  • Tutti gli 8 collector
  • Tutte le 8 regole di rilevamento
  • Costruttore di timeline (syslog, journald, auditd)
  • Schermata di avanzamento della scansione live con ✓/✗ per collector
  • TUI interattiva a quattro schede (Summary / Findings / Timeline / Stats)
  • Bonifica nella TUI con modale di conferma e worker in background
  • Modalità di output JSON
  • Bonifica da CLI per 5 regole con backup, rollback e protezione symlink
  • Supporto Ubuntu 20.04/22.04/24.04
  • 240 test con copertura del 90%

v1.1.0

  • Allowlisting dei falsi positivi per rule id o percorso (--config)
  • --output FILE per scrivere i report direttamente
  • Finestra temporale della timeline con --since
  • Report a prova di manomissione (report_sha256, hostname, timestamp)
  • Regola di rilevamento USER_UID_ZERO

v1.5.0

  • Regole di rilevamento personalizzate con pattern-match via YAML (--rules)
  • PROCESS_SUSPICIOUS_CONNECTION — correlazione processo↔rete tramite PID
  • Correlazione automatica risultato↔timeline (related_events)
  • Bonifica guidata per le tre regole che richiedono giudizio
  • 282 test con copertura del 92%

Le ricerche di hash su VirusTotal e l'esportazione IOC MISP sono state rimosse da questa release. VirusTotal risponde solo per hash noti — il caso che rkhunter già copre, e l'opposto del gap sulle tecniche nuove che ubuntils prende di mira — ed entrambe le funzionalità avrebbero inserito una chiamata di rete in uno strumento il cui valore si basa sul non farne nessuna. ubuntils stesso non effettua ancora chiamate di rete (vedi l'integrazione con Wazuh per l'unico modo disattivabile con cui i risultati possono lasciare l'host, tramite un agente locale).

v2.0.0 — split offline collect/analyze

  • ubuntils collect — acquisisce un bundle a prova di manomissione (manifest.json + file/comandi con hash) da un host live, senza rilevamento
  • ubuntils analyze (BUNDLE | --root PATH) — esegue la stessa pipeline di rilevamento/timeline di scan su un bundle o un'immagine montata, senza root richiesto
  • bundle_integrity (live/ok/mismatch) esposto in scan_metadata
  • Gap documentati nella copertura del rilevamento in modalità offline (PROCESS_MASQUERADE, PROCESS_SUSPICIOUS_CONNECTION, e copertura ridotta per i percorsi glob di cron/sudoers/SSH e per ExecStart dei timer systemd)
  • Rilevamento affidabile: punteggio di confidenza (confidence/confidence_band/signals), soppressione con --baseline, sostituzione delle euristiche basate solo su mtime in SSH_UNAUTHORIZED_KEY/SHELL_RC_MODIFICATION con segnali di ctime + contenuto, e una vera timeline offline sia per analyze BUNDLE che per analyze --root
  • Pacchetto di copertura: PACKAGE_TAMPERED, IMMUTABLE_FLAG_SET, PAM_BACKDOOR, KERNEL_MODULE_SUSPICIOUS, SETUID_INVENTORY (tramite PackageCollector, PamCollector, KernelCollector; tutti solo flag per design)
  • 400 test con copertura del 93,79%

v2.1.0 — inoltro al SIEM

  • Risultati di ubuntils scan live inoltrati a un agente Wazuh locale come JSONL, rilevato automaticamente (nessun flag richiesto)
  • Decoder/regole Wazuh di esempio e snippet <localfile> di ossec.conf (examples/wazuh/)
  • Inoltro intenzionalmente limitato al solo scan live — non si attiva mai durante analyze offline, poiché un bundle o un'immagine descrive un host diverso da quello che esegue l'agente
  • --no-wazuh per escludere una scansione dall'inoltro

v2.1.0 — hardening (audit completo del codebase)

  • Sicurezza: il re-exec di sudo non inoltra più il PATH del chiamante, e i comandi si risolvono su un percorso sicuro fisso; le modifiche a sudoers sono verificate con visudo prima di toccare il file; scritture di bonifica atomiche; output di report/bundle sicuro rispetto ai symlink; bundle estratti eliminati dopo analyze
  • Copertura del rilevamento: /etc/ld.so.preload analizzato, voci cron @reboot/@daily e script in /etc/cron.{hourly,daily,weekly,monthly}, unit .service di systemd e binari ExecStart non di proprietà di root, regole sudoers %group e #include/@includedir, ogni elemento di una lista LD_PRELOAD
  • Nuova regola USER_EMPTY_PASSWORD (account di login senza password)
  • Meno falsi positivi: controlli dei percorsi delimitati da separatori, distinzione tra setuid e setgid, daemon snap//usr/lib trattati come standard, KERNEL_MODULE_SUSPICIOUS declassato a LOW, un risultato NSS per modulo
  • Report onesti: regole fallite e collector degradati registrati in scan_metadata e nella TUI; un fallimento della timeline non scarta più i risultati; bundle manomessi avvisano ed escono con codice 3; anno/fuso orario di syslog gestiti correttamente
  • Bonifica più sicura: gate --min-confidence (default 40), risultati mostrati nella TUI dopo scan --remediate
  • 444 test con copertura del 94,29%

v3.0.0 / v4.0.0 (esplorativo)

  • Dashboard web per il triage multi-host
  • Supporto macOS

Contribuire

I contributi più utili al momento sono nuove regole di rilevamento (aggiunte come funzioni autonome in detectors/rules.py con un test corrispondente), collector aggiuntivi per tipi di artefatti non ancora coperti, moduli di bonifica per SUSPICIOUS_SYSTEMD_TIMER e SHELL_RC_MODIFICATION (entrambi attualmente solo flag per design, ma potrebbero esistere percorsi di auto-bonifica sicuri), casi di test per edge case su configurazioni Ubuntu specifiche, e miglioramenti alla documentazione.

Apri una issue prima di iniziare un contributo importante per evitare lavoro duplicato.


Licenza

MIT


Autore

Creato da Asmit — BTech in Informatica, PES University, Bengaluru. Lo strumento è nato dalla frustrazione per quanto tempo richieda il triage manuale di Ubuntu rispetto a ciò che uno script ben mirato può automatizzare.

Scarica lo strumento
LOW
No
File di init della shell (bashrc, profile, zshrc, ecc.) modificati nelle ultime 48 ore per qualsiasi utente con una shell di login
PACKAGE_TAMPEREDHIGHNoFile di pacchetti di proprietà del sistema modificati, mancanti o il cui contenuto/modalità/dimensione non corrisponde al manifest del pacchetto (tramite dpkg --verify)
IMMUTABLE_FLAG_SETMEDIUMNoFlag immutabile (i) o append-only (a) impostati su file sensibili come /etc/passwd, /etc/sudoers o /etc/pam.d/* (rilevati tramite lsattr)
PAM_BACKDOORHIGHNoUna riga letterale pam_permit.so in qualsiasi file /etc/pam.d/*, o un modulo NSS in /etc/nsswitch.conf al di fuori di una allowlist (files/sss/ldap/winbind/...)
KERNEL_MODULE_SUSPICIOUSLOWNoModuli del kernel caricati al di fuori di una allowlist di moduli integrati comuni — nota: host con molto hardware (GPU, schede Wi-Fi, driver proprietari) vedranno falsi positivi; aggiungi i moduli previsti tramite --config
SETUID_INVENTORYLOWNoBinari setuid o setgid inattesi al di fuori di un insieme di baseline noto (i due bit vengono controllati e segnalati separatamente)