mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/linux-hardening/privilege-escalation/docker-security/na
This commit is contained in:
parent
ae2ee2d51c
commit
14f328a000
@ -14,29 +14,29 @@
|
||||
```bash
|
||||
sudo unshare -T [--mount-proc] /bin/bash
|
||||
```
|
||||
Με την τοποθέτηση μιας νέας παρουσίας του συστήματος αρχείων `/proc` αν χρησιμοποιήσετε την παράμετρο `--mount-proc`, διασφαλίζετε ότι η νέα mount namespace έχει μια **ακριβή και απομονωμένη άποψη των πληροφοριών διαδικασίας που είναι συγκεκριμένες για αυτή τη namespace**.
|
||||
Με την τοποθέτηση μιας νέας παρουσίας του συστήματος αρχείων `/proc` αν χρησιμοποιήσετε την παράμετρο `--mount-proc`, διασφαλίζετε ότι το νέο namespace τοποθέτησης έχει μια **ακριβή και απομονωμένη άποψη των πληροφοριών διαδικασίας που είναι συγκεκριμένες για αυτό το namespace**.
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Σφάλμα: bash: fork: Cannot allocate memory</summary>
|
||||
|
||||
Όταν εκτελείται το `unshare` χωρίς την επιλογή `-f`, προκύπτει ένα σφάλμα λόγω του τρόπου που το Linux χειρίζεται τις νέες PID (Process ID) namespaces. Οι βασικές λεπτομέρειες και η λύση περιγράφονται παρακάτω:
|
||||
Όταν εκτελείται το `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.
|
||||
- Ο πυρήνας του 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.
|
||||
|
||||
2. **Συνέπεια**:
|
||||
|
||||
- Η έξοδος του PID 1 σε μια νέα namespace οδηγεί στον καθαρισμό της σημαίας `PIDNS_HASH_ADDING`. Αυτό έχει ως αποτέλεσμα τη αποτυχία της συνάρτησης `alloc_pid` να κατανεμηθεί ένα νέο PID κατά τη δημιουργία μιας νέας διαδικασίας, παράγοντας το σφάλμα "Cannot allocate memory".
|
||||
- Η έξοδος του PID 1 σε ένα νέο namespace οδηγεί στον καθαρισμό της σημαίας `PIDNS_HASH_ADDING`. Αυτό έχει ως αποτέλεσμα τη αποτυχία της συνάρτησης `alloc_pid` να κατανοήσει ένα νέο PID κατά τη δημιουργία μιας νέας διαδικασίας, παράγοντας το σφάλμα "Cannot allocate memory".
|
||||
|
||||
3. **Λύση**:
|
||||
- Το πρόβλημα μπορεί να επιλυθεί χρησιμοποιώντας την επιλογή `-f` με το `unshare`. Αυτή η επιλογή κάνει το `unshare` να δημιουργήσει μια νέα διαδικασία μετά τη δημιουργία της νέας PID namespace.
|
||||
- Η εκτέλεση `%unshare -fp /bin/bash%` διασφαλίζει ότι η εντολή `unshare` γίνεται PID 1 στη νέα namespace. Το `/bin/bash` και οι παιδικές του διαδικασίες είναι τότε ασφαλώς περιορισμένες μέσα σε αυτή τη νέα namespace, αποτρέποντας την πρόωρη έξοδο του PID 1 και επιτρέποντας την κανονική κατανομή PID.
|
||||
- Το πρόβλημα μπορεί να επιλυθεί χρησιμοποιώντας την επιλογή `-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` και τις υπο-διαδικασίες του να λειτουργούν χωρίς να αντιμετωπίζουν το σφάλμα κατανομής μνήμης.
|
||||
Διασφαλίζοντας ότι το `unshare` εκτελείται με την επιλογή `-f`, το νέο PID namespace διατηρείται σωστά, επιτρέποντας στο `/bin/bash` και τις υπο-διαδικασίες του να λειτουργούν χωρίς να αντιμετωπίζουν το σφάλμα κατανομής μνήμης.
|
||||
|
||||
</details>
|
||||
|
||||
@ -55,8 +55,87 @@ sudo find /proc -maxdepth 3 -type l -name time -exec readlink {} \; 2>/dev/null
|
||||
# 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>
|
||||
```
|
||||
### Είσοδος σε ένα Time namespace
|
||||
### Είσοδος σε ένα Χρονικό namespace
|
||||
```bash
|
||||
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` φαίνεται ως εξής:
|
||||
```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 στην παραγωγή.
|
||||
|
||||
---
|
||||
|
||||
## Σκέψεις ασφαλείας
|
||||
|
||||
1. **Απαιτούμενη ικανότητα** – Μια διαδικασία χρειάζεται **CAP_SYS_TIME** μέσα στο namespace χρήστη/χρόνου της για να αλλάξει τις μετατοπίσεις. Η αφαίρεση αυτής της ικανότητας στο κοντέινερ (προεπιλογή στο Docker & Kubernetes) αποτρέπει την παραχάραξη.
|
||||
2. **Καμία αλλαγή ρολογιού** – Επειδή το `CLOCK_REALTIME` μοιράζεται με τον κεντρικό υπολογιστή, οι επιτιθέμενοι δεν μπορούν να παραποιήσουν τις διάρκειες πιστοποιητικών, την λήξη JWT, κ.λπ. μέσω timens μόνο.
|
||||
3. **Αποφυγή ανίχνευσης / καταγραφής** – Λογισμικό που βασίζεται στο `CLOCK_MONOTONIC` (π.χ. περιοριστές ρυθμού βασισμένοι σε χρόνο λειτουργίας) μπορεί να μπερδευτεί αν ο χρήστης του namespace ρυθμίσει τη μετατόπιση. Προτιμήστε το `CLOCK_REALTIME` για χρονικές σφραγίδες που σχετίζονται με την ασφάλεια.
|
||||
4. **Επιφάνεια επίθεσης πυρήνα** – Ακόμα και με την αφαίρεση του `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>
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user