Translated ['src/linux-hardening/privilege-escalation/docker-security/na

This commit is contained in:
Translator 2025-08-05 04:31:21 +00:00
parent 6940ba128b
commit 9713e0399f

View File

@ -4,9 +4,9 @@
## Informazioni di base
Il time namespace in Linux consente offset per namespace sugli orologi monotoni e di avvio del sistema. È comunemente usato nei container Linux per modificare la data/ora all'interno di un container e regolare gli orologi dopo il ripristino da un checkpoint o snapshot.
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.
## Lab:
## Laboratorio:
### Crea diversi Namespaces
@ -20,11 +20,11 @@ Montando una nuova istanza del filesystem `/proc` se utilizzi il parametro `--mo
<summary>Errore: bash: fork: Impossibile allocare memoria</summary>
Quando `unshare` viene eseguito senza l'opzione `-f`, si incontra 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:
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:
1. **Spiegazione del Problema**:
1. **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 (denominato processo "unshare") non entra nel nuovo namespace; solo i suoi processi figli lo fanno.
- 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 di `unshare`. 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.
@ -34,7 +34,7 @@ Quando `unshare` viene eseguito senza l'opzione `-f`, si incontra un errore a ca
3. **Soluzione**:
- Il problema può essere risolto utilizzando l'opzione `-f` con `unshare`. Questa opzione fa sì che `unshare` fork un nuovo processo dopo aver creato il nuovo namespace PID.
- Eseguire `%unshare -fp /bin/bash%` garantisce che il comando `unshare` 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 una normale allocazione PID.
- Eseguire `%unshare -fp /bin/bash%` garantisce che il comando `unshare` 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.
@ -59,4 +59,83 @@ sudo find /proc -maxdepth 3 -type l -name time -exec ls -l {} \; 2>/dev/null |
```bash
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 campo `linux.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ì:
```json
{
"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
1. **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.
2. **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.
3. **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. Preferisci `CLOCK_REALTIME` per i timestamp rilevanti per la sicurezza.
4. **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>
{{#include ../../../../banners/hacktricks-training.md}}