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/bash
nello stesso processo diunshare
. Di conseguenza,/bin/bash
e i suoi processi figli si trovano nel namespace PID originale. - Il primo processo figlio di
/bin/bash
nel 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_pid
nell'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
-f
conunshare
. Questa opzione fa sì cheunshare
fork un nuovo processo dopo aver creato il nuovo namespace PID. - Eseguire
%unshare -fp /bin/bash%
garantisce che il comandounshare
stesso diventi PID 1 nel nuovo namespace./bin/bash
e 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_MONOTONIC
CLOCK_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
time
dedicato e il campolinux.timeOffsets
in 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.json
appare 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_REALTIME
per i timestamp rilevanti per la sicurezza. - Superficie di attacco del kernel – Anche con
CAP_SYS_TIME
rimosso, 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_TIME
nel 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.