
PoC для CVE-2019-5736
PoC для CVE-2019-5736
Создано с помощью @singe, @_cablethief и @feexd
Протестировано на Ubuntu 18.04, Debian 9 и Arch Linux. Версии Docker 18.09.1-ce и 18.03.1-ce. Данный PoC в настоящее время не работает с Ubuntu 16.04 и CentOS.
Посмотрите код эксплойта от Dragon Sector (люди, обнаружившие уязвимость) здесь.
Это реализация на Go уязвимости CVE-2019-5736, позволяющей выйти за пределы контейнера в Docker. Эксплойт работает путем перезаписи и выполнения бинарного файла runc хост‑системы изнутри контейнера.
Существует 2 варианта использования эксплойта. Первый (именно он представлен в этом репозитории) по сути является ловушкой. Злоумышленнику необходимо получить выполнение команд внутри контейнера и запустить вредоносный бинарный файл, который будет прослушивать. Когда кто-то (злоумышленник или жертва) использует docker exec для входа в контейнер, это запускает эксплойт, позволяющий выполнить код с правами root.

Второй вариант (который не представлен в этом репозитории) создает вредоносный образ Docker. Когда этот образ запускается, эксплойт срабатывает. Нет необходимости выполнять exec в контейнере. Смотрите пример в виде gif внизу этого readme.
Для эксплуатации этой уязвимости необходимо иметь root (uid 0) внутри контейнера.
Да, вы перезапишете свою реализацию runc, что приведет к невозможности запуска Docker‑контейнеров. Пожалуйста, сделайте резервную копию /usr/bin/docker-runc или /usr/bin/runc (в зависимости от того, какой у вас; также проверьте /usr/sbin).
Измените код по своему усмотрению и скомпилируйте его с помощью go build main.go. Переместите полученный бинарный файл в контейнер, из которого хотите совершить побег. Запустите бинарный файл, и в следующий раз, когда кто-то подключится к контейнеру и вызовет /bin/sh, ваша полезная нагрузка сработает.
Этот PoC был создан на основе отличного объяснения из этого коммита в проекте lxc (а также с помощью полезных советов от других).
Например, если целевой бинарный файл был /bin/bash, его можно заменить исполняемым скриптом, указывающим путь интерпретатора #!/proc/self/exe (/proc/self/exec — это символическая ссылка, создаваемая ядром для каждого процесса, которая указывает на бинарный файл, выполняемый для этого процесса). Таким образом, когда /bin/bash выполняется внутри контейнера, вместо него будет выполнен целевой объект /proc/self/exe, который будет указывать на бинарный файл runc на хосте.

Мы реализуем это, перезаписывая /bin/sh в контейнере на #!/proc/self/exe, который будет указывать на бинарный файл, запустивший этот процесс (Docker exec).

Затем атакующий может попытаться записать в цель /proc/self/exe, чтобы перезаписать бинарный файл runc на хосте. Однако в целом это не удастся, так как ядро не позволит перезаписать его во время выполнения runC. Чтобы обойти это, атакующий может вместо этого открыть файловый дескриптор /proc/self/exe с помощью флага O_PATH, а затем переоткрыть бинарный файл как O_WRONLY через /proc/self/fd/ и попытаться записать в него в активном цикле из отдельного процесса.
Примечание: Некоторые части предыдущего раздела не совсем точны. Вам не нужно использовать флаг O_PATH при получении файлового дескриптора для runcinit. Кроме того, вам не нужно создавать цикл записи в отдельном процессе. Мы получаем файловый дескриптор для runcinit, получая дескриптор файла /proc/PID/exe. Затем мы используем этот дескриптор для получения дескриптора файла /proc/self/fd/FILEDESCRIPTOR. Это дескриптор файла, который мы будем использовать для записи.

В конечном итоге это удастся, когда бинарный файл runC завершит работу. После этого бинарный файл runC будет скомпрометирован и может быть использован для атаки на другие контейнеры или сам хост.
Если нам удается записать в этот дескриптор файла, мы перезаписываем бинарный файл runc на хосте. Мы можем выполнять произвольные команды с правами root.
Этот репозиторий не содержит этого примера, но вы можете найти его здесь. На мой взгляд, это гораздо более опасный сценарий. Просто запустите вредоносный образ контейнера, и вы получите выполнение кода с правами root. Подробное объяснение см. здесь.
