User Namespace

Reading time: 8 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

Basic Information

Ένα user namespace είναι μια δυνατότητα του πυρήνα Linux που παρέχει απομόνωση των αντιστοιχίσεων ID χρηστών και ομάδων, επιτρέποντας σε κάθε user namespace να έχει το δικό του σύνολο ID χρηστών και ομάδων. Αυτή η απομόνωση επιτρέπει σε διαδικασίες που εκτελούνται σε διαφορετικά user namespaces να έχουν διαφορετικά προνόμια και ιδιοκτησία, ακόμη και αν μοιράζονται τα ίδια αριθμητικά ID χρηστών και ομάδων.

Τα user namespaces είναι ιδιαίτερα χρήσιμα στην κοντεντοποίηση, όπου κάθε κοντέινερ θα πρέπει να έχει το δικό του ανεξάρτητο σύνολο ID χρηστών και ομάδων, επιτρέποντας καλύτερη ασφάλεια και απομόνωση μεταξύ των κοντέινερ και του συστήματος φιλοξενίας.

How it works:

  1. Όταν δημιουργείται ένα νέο user namespace, ξεκινά με ένα κενό σύνολο αντιστοιχίσεων ID χρηστών και ομάδων. Αυτό σημαίνει ότι οποιαδήποτε διαδικασία εκτελείται στο νέο user namespace θα έχει αρχικά κανένα προνόμιο εκτός του namespace.
  2. Οι αντιστοιχίσεις ID μπορούν να καθοριστούν μεταξύ των ID χρηστών και ομάδων στο νέο namespace και εκείνων στο γονικό (ή κεντρικό) namespace. Αυτό επιτρέπει στις διαδικασίες στο νέο namespace να έχουν προνόμια και ιδιοκτησία που αντιστοιχούν σε ID χρηστών και ομάδων στο γονικό namespace. Ωστόσο, οι αντιστοιχίσεις ID μπορούν να περιοριστούν σε συγκεκριμένα εύρη και υποσύνολα ID, επιτρέποντας λεπτομερή έλεγχο των προνομίων που χορηγούνται σε διαδικασίες στο νέο namespace.
  3. Μέσα σε ένα user namespace, οι διαδικασίες μπορούν να έχουν πλήρη προνόμια root (UID 0) για λειτουργίες εντός του namespace, ενώ εξακολουθούν να έχουν περιορισμένα προνόμια εκτός του namespace. Αυτό επιτρέπει στα κοντέινερ να εκτελούνται με ικανότητες παρόμοιες με του root εντός του δικού τους namespace χωρίς να έχουν πλήρη προνόμια root στο σύστημα φιλοξενίας.
  4. Οι διαδικασίες μπορούν να μετακινούνται μεταξύ namespaces χρησιμοποιώντας την κλήση συστήματος setns() ή να δημιουργούν νέα namespaces χρησιμοποιώντας τις κλήσεις συστήματος unshare() ή clone() με την σημαία CLONE_NEWUSER. Όταν μια διαδικασία μετακινείται σε ένα νέο namespace ή δημιουργεί ένα, θα αρχίσει να χρησιμοποιεί τις αντιστοιχίσεις ID χρηστών και ομάδων που σχετίζονται με αυτό το namespace.

Lab:

Create different Namespaces

CLI

bash
sudo unshare -U [--mount-proc] /bin/bash

Με την τοποθέτηση μιας νέας παρουσίας του συστήματος αρχείων /proc αν χρησιμοποιήσετε την παράμετρο --mount-proc, διασφαλίζετε ότι το νέο namespace τοποθέτησης έχει μια ακριβή και απομονωμένη άποψη των πληροφοριών διαδικασίας που είναι συγκεκριμένες για αυτό το namespace.

Σφάλμα: bash: fork: Cannot allocate memory

Όταν εκτελείται το unshare χωρίς την επιλογή -f, προκύπτει ένα σφάλμα λόγω του τρόπου που το Linux χειρίζεται τα νέα PID (Process ID) namespaces. Οι βασικές λεπτομέρειες και η λύση περιγράφονται παρακάτω:

  1. Εξήγηση Προβλήματος:
  • Ο πυρήνας του 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.
  1. Συνέπεια:
  • Η έξοδος του PID 1 σε ένα νέο namespace οδηγεί στον καθαρισμό της σημαίας PIDNS_HASH_ADDING. Αυτό έχει ως αποτέλεσμα τη αποτυχία της συνάρτησης alloc_pid να κατανομήσει ένα νέο PID κατά τη δημιουργία μιας νέας διαδικασίας, παράγοντας το σφάλμα "Cannot allocate memory".
  1. Λύση:
  • Το πρόβλημα μπορεί να επιλυθεί χρησιμοποιώντας την επιλογή -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

bash
docker run -ti --name ubuntu1 -v /usr:/ubuntu1 ubuntu bash

Για να χρησιμοποιήσετε το user namespace, ο Docker daemon πρέπει να ξεκινήσει με --userns-remap=default(Στο ubuntu 14.04, αυτό μπορεί να γίνει τροποποιώντας το /etc/default/docker και στη συνέχεια εκτελώντας sudo service docker restart)

Ελέγξτε σε ποιο namespace βρίσκεται η διαδικασία σας

bash
ls -l /proc/self/ns/user
lrwxrwxrwx 1 root root 0 Apr  4 20:57 /proc/self/ns/user -> 'user:[4026531837]'

Είναι δυνατόν να ελέγξετε τον χάρτη χρηστών από το κοντέινερ docker με:

bash
cat /proc/self/uid_map
0          0 4294967295  --> Root is root in host
0     231072      65536  --> Root is 231072 userid in host

Ή από τον κεντρικό υπολογιστή με:

bash
cat /proc/<pid>/uid_map

Βρείτε όλα τα User namespaces

bash
sudo find /proc -maxdepth 3 -type l -name user -exec readlink {} \; 2>/dev/null | sort -u
# Find the processes with an specific namespace
sudo find /proc -maxdepth 3 -type l -name user -exec ls -l  {} \; 2>/dev/null | grep <ns-number>

Είσοδος σε ένα User namespace

bash
nsenter -U TARGET_PID --pid /bin/bash

Επίσης, μπορείτε να εισέλθετε σε άλλη διαδικασία namespace μόνο αν είστε root. Και δεν μπορείτε να εισέλθετε σε άλλη namespace χωρίς έναν περιγραφέα που να δείχνει σε αυτήν (όπως το /proc/self/ns/user).

Δημιουργία νέου User namespace (με αντιστοιχίσεις)

bash
unshare -U [--map-user=<uid>|<name>] [--map-group=<gid>|<name>] [--map-root-user] [--map-current-user]
bash
# Container
sudo unshare -U /bin/bash
nobody@ip-172-31-28-169:/home/ubuntu$ #Check how the user is nobody

# From the host
ps -ef | grep bash # The user inside the host is still root, not nobody
root       27756   27755  0 21:11 pts/10   00:00:00 /bin/bash

Ανάκτηση Δυνατοτήτων

Στην περίπτωση των namespaces χρηστών, όταν δημιουργείται ένα νέο namespace χρηστών, η διαδικασία που εισέρχεται στο namespace αποκτά ένα πλήρες σύνολο δυνατοτήτων εντός αυτού του namespace. Αυτές οι δυνατότητες επιτρέπουν στη διαδικασία να εκτελεί προνομιακές λειτουργίες όπως mounting filesystems, δημιουργία συσκευών ή αλλαγή ιδιοκτησίας αρχείων, αλλά μόνο εντός του πλαισίου του namespace χρηστών της.

Για παράδειγμα, όταν έχετε τη δυνατότητα CAP_SYS_ADMIN εντός ενός namespace χρηστών, μπορείτε να εκτελείτε λειτουργίες που συνήθως απαιτούν αυτή τη δυνατότητα, όπως το mounting filesystems, αλλά μόνο εντός του πλαισίου του namespace χρηστών σας. Οποιεσδήποτε λειτουργίες εκτελείτε με αυτή τη δυνατότητα δεν θα επηρεάσουν το σύστημα φιλοξενίας ή άλλα namespaces.

warning

Επομένως, ακόμη και αν η απόκτηση μιας νέας διαδικασίας μέσα σε ένα νέο namespace χρηστών θα σας δώσει όλες τις δυνατότητες πίσω (CapEff: 000001ffffffffff), στην πραγματικότητα μπορείτε να χρησιμοποιήσετε μόνο αυτές που σχετίζονται με το namespace (mount για παράδειγμα) αλλά όχι όλες. Έτσι, αυτό από μόνο του δεν είναι αρκετό για να ξεφύγετε από ένα Docker container.

bash
# There are the syscalls that are filtered after changing User namespace with:
unshare -UmCpf  bash

Probando: 0x067 . . . Error
Probando: 0x070 . . . Error
Probando: 0x074 . . . Error
Probando: 0x09b . . . Error
Probando: 0x0a3 . . . Error
Probando: 0x0a4 . . . Error
Probando: 0x0a7 . . . Error
Probando: 0x0a8 . . . Error
Probando: 0x0aa . . . Error
Probando: 0x0ab . . . Error
Probando: 0x0af . . . Error
Probando: 0x0b0 . . . Error
Probando: 0x0f6 . . . Error
Probando: 0x12c . . . Error
Probando: 0x130 . . . Error
Probando: 0x139 . . . Error
Probando: 0x140 . . . Error
Probando: 0x141 . . . Error

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