Статья Как Mozilla упустила (не)очевидную уязвимость

Admin

Администратор

Как Mozilla упустила (не)очевидную уязвимость​

В 2021 году всем хорошим багам нужно цепляющее название, и у этой уязвимости появилось имя BigSig. Сначала объясню, как она нашлась, а затем попытаюсь понять, почему её так долго упускали.

Анализ​

Network Security Services (NSS) — популярная кросс-платформенная криптографическая библиотека от Mozilla. Когда проверяется зашифрованная цифровая подпись ASN.1, в NSS создаётся структура VFYContext для хранения необходимых данных — открытого ключа, хеш-алгоритма и самой подписи.
Код:
struct VFYContextStr {
   SECOidTag hashAlg; /* the hash algorithm */
   SECKEYPublicKey *key;
   union {
       unsigned char buffer[1];
       unsigned char dsasig[DSA_MAX_SIGNATURE_LEN];
       unsigned char ecdsasig[2 * MAX_ECKEY_LEN];
       unsigned char rsasig[(RSA_MAX_MODULUS_BITS + 7) / 8];
   } u;
   unsigned int pkcs1RSADigestInfoLen;
   unsigned char *pkcs1RSADigestInfo;
   void *wincx;
   void *hashcx;
   const SECHashObject *hashobj;
   SECOidTag encAlg;    /* enc alg */
   PRBool hasSignature;
   SECItem *params;
};
Структура VFYContext из NSS

Сигнатура максимального размера, которую обрабатывает эта структура, равна наибольшему элементу объединения, здесь это RSA в 2048 байтов, то есть 16 384 бита. Это достаточно много, чтобы вместить сигнатуры даже невероятно больших ключей. А что, если сделать сигнатуру больше этой? Произойдёт повреждение памяти. Да, так есть. Ненадёжная сигнатура просто копируется в этот буфер фиксированного размера, перезаписывая соседние элементы произвольными данными, которые контролируются злоумышленником.

Баг прост в воспроизведении и влияет на несколько алгоритмов. Проще всего показать RSA-PSS:
Код:
# We need 16384 bits to fill the buffer, then 32 + 64 + 64 + 64 bits to overflow to hashobj,
# which contains function pointers (bigger would work too, but takes longer to generate).
$ openssl genpkey -algorithm rsa-pss -pkeyopt rsa_keygen_bits:$((16384 + 32 + 64 + 64 + 64)) -pkeyopt rsa_keygen_primes:5 -out bigsig.key
# Generate a self-signed certificate from that key
$ openssl req -x509 -new -key bigsig.key -subj "/CN=BigSig" -sha256 -out bigsig.cer
# Verify it with NSS...
$ vfychain -a bigsig.cer
Уязвимость BigSig за три простых команд

Код, который вызывает повреждение, зависит от алгоритма. Вот код для RSA-PSS. Баг заключается в том, что проверки границ просто нет вообще: sig и key — это большие двоичные объекты произвольной длины, контролируемые злоумышленником, а cx->u — это буфер фиксированного размера:
Код:
case rsaPssKey:
               sigLen = SECKEY_SignatureLen(key);
               if (sigLen == 0) {
                   /* error set by SECKEY_SignatureLen */
                   rv = SECFailure;
                   break;
               }

               if (sig->len != sigLen) {
                   PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
                   rv = SECFailure;
                   break;
               }

               PORT_Memcpy(cx->u.buffer, sig->data, sigLen);
               break;
Уязвимость вызывает ряд вопросов:
  • Связана ли она с недавним изменением кода или это регрессия, которая проявилась только сейчас? Нет, исходный код был проверен поддержкой ECC 17 октября 2003 года, но его нельзя было использовать до рефакторинга, проведённого в июне 2012 года. В 2017 году была добавили поддержка RSA-PSS, при этом допустили ту же ошибку.
  • Много ли времени требуется, чтобы сгенерировать ключ, который вызывает баг? Нет, в приведённом примере генерируются реальный ключ и сигнатура, но это может быть мусор: переполнение происходит до проверки сигнатуры. Несколько килобайтов символа А работают без проблем.
  • Требуется ли для доступа к уязвимому коду сложное состояние, с которым у техник тестирования и статических анализаторов были бы трудности при синтезе, например хеши или контрольные суммы? Нет, должен быть правильный DER, вот и всё.
  • Уязвимости трудно достичь в смысле кода? Нет, в Firefox этот путь кода не используется для сигнатур RSA-PSS, но точка входа по умолчанию для проверки сертификата в NSS — CERT_VerifyCertificate() — уязвима.
  • Она характерна исключительно для алгоритма RSA-PSS? Нет, она влияет и на сигнатуры DSA.
  • Этой уязвимостью нельзя воспользоваться или же она имеет ограниченное воздействие? Нет, может быть затёрт элемент hashobj. Этот объект содержит указатели функции, которые сразу же используются.
Это не сбой процесса: вендор всё сделал правильно. В Mozilla работают специалисты мирового класса по обеспечению безопасности. Они первыми внедрили программу вознаграждений за обнаруженные уязвимости, вкладываются в обеспечение безопасной работы с памятью, автоматизацию тестирования безопасности и покрытие кода тестами.

NSS был одним из первых проектов, включённых в oss-fuzz: по крайней мере поддерживался официально с октября 2014 года. В Mozilla сами также проводят автоматизацию тестирования безопасности NSS с помощью libFuzzer и представили собственную коллекцию методов-модификаторов, а также основу корпуса покрытия. Есть обширный тестовый комплект и ночные сборки ASAN.

Я в общем скептически отношусь к статическому анализу, но это похоже на простую недостающую проверку границ, которую должно быть легко найти. Coverity отслеживает NSS по крайней мере с декабря 2008 года и тоже, кажется, не смогла обнаружить уязвимость.

До 2015 года в Google Chrome использовали NSS и поддерживали собственную инфраструктуру тестового комплекта и автоматизации тестирования безопасности, независимую от Mozilla. Сегодня в платформах Chrome используется BoringSSL, но порт NSS ещё поддерживается.
  • Было ли в Mozilla хорошее тестовое покрытие уязвимых областей? Да.
  • Были ли в корпусе автоматизации тестирования безопасности Mozilla / Chrome / oss-fuzz соответствующие входные данные? Да.
  • Есть ли метод-модификатор, способный расширить эти ASN1_ITEM? Да.
  • Является ли это внутриобъектным переполнением или другой формой повреждения, которую ASAN было бы трудно обнаружить? Нет, это классическое переполнение буфера, которое ASAN может обнаружить легко.

Как я нашёл баг?​

Экспериментировал с альтернативными методами измерения покрытия кода, чтобы узнать, можно ли их как-то использовать на практике в автоматизации тестирования безопасности. В технике тестирования, с помощью которой удалось обнаружить эту уязвимость, применялось сочетание двух подходов: покрытие стека и выделение объектов.

Покрытие стека​

Самый распространённый метод измерения покрытия кода — покрытие блоков или покрытие границ, когда доступен исходный код. Интересно, всегда ли этого достаточно? Например, возьмём простую таблицу диспетчеризации с сочетанием надёжных и ненадёжных параметров, как показано в листинге:
Код:
#include <stdio.h>
#include <string.h>
#include <limits.h>
 
static char buf[128];
 
void cmd_handler_foo(int a, size_t b) { memset(buf, a, b); }
void cmd_handler_bar(int a, size_t b) { cmd_handler_foo('A', sizeof buf); }
void cmd_handler_baz(int a, size_t b) { cmd_handler_bar(a, sizeof buf); }
 
typedef void (* dispatch_t)(int, size_t);
 
dispatch_t handlers[UCHAR_MAX] = {
    cmd_handler_foo,
    cmd_handler_bar,
    cmd_handler_baz,
};
 
int main(int argc, char **argv)
{
    int cmd;
 
    while ((cmd = getchar()) != EOF) {
        if (handlers[cmd]) {
            handlers[cmd](getchar(), getchar());
        }
    }
}
Покрытие команды bar — это надмножество команды foo, поэтому ввод, содержащий foo, будет отброшен при минимизации корпуса. Есть уязвимость, недоступная через команду bar, которая может быть не обнаружена никогда. Покрытие стека корректно сохранит оба ввода1.

Чтобы решить эту проблему, я отслеживал стек вызовов во время выполнения.

Наивная реализация слишком медленная, но после многих оптимизаций я создал практичную библиотеку, достаточно быструю, чтобы интегрировать её в автоматизацию тестирования безопасности, ориентированную на покрытие. Я тестировал, как она работает с NSS и другими библиотеками.

Выделение объектов​

Многие типы данных создаются из записей меньшего размера. Файлы PNG состоят из фрагментов, файлы PDF — из потоков, файлы ELF — из разделов, а сертификаты X.509 — из элементов ASN.1 TLV. Если в технике тестирования заложено представление о базовом формате, то с её помощью можно выделить эти записи и извлечь те, что приводят к обнаружению новой трассировки стека.

Техника тестирования, которую я использовал, способна выделять и извлекать интересные новые идентификаторы объекта ASN.1, последовательности SEQUENCE, целые числа INTEGER и т. д. После извлечения они могут случайным образом комбинироваться или вставляться в данные шаблона. На самом деле идея не новая, новая — реализация. Планирую в будущем сделать этот код общедоступным.

Работают ли эти подходы?​

Возможно, обнаружение этого бага подтверждает мои идеи, но я не уверен, что это так. Я проводил относительно новую автоматизацию тестирования безопасности, но не вижу причин, почему этот баг не мог быть обнаружен раньше даже с помощью простейших методов тестирования.

Что в итоге?​

Как обширная, настраиваемая автоматизация тестирования безопасности с впечатляющими показателями покрытия не выявила этот баг?

Что пошло не так?​

1. Нет сквозного тестирования​

NSS — модульная библиотека. Многоуровневый дизайн отражён в подходе автоматизации тестирования безопасности, ведь каждый компонент тестируется независимо. Например, декодер QuickDER проходит расширенное тестирование, но при использовании техники тестирования объекты просто создаются, отбрасываются и никогда не используются:
Код:
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
char *dest[2048];

for (auto tpl : templates) {
PORTCheapArenaPool pool;
SECItem buf = {siBuffer, const_cast<unsigned char *>(Data),
static_cast<unsigned int>(Size)};

PORT_InitCheapArena(&pool, DER_DEFAULT_CHUNKSIZE);
(void)SEC_QuickDERDecodeItem(&pool.arena, dest, tpl, &buf);
PORT_DestroyCheapArena(&pool);
}
При использовании техники тестирования QuickDER объекты просто создаются и отбрасываются. Так проверяется синтаксический анализ ASN.1, но не корректность работы с получаемыми объектами других компонентов.
С этой техникой тестирования можно было создать SECKEYPublicKey, который бы достал в уязвимый код. Но баг так и не был бы обнаружен, ведь результат никогда не использовался для проверки сигнатуры.

2. Произвольные ограничения по размеру​

Для ввода автоматизированного тестирования задаётся произвольное ограничение в 10 000 байтов. В NSS такого ограничения нет: у многих структур этот размер возможно превысить. В случае с этой уязвимостью ошибки происходят на границах, поэтому ограничение следует выбирать с умом.
Приемлемым вариантом может быть 224–1 байтов, т. е. максимально возможный сертификат, предоставляемый сервером во время согласования рукопожатия TLS.
Хотя в NSS обрабатываются объекты даже большего размера, TLS задействовать нельзя, а это снижает общую степень серьёзности любых пропущенных уязвимостей.

3. Метрики и заблуждения​

Все техники тестирования NSS представлены в объединённых показателях покрытия oss-fuzz, а не в их индивидуальных покрытиях. Эти данные оказались неверными, так как уязвимый код проходит расширенное автоматизированное тестирование, но с помощью техник тестирования, которые не могли генерировать соответствующие входные данные.
Почему? Потому что в техниках тестирования типа tls_server_target используются фиксированные, жёстко заданные сертификаты. При этом выполняется код, относящийся к проверке сертификата, но проводится автоматизированное тестирование лишь сообщений TLS и изменений состояния протокола.

Что всё-таки сработало?​

  • Благодаря дизайну библиотеки проверки корректности сертификатов mozilla::pkix не было допущено ухудшение ситуации с этим багом. К сожалению, она не используется вне Firefox и Thunderbird.
Сложно сказать, удача это или нет. Вероятно, RSA-PSS в mozilla::pkix будет разрешён.

Рекомендации​

Эта проблема свидетельствует о том, что даже в очень хорошо поддерживаемом C/C++ могут быть фатальные, простейшие ошибки.

Краткосрочные рекомендации​

  • Увеличить максимальный размер объектов ASN.1, создаваемых с помощью libFuzzer, с 10 000 до 224–1 = 16 777 215 байтов.
  • При использовании техники тестирования QuickDER должны вызываться соответствующие API с любыми успешно созданными объектами, прежде чем они будут уничтожены.
  • Показатели покрытия кода oss-fuzz нужно разделить по технике тестирования, а не по проекту.

Решение​

Эта уязвимость, CVE-2021-43527, закрыта в NSS 3.73.0. Если вы вендор, распространяющий NSS в своих продуктах, то вам, скорее всего, потребуется заменить библиотеку или применить патч.
 
Похожие темы
Admin Интересно Вашему RDP поставили «лайк». История о том, как горстка серверов прочесала Интернет и нашла все изъяны. Новости в сети 0
Admin Интересно Русские хакеры против картошки фри. Как взлом кассы самообслуживания обернулся годом условно. Новости в сети 0
Admin Интересно Тройная порция шантажа под соусом анонимности. Как одна банда притворяется сразу тремя разными группировками. Новости в сети 0
Admin Интересно Как соседей России заставляют выбирать между Европой и личным спокойствием. Новости в сети 0
Admin Интересно Позвони мне через пылесос. Как выживает рунет после блокировки мессенджеров. Новости в сети 0
Admin Интересно Ускоритель частиц размером с карандаш. Мощность — как у километрового. И это работает. Новости в сети 0
Admin Интересно Война правок и логотипов: Как Euro-Office поссорился с ONLYOFFICE из-за лицензии. Новости в сети 0
Admin Интересно Цифры врали. Не специально — просто их сложили неправильно. Вот как парадокс Симпсона ломает статистику. Новости в сети 0
Admin Интересно Цифровые активы после смерти: как управлять рисками для цифрового наследства. Новости в сети 0
Admin Интересно Тихий взлом и полная невидимость. Рассказываем, как новый вирус RoadK1ll захватывает корпоративные сети. Новости в сети 0
Admin Интересно Как заморозить воду быстрее? Сначала вскипятите её и плюньте на здравый смысл. Новости в сети 0
Admin Интересно Откройте доступ к коду из любой точки мира. Как работает новый проект rustunnel. Новости в сети 0
Admin Интересно Не просто «стенка с мониторами». Как за 6 недель создать работающий центр кибербезопасности. Новости в сети 0
Admin Интересно Хакеров много, а работать некому. Как кадровый голод обнуляет защиту мировых гигантов. Новости в сети 0
Admin Интересно Римские цифры, узелки инков и буква x в магазине: как запись чисел определила всю историю математики. Новости в сети 0
Admin Интересно 43% сотрудников опасаются, что ИИ лишит их работы. Как страх увольнения убивает эффективность бизнеса. Новости в сети 0
Admin Интересно Власти Венгрии решили завербовать сторонника оппозиции. Вышло как при коммунизме. Новости в сети 0
Admin Интересно Веб-семинар: Как проверить эффективность вашей защиты от реальных атак. Новости в сети 0
Admin Интересно Как заставить нейросеть удалить всё лишнее (и нужное тоже)? Разбираемся в «токсичных потоках». Новости в сети 0
Admin Интересно 27 граммов еды из 1 грамма бактерий. Как превратить марсианскую пыль в полноценный обед. Новости в сети 0
Admin Интересно Сложность облачных сред как главный враг кибербезопасности. Новости в сети 0
Admin Интересно Три миллиона IP-камер и роутеров по всему миру. Как спецслужбы разгромили гигантскую сеть ботнетов. Новости в сети 0
Admin Интересно Как короткий код превращает рабочую станцию в зомби. Новости в сети 0
Admin Интересно 20 часов до первого удара. Как ИИ-инструменты лишили системных администраторов сна. Новости в сети 0
Admin Интересно Форум SocioTech 2026: как объединить бизнес, информационную безопасность и персонал. Новости в сети 0
Admin Интересно GhostMail: как письмо о стажировке украло всю почту за 90 дней. Новости в сети 0
Admin Интересно Рынок шпионских программ: как посредники делают слежку анонимной и дорогой. Новости в сети 0
Admin Интересно Как быстро восстановить взломанный аккаунт: краткое руководство. Новости в сети 0
Admin Интересно Драйверы-предатели. Как легитимные программы помогают преступникам шифровать ваши данные. Новости в сети 0
Admin Интересно Практический онлайн-курс: как внедрить и настроить UserGate. Новости в сети 0
Admin Интересно Центральная предельная теорема: как случайности формируют закономерности. Новости в сети 0
Admin Интересно Как Mesh CSMA выявляет и устраняет пути атак на ключевые активы. Новости в сети 0
Admin Интересно Капча с двойным дном. Как обычное подтверждение, что вы не робот, превращается в установку шпиона. Новости в сети 0
Admin Интересно Кавычки решают всё. Как одна забытая проверка в коде подставила четверть миллиона владельцев сайтов. Новости в сети 0
Admin Интересно Спутники за миллиарды долларов боятся батарейки из супермаркета. Как военные и хулиганы «выключают» космос одной кнопкой. Новости в сети 0
Admin Интересно Anthropic запустила сервис для проверки кода, который работает как опытный разработчик. Новости в сети 0
Admin Интересно Как предотвратить утечку данных через ИИ: вебинар по аудиту современных агентских процессов. Новости в сети 0
Admin Интересно Фишинговая кампания перед выборами в Армении: как злоумышленники обошли защиту. Новости в сети 0
Admin Интересно Живые нейроны играют в «Doom»: как ученые заставили кусок плоти из пробирки расстреливать кибердемонов. Новости в сети 0
Admin Интересно Слишком сложно для Microsoft. Как три разработчика сделали сайт npm лучше, чем целая корпорация. Новости в сети 0
Admin Интересно Киберпреступники используют ICE как прикрытие для фишинговой кампании. Новости в сети 0
Admin Интересно Цифровой детокс по принуждению. Как юг Москвы неожиданно вернулся в эпоху до интернета. Новости в сети 0
Admin Интересно Как малый и средний бизнес использует исследования угроз и MDR для защиты. Новости в сети 0
Admin Интересно Claude AI демонстрирует, как технологии опережают правила и этику. Новости в сети 0
Admin Интересно Пчелиные соты, 24 измерения и нейросеть. Как ИИ проверил главную математическую работу десятилетия. Новости в сети 0
Admin Интересно Защита образования: как MDR может помочь школам в борьбе с киберугрозами. Новости в сети 0
Admin Интересно Укол вместо скальпеля. Ученые из MIT придумали, как вырастить «запасную» печень без операции. Новости в сети 0
Admin Интересно Робот стоит — лицо как живое. Улыбается — жуть. Пришлось собрать 200 тысяч 3D-лиц, чтобы научить машины мимике. Новости в сети 0
Admin Интересно Защита образования: как MDR помогает школам в борьбе с киберугрозами. Новости в сети 0
Admin Интересно Остров Рунет за триллион. Как Россия планирует окончательно отгородиться от мировой сети к 2028 году. Новости в сети 0

Название темы