
PoC для CVE-2025-31133
В этом документе объясняется функциональность предоставленного PoC-скрипта (Proof-of-Concept) для уязвимости runc CVE-2025-31133.
maskedPaths в runc.maskedPaths, что позволяет ему записывать данные в чувствительные файлы хост-системы. Это представляет собой побег из контейнера./proc/sys/kernel/core_pattern на хосте изнутри контейнера."pwned" в целевой файл и не выполняет произвольный код на хосте. Он также содержит инструкции по восстановлению исходного значения.Функция maskedPaths в спецификации OCI контейнера (config.json) — это механизм безопасности, предназначенный для предотвращения доступа контейнеров к чувствительным системным файлам. Он работает за счёт bind-mount-подключения /dev/null (пустого файла устройства) поверх этих чувствительных путей внутри контейнера, что фактически делает их недоступными для чтения и записи.
Уязвимость (CVE-2025-31133) представляет собой состояние гонки Time-of-Check to Time-of-Use (TOCTOU). Эксплойт работает следующим образом:
runc настраивает контейнер, он готовится использовать файл dev/null из rootfs контейнера в качестве источника для bind-mount, который замаскирует чувствительный путь (например, /proc/sys/kernel/core_pattern).runc разрешает путь к rootfs/dev/null, и моментом, когда он фактически выполняет операцию монтирования.rootfs/dev/null между легитимным узлом устройства и символической ссылкой, указывающей на целевой файл на хосте (/proc/sys/kernel/core_pattern).runc выполнит операцию монтирования в тот самый момент, когда rootfs/dev/null является символической ссылкой. Это заставляет ядро следовать по символической ссылке, и предполагаемая операция маскирования для /proc/sys/kernel/core_pattern не срабатывает.Этот PoC использует данную технику для записи в /proc/sys/kernel/core_pattern — распространённую цель для подобных эксплойтов, поскольку её изменение может привести к выполнению произвольного кода на хосте при сбое процесса. Однако этот PoC записывает только безвредную строку, чтобы доказать наличие примитива записи.
Скрипт poc.sh автоматизирует весь описанный выше процесс.
Настройка и очистка:
runc, имени контейнера и пути к rootfs.cleanup, которая гарантирует удаление всех ранее созданных контейнеров или файлов скрипта. Эта функция автоматически вызывается при выходе, прерывании или завершении работы.Подготовка:
/proc/sys/kernel/core_pattern хоста во временный файл. Позже это используется для проверки, удался ли эксплойт, и для помощи пользователю в восстановлении системы../rootfs) и файл config.json.config.json явно перечисляет /proc/sys/kernel/core_pattern в разделе maskedPaths — той самой функции, которую эксплойт нацелен обойти.Функция гонки (symlink_race)
Предварительные требования:
runc.busybox-static (для оболочки контейнера).sudo) для запуска runc и изменения /proc.Шаги:
poc.sh.chmod +x poc.sh.sudo ./poc.sh.[+] EXPLOIT SUCCEEDED!, это означает, что состояние гонки было выиграно. Файл /proc/sys/kernel/core_pattern на хосте был успешно изменён изнутри контейнера, что подтверждает уязвимость.[-] Exploit did not succeed., гонка не была выиграна при этой попытке. Состояния гонки вероятностны и сильно зависят от времени и загрузки системы. Попробуйте запустить скрипт ещё несколько раз.PoC изменит системный файл. Чтобы восстановить его в исходное состояние, выполните команду, предложенную скриптом:
# The 'ORIGINAL_PATTERN' will be the actual value from your system
echo 'original_core_pattern_value' | sudo tee /proc/sys/kernel/core_pattern
/proc/sys/kernel/core_patternrootfs/dev/nullrootfs/dev/null к целевому файлу на хосте (/proc/sys/kernel/core_pattern).rootfs/dev/null как полноценное символьное устройство (mknod).Выполнение:
symlink_race запускается как фоновый процесс.runc run ... для создания и запуска контейнера. Именно в этот момент runc попытается применить maskedPaths.runc exec для выполнения команды внутри контейнера: echo 'pwned' > /proc/sys/kernel/core_pattern.Проверка:
/proc/sys/kernel/core_pattern хоста."pwned" и исходным значением.[+] EXPLOIT SUCCEEDED! или [-] Exploit did not succeed..