Time Namespace
Reading time: 7 minutes
tip
Impara e pratica il hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP:
HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos github.
Informazioni di base
Il time namespace in Linux consente offset per namespace sugli orologi monotoni e di avvio del sistema. È comunemente usato nei contenitori Linux per modificare la data/ora all'interno di un contenitore e regolare gli orologi dopo il ripristino da un checkpoint o snapshot.
Laboratorio:
Crea diversi Namespaces
CLI
sudo unshare -T [--mount-proc] /bin/bash
Montando una nuova istanza del filesystem /proc se utilizzi il parametro --mount-proc, garantisci che il nuovo namespace di mount abbia una visione accurata e isolata delle informazioni sui processi specifiche per quel namespace.
Errore: bash: fork: Impossibile allocare memoria
Quando unshare viene eseguito senza l'opzione -f, si verifica un errore a causa del modo in cui Linux gestisce i nuovi namespace PID (Process ID). I dettagli chiave e la soluzione sono delineati di seguito:
- Spiegazione del problema:
- Il kernel Linux consente a un processo di creare nuovi namespace utilizzando la chiamata di sistema
unshare. Tuttavia, il processo che avvia la creazione di un nuovo namespace PID (chiamato "processo unshare") non entra nel nuovo namespace; solo i suoi processi figli lo fanno. - Eseguire
%unshare -p /bin/bash%avvia/bin/bashnello stesso processo diunshare. Di conseguenza,/bin/bashe i suoi processi figli si trovano nel namespace PID originale. - Il primo processo figlio di
/bin/bashnel nuovo namespace diventa PID 1. Quando questo processo termina, attiva la pulizia del namespace se non ci sono altri processi, poiché PID 1 ha il ruolo speciale di adottare processi orfani. Il kernel Linux disabiliterà quindi l'allocazione PID in quel namespace.
- Conseguenza:
- L'uscita di PID 1 in un nuovo namespace porta alla pulizia del flag
PIDNS_HASH_ADDING. Questo provoca il fallimento della funzionealloc_pidnell'allocare un nuovo PID durante la creazione di un nuovo processo, producendo l'errore "Impossibile allocare memoria".
- Soluzione:
- Il problema può essere risolto utilizzando l'opzione
-fconunshare. Questa opzione fa sì cheunsharefork un nuovo processo dopo aver creato il nuovo namespace PID. - Eseguire
%unshare -fp /bin/bash%garantisce che il comandounsharestesso diventi PID 1 nel nuovo namespace./bin/bashe i suoi processi figli sono quindi contenuti in modo sicuro all'interno di questo nuovo namespace, prevenendo l'uscita prematura di PID 1 e consentendo l'allocazione normale dei PID.
Assicurandoti che unshare venga eseguito con il flag -f, il nuovo namespace PID viene mantenuto correttamente, consentendo a /bin/bash e ai suoi subprocessi di operare senza incontrare l'errore di allocazione della memoria.
Docker
docker run -ti --name ubuntu1 -v /usr:/ubuntu1 ubuntu bash
Controlla in quale namespace si trova il tuo processo
ls -l /proc/self/ns/time
lrwxrwxrwx 1 root root 0 Apr 4 21:16 /proc/self/ns/time -> 'time:[4026531834]'
Trova tutti i namespace di tempo
sudo find /proc -maxdepth 3 -type l -name time -exec readlink {} \; 2>/dev/null | sort -u
# Find the processes with an specific namespace
sudo find /proc -maxdepth 3 -type l -name time -exec ls -l {} \; 2>/dev/null | grep <ns-number>
Entra all'interno di un Time namespace
nsenter -T TARGET_PID --pid /bin/bash
Manipulating Time Offsets
A partire da Linux 5.6, due orologi possono essere virtualizzati per ogni namespace temporale:
CLOCK_MONOTONICCLOCK_BOOTTIME
I loro delta per namespace sono esposti (e possono essere modificati) attraverso il file /proc/<PID>/timens_offsets:
$ sudo unshare -Tr --mount-proc bash # -T creates a new timens, -r drops capabilities
$ cat /proc/$$/timens_offsets
monotonic 0
boottime 0
Il file contiene due righe - una per orologio - con l'offset in nanosecondi. I processi che detengono CAP_SYS_TIME nella time namespace possono cambiare il valore:
# advance CLOCK_MONOTONIC by two days (172 800 s)
echo "monotonic 172800000000000" > /proc/$$/timens_offsets
# verify
$ cat /proc/$$/uptime # first column uses CLOCK_MONOTONIC
172801.37 13.57
Se hai bisogno che l'orologio a muro (CLOCK_REALTIME) cambi, devi comunque fare affidamento su meccanismi classici (date, hwclock, chronyd, …); non è namespaced.
unshare(1) helper flags (util-linux ≥ 2.38)
sudo unshare -T \
--monotonic="+24h" \
--boottime="+7d" \
--mount-proc \
bash
Le opzioni lunghe scrivono automaticamente i delta scelti in timens_offsets subito dopo la creazione dello spazio dei nomi, risparmiando un echo manuale.
Supporto OCI e Runtime
- La OCI Runtime Specification v1.1 (Nov 2023) ha aggiunto un tipo di spazio dei nomi
timededicato e il campolinux.timeOffsetsin modo che i motori dei container possano richiedere la virtualizzazione del tempo in modo portabile. - runc >= 1.2.0 implementa quella parte della specifica. Un frammento minimo di
config.jsonappare così:
{
"linux": {
"namespaces": [
{"type": "time"}
],
"timeOffsets": {
"monotonic": 86400,
"boottime": 600
}
}
}
Poi esegui il container con runc run <id>.
NOTA: runc 1.2.6 (Feb 2025) ha corretto un bug "exec into container with private timens" che poteva portare a un blocco e potenziale DoS. Assicurati di essere su ≥ 1.2.6 in produzione.
Considerazioni sulla sicurezza
- Capacità richiesta – Un processo ha bisogno di CAP_SYS_TIME all'interno del suo spazio dei nomi utente/tempo per cambiare gli offset. Rimuovere quella capacità nel container (predefinito in Docker e Kubernetes) previene manomissioni.
- Nessuna modifica dell'orologio – Poiché
CLOCK_REALTIMEè condiviso con l'host, gli attaccanti non possono falsificare le scadenze dei certificati, la scadenza dei JWT, ecc. tramite timens da solo. - Evasione di log / rilevamento – Il software che si basa su
CLOCK_MONOTONIC(ad es. limitatori di velocità basati sul tempo di attività) può essere confuso se l'utente dello spazio dei nomi regola l'offset. PreferisciCLOCK_REALTIMEper i timestamp rilevanti per la sicurezza. - Superficie di attacco del kernel – Anche con
CAP_SYS_TIMErimosso, il codice del kernel rimane accessibile; mantieni l'host aggiornato. Linux 5.6 → 5.12 ha ricevuto molteplici correzioni di bug timens (NULL-deref, problemi di segno).
Checklist di indurimento
- Rimuovi
CAP_SYS_TIMEnel profilo predefinito del runtime del tuo container. - Tieni aggiornati i runtime (runc ≥ 1.2.6, crun ≥ 1.12).
- Fissa util-linux ≥ 2.38 se fai affidamento sugli helper
--monotonic/--boottime. - Audita il software nel container che legge uptime o CLOCK_MONOTONIC per la logica critica per la sicurezza.
Riferimenti
- man7.org – Pagina del manuale degli spazi dei nomi temporali: https://man7.org/linux/man-pages/man7/time_namespaces.7.html
- Blog OCI – "OCI v1.1: nuovi spazi dei nomi time e RDT" (15 Nov 2023): https://opencontainers.org/blog/2023/11/15/oci-spec-v1.1
tip
Impara e pratica il hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP:
HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos github.
HackTricks