Time Namespace

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

Часовий простір у Linux дозволяє використовувати зсуви для системних монотонних і завантажувальних годинників для кожного простору. Він зазвичай використовується в контейнерах Linux для зміни дати/часу всередині контейнера та коригування годинників після відновлення з контрольної точки або знімка.

Lab:

Create different Namespaces

CLI

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

Монтування нової інстанції файлової системи /proc, якщо ви використовуєте параметр --mount-proc, забезпечує, що новий простір монтування має точний та ізольований вигляд інформації про процеси, специфічної для цього простору.

Помилка: bash: fork: Не вдалося виділити пам'ять

Коли unshare виконується без параметра -f, виникає помилка через те, як Linux обробляє нові PID (ідентифікатори процесів) простори. Основні деталі та рішення наведені нижче:

  1. Пояснення проблеми:
  • Ядро Linux дозволяє процесу створювати нові простори за допомогою системного виклику unshare. Однак процес, який ініціює створення нового PID простору (який називається "процесом unshare"), не входить до нового простору; лише його дочірні процеси входять.
  • Виконання %unshare -p /bin/bash% запускає /bin/bash в тому ж процесі, що й unshare. Відповідно, /bin/bash та його дочірні процеси знаходяться в оригінальному PID просторі.
  • Перший дочірній процес /bin/bash у новому просторі стає PID 1. Коли цей процес завершується, це викликає очищення простору, якщо немає інших процесів, оскільки PID 1 має особливу роль усиновлення сирітських процесів. Ядро Linux тоді вимкне виділення PID у цьому просторі.
  1. Наслідок:
  • Вихід PID 1 у новому просторі призводить до очищення прапора PIDNS_HASH_ADDING. Це призводить до того, що функція alloc_pid не може виділити новий PID при створенні нового процесу, що викликає помилку "Не вдалося виділити пам'ять".
  1. Рішення:
  • Проблему можна вирішити, використовуючи параметр -f з unshare. Цей параметр змушує unshare створити новий процес після створення нового PID простору.
  • Виконання %unshare -fp /bin/bash% забезпечує, що команда unshare сама стає PID 1 у новому просторі. /bin/bash та його дочірні процеси тоді безпечно містяться в цьому новому просторі, запобігаючи передчасному виходу PID 1 та дозволяючи нормальне виділення PID.

Забезпечивши, що unshare виконується з прапором -f, новий PID простір правильно підтримується, що дозволяє /bin/bash та його підпроцесам працювати без виникнення помилки виділення пам'яті.

Docker

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

Перевірте, в якому просторі імен знаходиться ваш процес

bash
ls -l /proc/self/ns/time
lrwxrwxrwx 1 root root 0 Apr  4 21:16 /proc/self/ns/time -> 'time:[4026531834]'

Знайти всі простори часу

bash
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>

Увійти в простір часу

bash
nsenter -T TARGET_PID --pid /bin/bash

Маніпулювання часовими зсувами

Починаючи з Linux 5.6, два годинники можуть бути віртуалізовані для кожного простору часу:

  • CLOCK_MONOTONIC
  • CLOCK_BOOTTIME

Їхні делти на кожен простір часу відкриті (і можуть бути змінені) через файл /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 в часовому просторі, можуть змінювати значення:

# 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) допоміжні прапори (util-linux ≥ 2.38)

sudo unshare -T \
--monotonic="+24h"  \
--boottime="+7d"    \
--mount-proc         \
bash

Довгі параметри автоматично записують обрані дельти в timens_offsets одразу після створення простору імен, що заощаджує ручне echo.


Підтримка OCI та Runtime

  • OCI Runtime Specification v1.1 (листопад 2023) додала спеціальний тип простору імен 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 всередині свого простору імен користувача/часу, щоб змінити зсуви. Відмова від цієї можливості в контейнері (за замовчуванням у Docker та Kubernetes) запобігає маніпуляціям.
  2. Без змін годинника – Оскільки CLOCK_REALTIME спільний з хостом, зловмисники не можуть підробити терміни дії сертифікатів, терміни дії JWT тощо лише за допомогою timens.
  3. Уникнення журналювання/виявлення – Програмне забезпечення, яке покладається на CLOCK_MONOTONIC (наприклад, обмежувачі швидкості на основі часу безперервної роботи), може бути заплутаним, якщо користувач простору імен регулює зсув. Віддавайте перевагу CLOCK_REALTIME для часових міток, що мають значення для безпеки.
  4. Поверхня атаки ядра – Навіть якщо CAP_SYS_TIME видалено, код ядра залишається доступним; підтримуйте хост в актуальному стані. Linux 5.6 → 5.12 отримав кілька виправлень помилок timens (NULL-deref, проблеми з підписом).

Контрольний список посилення безпеки

  • Відмовтеся від CAP_SYS_TIME у вашому профілі за замовчуванням контейнерного виконання.
  • Підтримуйте виконання в актуальному стані (runc ≥ 1.2.6, crun ≥ 1.12).
  • Закріпіть util-linux ≥ 2.38, якщо ви покладаєтеся на допоміжні програми --monotonic/--boottime.
  • Аудит програмного забезпечення в контейнері, яке читає uptime або CLOCK_MONOTONIC для логіки, критично важливої для безпеки.

Посилання

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