Χρονικό Namespace
Reading time: 7 minutes
tip
Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Ελέγξτε τα σχέδια συνδρομής!
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.
Βασικές Πληροφορίες
Το χρονικό namespace στο Linux επιτρέπει για ανά namespace offsets στους συστήματος μονοτονικούς και χρόνους εκκίνησης ρολόγια. Χρησιμοποιείται συνήθως σε κοντέινερ Linux για να αλλάξει την ημερομηνία/ώρα εντός ενός κοντέινερ και να ρυθμίσει τα ρολόγια μετά την αποκατάσταση από ένα checkpoint ή snapshot.
Εργαστήριο:
Δημιουργία διαφορετικών Namespaces
CLI
sudo unshare -T [--mount-proc] /bin/bash
Με την τοποθέτηση μιας νέας παρουσίας του συστήματος αρχείων /proc
αν χρησιμοποιήσετε την παράμετρο --mount-proc
, διασφαλίζετε ότι το νέο namespace τοποθέτησης έχει μια ακριβή και απομονωμένη άποψη των πληροφοριών διαδικασίας που είναι συγκεκριμένες για αυτό το namespace.
Σφάλμα: bash: fork: Cannot allocate memory
Όταν εκτελείται το unshare
χωρίς την επιλογή -f
, προκύπτει ένα σφάλμα λόγω του τρόπου που το Linux χειρίζεται τα νέα PID (Process ID) namespaces. Οι βασικές λεπτομέρειες και η λύση περιγράφονται παρακάτω:
- Εξήγηση Προβλήματος:
- Ο πυρήνας του Linux επιτρέπει σε μια διαδικασία να δημιουργεί νέα namespaces χρησιμοποιώντας την κλήση συστήματος
unshare
. Ωστόσο, η διαδικασία που ξεκινά τη δημιουργία ενός νέου PID namespace (αναφερόμενη ως η διαδικασία "unshare") δεν εισέρχεται στο νέο namespace; μόνο οι παιδικές της διαδικασίες το κάνουν. - Η εκτέλεση
%unshare -p /bin/bash%
ξεκινά το/bin/bash
στην ίδια διαδικασία με τοunshare
. Ως εκ τούτου, το/bin/bash
και οι παιδικές του διαδικασίες βρίσκονται στο αρχικό PID namespace. - Η πρώτη παιδική διαδικασία του
/bin/bash
στο νέο namespace γίνεται PID 1. Όταν αυτή η διαδικασία τερματίσει, ενεργοποιεί την καθαριότητα του namespace αν δεν υπάρχουν άλλες διαδικασίες, καθώς το PID 1 έχει τον ειδικό ρόλο της υιοθέτησης ορφανών διαδικασιών. Ο πυρήνας του Linux θα απενεργοποιήσει στη συνέχεια την κατανομή PID σε αυτό το namespace.
- Συνέπεια:
- Η έξοδος του PID 1 σε ένα νέο namespace οδηγεί στον καθαρισμό της σημαίας
PIDNS_HASH_ADDING
. Αυτό έχει ως αποτέλεσμα τη αποτυχία της συνάρτησηςalloc_pid
να κατανοήσει ένα νέο PID κατά τη δημιουργία μιας νέας διαδικασίας, παράγοντας το σφάλμα "Cannot allocate memory".
- Λύση:
- Το πρόβλημα μπορεί να επιλυθεί χρησιμοποιώντας την επιλογή
-f
με τοunshare
. Αυτή η επιλογή κάνει τοunshare
να δημιουργήσει μια νέα διαδικασία μετά τη δημιουργία του νέου PID namespace. - Η εκτέλεση
%unshare -fp /bin/bash%
διασφαλίζει ότι η εντολήunshare
γίνεται PID 1 στο νέο namespace. Το/bin/bash
και οι παιδικές του διαδικασίες είναι στη συνέχεια ασφαλώς περιεχόμενες μέσα σε αυτό το νέο namespace, αποτρέποντας την πρόωρη έξοδο του PID 1 και επιτρέποντας την κανονική κατανομή PID.
Διασφαλίζοντας ότι το unshare
εκτελείται με την επιλογή -f
, το νέο PID namespace διατηρείται σωστά, επιτρέποντας στο /bin/bash
και τις υπο-διαδικασίες του να λειτουργούν χωρίς να αντιμετωπίζουν το σφάλμα κατανομής μνήμης.
Docker
docker run -ti --name ubuntu1 -v /usr:/ubuntu1 ubuntu bash
Έλεγχος σε ποιο namespace βρίσκεται η διαδικασία σας
ls -l /proc/self/ns/time
lrwxrwxrwx 1 root root 0 Apr 4 21:16 /proc/self/ns/time -> 'time:[4026531834]'
Βρείτε όλα τα Time namespaces
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>
Είσοδος σε ένα Χρονικό namespace
nsenter -T TARGET_PID --pid /bin/bash
Manipulating Time Offsets
Αρχίζοντας με το Linux 5.6, δύο ρολόγια μπορούν να εικονικοποιηθούν ανά χρονικό namespace:
CLOCK_MONOTONIC
CLOCK_BOOTTIME
Οι διαφορές τους ανά namespace εκτίθενται (και μπορούν να τροποποιηθούν) μέσω του αρχείου /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
Το αρχείο περιέχει δύο γραμμές – μία ανά ρολόι – με την απόκλιση σε νανοδευτερόλεπτα. Οι διεργασίες που κατέχουν CAP_SYS_TIME στο χρονικό namespace μπορούν να αλλάξουν την τιμή:
# 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
Αν χρειάζεστε το ρολόι τοίχου (CLOCK_REALTIME
) να αλλάξει επίσης, πρέπει ακόμα να βασιστείτε σε κλασικούς μηχανισμούς (date
, hwclock
, chronyd
, …); δεν είναι ονοματοδοτημένο.
unshare(1)
helper flags (util-linux ≥ 2.38)
sudo unshare -T \
--monotonic="+24h" \
--boottime="+7d" \
--mount-proc \
bash
Οι μακροχρόνιες επιλογές γράφουν αυτόματα τις επιλεγμένες δέλτα στο timens_offsets
αμέσως μετά τη δημιουργία του namespace, αποθηκεύοντας μια χειροκίνητη echo
.
OCI & Υποστήριξη Runtime
- Η OCI Runtime Specification v1.1 (Νοέμβριος 2023) πρόσθεσε έναν ειδικό τύπο namespace
time
και το πεδίοlinux.timeOffsets
ώστε οι μηχανές κοντέινερ να μπορούν να ζητούν εικονικοποίηση χρόνου με φορητό τρόπο. - runc >= 1.2.0 υλοποιεί αυτό το μέρος της προδιαγραφής. Ένα ελάχιστο τμήμα
config.json
φαίνεται ως εξής:
{
"linux": {
"namespaces": [
{"type": "time"}
],
"timeOffsets": {
"monotonic": 86400,
"boottime": 600
}
}
}
Στη συνέχεια, εκτελέστε το κοντέινερ με runc run <id>
.
ΣΗΜΕΙΩΣΗ: runc 1.2.6 (Φεβρουάριος 2025) διόρθωσε ένα σφάλμα "exec into container with private timens" που θα μπορούσε να οδηγήσει σε κρέμασμα και πιθανό DoS. Βεβαιωθείτε ότι είστε σε ≥ 1.2.6 στην παραγωγή.
Σκέψεις ασφαλείας
- Απαιτούμενη ικανότητα – Μια διαδικασία χρειάζεται CAP_SYS_TIME μέσα στο namespace χρήστη/χρόνου της για να αλλάξει τις μετατοπίσεις. Η αφαίρεση αυτής της ικανότητας στο κοντέινερ (προεπιλογή στο Docker & Kubernetes) αποτρέπει την παραχάραξη.
- Καμία αλλαγή ρολογιού – Επειδή το
CLOCK_REALTIME
μοιράζεται με τον κεντρικό υπολογιστή, οι επιτιθέμενοι δεν μπορούν να παραποιήσουν τις διάρκειες πιστοποιητικών, την λήξη JWT, κ.λπ. μέσω timens μόνο. - Αποφυγή ανίχνευσης / καταγραφής – Λογισμικό που βασίζεται στο
CLOCK_MONOTONIC
(π.χ. περιοριστές ρυθμού βασισμένοι σε χρόνο λειτουργίας) μπορεί να μπερδευτεί αν ο χρήστης του namespace ρυθμίσει τη μετατόπιση. Προτιμήστε τοCLOCK_REALTIME
για χρονικές σφραγίδες που σχετίζονται με την ασφάλεια. - Επιφάνεια επίθεσης πυρήνα – Ακόμα και με την αφαίρεση του
CAP_SYS_TIME
, ο κώδικας του πυρήνα παραμένει προσβάσιμος. Κρατήστε τον κεντρικό υπολογιστή ενημερωμένο. Το Linux 5.6 → 5.12 έλαβε πολλές διορθώσεις σφαλμάτων timens (NULL-deref, ζητήματα υπογραφής).
Λίστα ελέγχου σκληροποίησης
- Αφαιρέστε το
CAP_SYS_TIME
στο προεπιλεγμένο προφίλ runtime του κοντέινερ σας. - Κρατήστε τα runtimes ενημερωμένα (runc ≥ 1.2.6, crun ≥ 1.12).
- Κλειδώστε το util-linux ≥ 2.38 αν βασίζεστε στους βοηθούς
--monotonic/--boottime
. - Ελέγξτε το λογισμικό εντός του κοντέινερ που διαβάζει uptime ή CLOCK_MONOTONIC για κρίσιμη λογική ασφαλείας.
Αναφορές
- man7.org – Σελίδα εγχειριδίου για τα Time namespaces: https://man7.org/linux/man-pages/man7/time_namespaces.7.html
- OCI blog – "OCI v1.1: νέοι χρόνοι και RDT namespaces" (15 Νοεμβρίου 2023): https://opencontainers.org/blog/2023/11/15/oci-spec-v1.1
tip
Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Ελέγξτε τα σχέδια συνδρομής!
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.