Linux exploits
Привет, хабровчане. В преддверии старта курса «Administrator Linux. Professional» наш эксперт — Александр Колесников подготовил интересную статью, которой мы с радостью делимся с вами.
Также приглашаем будущих студентов и всех желающих посетить открытый урок по теме «Методы и возможности отладки скриптов оболочки Bash».
Операционная система Linux доказала миру всю силу Open Source проектов — благодаря ей у нас сегодня есть возможность заглянуть в исходный код рабочей ОС и на его основе собрать свою собственную систему для решения тех или иных задач. По причине своей открытости Linux должна была стать самой безопасной операционной системой в мире, так как открытый исходный код позволяет развивать и улучшать подсистемы защиты от атак на ОС и совершенствовать саму операционную систему. Действительно, на данный момент существует большое количество созданных комьюнити защит: сегодня уже просто не так просто проэксплуатировать уязвимости типа переполнения буфера для получения повышенных привилегий так же, как 20 лет назад. Тем не менее, сегодня можно в открытом доступе встретить эксплойты, которые даже на последних версиях ядра могут повысить привилегии пользователя. Рассмотрим в этой статье, как это работает и почему так получается. Мы пройдемся по основным составляющим эксплойтов и рассмотрим, как работают некоторые из них.
Вся предоставленная информация была собрана исключительно в ознакомительных целях.
Типы эксплойтов
Выберем общий термин, которым будем обозначать, что есть эксплойт — алгоритм, который нарушает нормальное функционирование операционной системы, а именно — механизмы разграничения доступа. Также введем понятие уязвимости — это несовершенство программного обеспечения, которое может быть использовано алгоритмом эксплойта. Без уязвимости существование эксплойта невозможно.
Введем классификацию эксплойтов. Базовое разделение эксплойтов на подгруппы для любой операционной системы начинается на уровне архитектуры. Сегодня операционные системы включают в себя как минимум 2 уровня привилегий, которые используют для своей работы. Ниже приведен рисунок, который наглядно показывает разделение привилегий. Картинка взята отсюда.
Картинка очень наглядно показывает, что в операционной системе присутствует уровень Ядра (Kernel Space), обычно это самый привилегированный режим, именно здесь находится то, что мы называем операционной системой. И второй уровень — Пользовательский (User Space): здесь запускаются обычные приложения и сервисы, которые мы используем каждый день.
Исторически сложилось, что для каждого из перечисленных выше уровней могут быть найдены уязвимости, для которых может быть создан эксплойт, но эксплойты для каждого из уровней имеют свои ограничения.
На пользовательском уровне любой эксплойт, который затрагивает приложение, будет иметь ровно те привилегии, которые использовал пользователь, который запустил уязвимое приложение. Поэтому такой вид эксплойтов позволяет получить полное управление над ОС только в случае запуска приложения администратором системы. В противоположность пользовательскому уровню, уровень ядра, если содержит уязвимый код, может сразу дать возможность управлять операционной системой с максимальными привилегиями. Ниже сфокусируемся на исследовании этих эксплойтов.
Эксплойты
Представим небольшую статистику по раскрытию уязвимостей для ядра операционной системы Linux дистрибутивов Debian, SUSE, Ubuntu, Arch Linux последних 4-х лет.
Данные взяты отсюда. Картина не претендует на полноту, но показывает, что уязвимостей достаточно много, и даже сегодня есть из чего выбирать для построения эксплойта. Давайте попробуем описать, что из себя представляет эксплойт.
Любой эксплойт для любого уровня операционной системы сегодня состоит из частей, которые должны быть имплементированы в его коде:
Подготовительные операции:
1) Выставление необходимого отображения памяти
2) Создание необходимых объектов в ОС
3) Обход механизмов защиты ОС для используемой уязвимости
Вызов уязвимой части ПО.
Выполняет полезную нагрузку:
1) Для открытия доступа к ОС
2) Для изменения конфигурации ОС
3) Для вывода ОС из строя
При выполнении всех пунктов, которые указаны выше, можно написать работоспособный эксплойт. Возьмем для исследования несколько эксплойтов прошлых лет и попробуем выяснить, можно ли найти какие-то закономерности или заимствования, которые используются для нарушения разграничений доступа в операционной системе Linux. В качестве объектов исследования возьмем эксплойты, которые используют следующие уязвимости с CVE идентификаторами:
CVE-2020–8835
CVE-2020–27194
Разбор эксплойтов
CVE-2020–8835 распространяется на ядро ОС Linux от версии 5.5.0. Уязвимость находится в имплементации технологии ebpf
. Технология была разработана для того, чтобы пользователь мог создавать кастомные обработчики для фильтрации сетевого трафика. В качестве основной составляющей для выполнения фильтрации используется виртуальная машина с собственным набором команд. Код, который выполняется виртуальной машиной, живет в ядре: ошибка в этом коде приносит атакующему возможность работать с памятью с максимальными привилегиями. В случае описываемой уязвимости проблема заключалась в том, что операции обработки команд длины 32 бита недостаточно корректно обрабатывались, и виртуальная машина могла писать и читать данные в оперативной памяти ядра.
Как автор эксплойта использует данную уязвимость и какая выполняется полезная нагрузка, рассмотрим дальше.
Подготовительный этап
За этот этап отвечает следующая часть кода.
Строка 394 — создание объекта в памяти, который будет хранить данные о командах для ebpf
. Строка 400 загружает в память код, который будет выполняться в виртуальной машине и позволит нарушить условия обработки 32 битных команд. Подготовка памяти окончена, следующие строки будут создавать объект сокета, который обеспечит вызов загруженных команд для bpf
. После этого начнется этап вызова уязвимости.
Вызов уязвимого кода
Вызов уязвимого кода, а точнее — работа с командами виртуальной машины, осуществляется со строки 423 по 441. Основная задача этого кода — получить базовый адрес структуры, которая находится в памяти, в данном случае это куча (heap) процесса. Как только эти команды выполнятся, эксплойт сможет обнаружить в памяти данные, используемые операционной системой для контроля разграничения доступа. В операционной системе Linux эти данные хранятся в структуре taskstruct
.
Полезная нагрузка
Полезная нагрузка данного эксплойта заключается в том, что после его выполнения можно запустить процесс с правами пользователя root
. Для этого код эксплойта производит модификацию полей структуры ядра операционной системы Linux — cred
это структура, которая входит в структуру taskstruct
. Исходный код структуры cred
можно найти здесь.
Действия по модификации полей struct cred
можно увидеть на строках 472,473,474
. То есть этим действием обнуляется значение uid, gid, sgid
создаваемого процесса. С точки зрения ОС это установка значений идентификаторов, которые обычно использует root
. Метод очень похож на тот, который применяется для атак на операционную систему Windows.
Обезопасить себя без обновления ОС можно, если внести следующие изменения в конфиг: sudo sysctl kernel.unprivilegedbpfdisabled=1
CVE-2020–27194 — снова уязвимость в ebpf
. Существует для ядра версий 5.8.*. Создатели этой технологии шутят, что bpf
— это JavaScript для ядра. На самом деле это суждение не далеко от истины. Виртуальная машина действительно проводит манипуляции над командами с помощью технологии JIT, что само собой несет все типичные уязвимости браузеров в ядро операционной системы, то есть сложно настроить подсистемы защиты для того чтобы обезопасить выполнение кода. Рассматриваемая уязвимость заключается в том, что из кода виртуальной машины можно провести модификацию любой области оперативной памяти. Возможно это из-за того, что виртуальная машина небезопасно работает с операциями 64 битной длины. Полностью аналогичная уязвимость той, которую мы рассматривали выше.
Эксплойт, который создан для того, чтобы использовать описанную уязвимость, выполняет те же операции, что и эксплойт CVE-2020–8835. Алгоритм эксплойта следующий:
Загрузить код с обработкой 64 битных операций в память
Создать сокет и отправить данные для вызова команд
ebpf
Найти в памяти адрес структуры
taskstruct
за счет выполнения команд в виртуальной машине
Модифицировать значения
uid,gid,sgid
и запустить интерактивную оболочку.
Автор писал исходный код с новыми фишками и дополнительными функциями. Предлагаем читателю самостоятельно взглянуть на код. Перечисленные этапы работы эксплойта выше не дадут запутаться.
Защита от этой уязвимости без использования обновления такая же: sudo sysctl kernel.unprivilegedbpf_disabled=1
Что в итоге?
На основании двух эксплойтов, который были рассмотрены в статье, можно предположить, что повышение привилегий в современной ОС Linux — это больше не темная магия программирования, а вполне отлаженный шаблонный процесс, который включает в себя переиспользование функций и объектов в оперативной памяти. При этом даже не нужно писать базонезависимый (shellcode) код, который будет выполнять большую часть действий. Достаточно просто изменить идентификаторы, которые используются для назначения привилегий для пользователей.
Узнать подробнее о курсе «Administrator Linux. Professional».
Зарегистрироваться на открытый урок «Методы и возможности отладки скриптов оболочки Bash».