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

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

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

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

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

Категории

Все категории
Loading categories
CVE-2022-0778 — Эксплойт proof-of-concept для CVE-2022-0778, демонстрирующий бесконечный цикл в BN_mod_sqrt в OpenSSL через специально сформированный сертификат X.509 с непростыми параметрами кривой, что позволяет осуществлять атаки типа «отказ в обслуживании». | Kitploit
Инструменты/GitHubGitHub/drago-96/cve-2022-0778
Анализ уязвимостейЭксплуатацияКриптографияАнализ Бинарных ФайловСтатьи и ИсследованияОбучение и Образование
GitHubdrago-96/cve-2022-0778

CVE-2022-0778

Эксплойт proof-of-concept для CVE-2022-0778, демонстрирующий бесконечный цикл в BN_mod_sqrt в OpenSSL через специально сформированный сертификат X.509 с непростыми параметрами кривой, что позволяет осуществлять атаки типа «отказ в обслуживании».

Репозиторий
18146104 лет назадПроверено Kitploit

Популярное

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

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

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

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

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

CVE-2022-0778

Обнаруженная уязвимость вызывает бесконечный цикл в функции BN_mod_sqrt() OpenSSL при разборе ключа эллиптической кривой. Это означает, что вредоносный X.509-сертификат может вызвать отказ в обслуживании (DoS) любого незапатченного сервера.

Суть уязвимости заключается в разборе EC-ключей с точками в сжатом формате: при разборе таких ключей OpenSSL пытается развернуть сжатую точку, вычисляя квадратный корень по модулю простого числа p, над которым определена кривая. Однако простота p нигде не проверяется, даже в BN_mod_sqrt(), для которой это является обязательным условием; таким образом, ошибка в реализации приводит к бесконечному циклу из-за того, что p не является простым, как ожидалось.

中文版说明可以见我的博客OpenSSL CVE-2022-0778漏洞问题复现与非法证书构造

Благодарности

  • Tavis Ormandy за обнаружение и раскрытие уязвимости
  • Drago за публикацию теста для BN_mod_sqrt()
  • catbro666 за создание X.509-сертификата, который заставляет сервер зависать
  • wllm-rbnt за полезный инструмент asn1template

Как тестировать

Предварительное условие — установленные gcc и уязвимая версия OpenSSL.

Для ошибки в BN_mod_sqrt(): скомпилируйте с помощью gcc -o my_bad_sqrt my_bad_sqrt.c -lcrypto, запустите ./my_bad_sqrt и наблюдайте бесконечное зависание! :D

С сертификатом: выполните openssl x509 -in certs/cert.der.new -inform DER -text -noout в командной строке; это также вызывает зависание.

Попадание в цикл

Функция BN_mod_sqrt() реализует алгоритм Тонелли-Шенкса для нахождения квадратного корня по модулю, т.е. для заданных целого числа a и простого числа p возвращает значение r такое, что r^2 == a (mod p).

Анализируя коммит, который исправляет уязвимость, мы видим, что виновником является цикл, который находит наименьший индекс i, для которого b^(2^i)==1 (mod p), где b определено ранее в алгоритме.

Цикл изменён с

i = 1;
if (!BN_mod_sqr(t, b, p, ctx))
    goto end;
while (!BN_is_one(t)) {
    i++;
    if (i == e) {
        ERR_raise(ERR_LIB_BN, BN_R_NOT_A_SQUARE);
        goto end;
    }
    if (!BN_mod_mul(t, t, t, p, ctx))
        goto end;
}

на

for (i = 1; i < e; i++) {
    if (i == 1) {
        if (!BN_mod_sqr(t, b, p, ctx))
            goto end;
    } else {
        if (!BN_mod_mul(t, t, t, p, ctx))
            goto end;
    }
    if (BN_is_one(t))
        break;
}

Во втором случае используется цикл for, ограниченный переменной e; в исходном коде, однако, есть только проверка случая i==e внутри цикла while.

Поскольку эти циклы находятся внутри более крупного цикла, который на каждой итерации устанавливает новое значение e равным текущему значению i, мы попробуем следующую стратегию атаки:

  1. при первом выполнении внешнего цикла добиться, чтобы i=1 в конце; для этого необходимо, чтобы b^2=1 (mod p).
  2. таким образом, во время второго выполнения мы получим e=1, и если мы сможем попасть во внутренний цикл, проверка i==e всегда будет проваливаться.
  3. если мы сможем всегда иметь t != 1 (mod p), то останемся в цикле навсегда.

Заметьте, что первые два шага могут произойти и при «нормальном» выполнении, т.е. с простым p. Однако, если p составное, мы можем также выполнить и третий шаг!

Немного математики

Алгоритм Тонелли-Шенкса работает, записывая p - 1 = 2^e * q с нечётным q. Это также порядок мультипликативной группы целых чисел по модулю p, и значения e и q будут многократно использоваться во время выполнения; однако, если p не простое, порядок мультипликативной группы не будет равен p-1, и это поможет нам попасть в бесконечный цикл.

В частности, b инициализируется как b = a^q (mod p), что означает, что если бы p было простым, то b имело бы порядок, являющийся степенью двойки, который мы затем найдём с помощью цикла.

Но если мы установим p = r * s, порядок мультипликативной группы будет (r-1)*(s-1) = r*s - r - s + 1 вместо r*s-1. Алгоритм использует значение q для получения элемента y порядка ровно 2^e; однако, когда p не простое, значение q не будет иметь особого смысла для порядка, поэтому элемент y не будет иметь порядок, равный степени двойки, по модулю p=r*s.

Поскольку в конце первого внешнего цикла b устанавливается как b = b*y^(e-i) (mod p), на второй итерации внутренний цикл будет пытаться найти значение i, для которого b^(2^i) == 1 (mod p), но потерпит неудачу, так как y больше не гарантированно имеет порядок степени двойки.

Эксплойт

Числа в эксплойте очень простые: мы берём r=17,s=41, что даёт p=r*s=697. Это означает, что вычисленные значения e и q будут p-1 = 2^3 * 87.

Затем мы выбираем a=696, что означает a == -1 (mod p) и также b == -1 (mod p) при инициализации. Это удовлетворяет шагу 1, устанавливая e=1 для следующего внешнего цикла.

Затем b будет установлено в элемент, порядок которого не является степенью двойки, и внутренний цикл застрянет, пытаясь найти i, для которого b^(2^i)==1 (mod p).

Создание опасного сертификата

Хорошо, теперь давайте изготовим опасный сертификат, который содержит недопустимые явные параметры кривой с базовой точкой, закодированной в сжатой форме.

Файлы этого раздела находятся в папке certs.

Создание обычного сертификата с явными параметрами кривой

Сначала нужно создать закрытый ключ EC. Поскольку мы хотим получить целевой сертификат с явными параметрами кривой, ключ также должен содержать явные параметры кривой.

$ openssl ecparam -out ec.key -name prime256v1 -genkey -noout -param_enc explicit -conv_form compressed

Затем для удобства мы подписываем сертификат самому себе и выводим его в формате DER.

$ openssl req -new -x509 -key ec.key -out cert.der -outform DER -days 360 -subj "/CN=TEST/"

Давайте проверим информацию о сертификате. Он содержит явные параметры кривой, как и ожидалось.

$ openssl x509 -in cert.der -text -noout -inform DER
...
                Field Type: prime-field
                Prime:
                    00:ff:ff:ff:ff:00:00:00:01:00:00:00:00:00:00:
                    00:00:00:00:00:00:ff:ff:ff:ff:ff:ff:ff:ff:ff:
                    ff:ff:ff
                A:
                    00:ff:ff:ff:ff:00:00:00:01:00:00:00:00:00:00:
                    00:00:00:00:00:00:ff:ff:ff:ff:ff:ff:ff:ff:ff:
                    ff:ff:fc
                B:
                    5a:c6:35:d8:aa:3a:93:e7:b3:eb:bd:55:76:98:86:
                    bc:65:1d:06:b0:cc:53:b0:f6:3b:ce:3c:3e:27:d2:
                    60:4b
                Generator (compressed):
                    03:6b:17:d1:f2:e1:2c:42:47:f8:bc:e6:e5:63:a4:
                    40:f2:77:03:7d:81:2d:eb:33:a0:f4:a1:39:45:d8:
                    98:c2:96
                Order:
                    00:ff:ff:ff:ff:00:00:00:00:ff:ff:ff:ff:ff:ff:
                    ff:ff:bc:e6:fa:ad:a7:17:9e:84:f3:b9:ca:c2:fc:
                    63:25:51
...

Создание недействительного сертификата

Теперь нужно изменить значения этих параметров: Prime, A, B, Generator. Они удовлетворяют уравнению ниже

где p — это Prime, a — параметр A, b — параметр B. p, a, b вместе определяют кривую. Разжатие точки означает вычисление координаты Y по соответствующей координате X.

Очевидно, что необходимо использовать операцию извлечения квадратного корня по модулю, которая вызовет BN_mod_sqrt().

Скачать инструмент