
Уведомление и воспроизводитель AddressSanitizer для переполнения буфера в куче (heap-buffer-overflow) в SQLite SQLAR, вызванного специально сформированным значением SZ, приводящим к усечённому выделению памяти и записи за пределами буфера в zlib.
CVE-2026-39113 — это переполнение буфера в куче в опциональном расширении SQLAR для SQLite. В приложении, загрузившем это расширение, атакующий, способный вызвать sqlar_uncompress() с управляемым сжатым blob и размером, может заставить zlib выполнить запись за пределами выделенной области кучи в системе LP64. Это нарушение границ памяти внутри процесса хоста; это не проблема разбора файлов базы данных SQLite, не обход аутентификации и не уязвимость, достижимая в каждом развёртывании SQLite по умолчанию.
Уязвимое поведение было внесено 2026-03-11 коммитом Git 169f68e (Fossil check-in 8bdc0d485e3ad0c7...) и исправлено 2026-04-01 коммитом Git 34e139d (Fossil check-in 6194f3b5314ef98b...). Затронутая область — снапшоты исходного кода и пользовательские сборки от 169f68e до родителя 34e139d. Ни один официальный релиз SQLite не был подтверждён как уязвимый: SQLite 3.52.0 предшествует внесению изменения, а SQLite 3.53.0 содержит как вносящее изменение, так и исправление. Таким образом, SQLite 3.53.0 — это первый официальный релиз, содержащий исправленный код, а не затронутый релиз.
Я проверил точную уязвимую ревизию, вносящее и исправляющее изменения, а также снапшоты релизов 3.52.0 и 3.53.0. Я также изучил сохранённый вывод авторизованного запуска в одноразовом окружении WSL2 Ubuntu 24.04. AddressSanitizer обнаружил переполнение буфера в куче с последующим завершением процесса, что подтверждает повреждение нативной кучи и отказ в обслуживании. Выполнение кода продемонстрировано не было.
SQLAR — это формат архивов SQLite. Опциональное расширение в ext/misc/sqlar.c регистрирует sqlar_compress() и sqlar_uncompress() как SQL-функции. Оно не является частью каждого приложения, использующего SQLite; уязвимый путь требует наличия и загрузки расширения.
В рамках этого отчёта Мэллори контролирует аргументы blob и SZ, передаваемые в:
SELECT sqlar_uncompress(?1, ?2);
В тестируемом окружении int был 32-битным, а sqlite3_int64 и zlib uLongf — 64-битными. Функция должна выделять как минимум столько памяти, сколько zlib разрешено записывать. Вместо этого уязвимый исходный код преобразует 64-битный размер в 32-битный тип параметра sqlite3_malloc(), сохраняя полное значение для uncompress().
Уязвимый снапшот исходного кода выводил Configuring SQLite version 3.53.0 во время конфигурирования. Эту строку версии для разработки не следует путать с официальным релизом SQLite 3.53.0 от 2026-04-09, исходный код которого содержит исправление.
В оцениваемой ревизии функция sqlarUncompressFunc() в ext/misc/sqlar.c считывает управляемый атакующим размер как 64-битное целое число:
sqlite3_int64 sz;
sz = sqlite3_value_int64(argv[1]);
Если sz положителен и отличается от длины входного blob, это же значение используется двумя несовместимыми способами:
uLongf szf = sz;
const Bytef *pData = sqlite3_value_blob(argv[0]);
Bytef *pOut = sqlite3_malloc(sz);
if( pOut==0 ){
sqlite3_result_error_nomem(context);
}else if( Z_OK!=uncompress(pOut, &szf, pData, nData) ){
sqlite3_result_error(context, "error in uncompress()", -1);
}
В этой ревизии SQLite объявляет sqlite3_malloc(int). В тестируемой сборке LP64 значение PoC 4294967328 (0x100000020) превратилось в 32 при передаче в этот API, тогда как szf сохранил полное 64-битное значение. Таким образом, SQLite выполнил небольшое выделение памяти, но zlib было сообщено, что выходной буфер может вмещать более 4 ГиБ. Распаковка 42-байтового blob, представляющего 4096 байт данных, затем пересекла границу выделенной области.
Несоответствие попало в проект, когда изменение от 2026-03-11 заменило sqlite3_value_int() на sqlite3_value_int64() без изменения API выделения памяти. Анализ исходного кода SQLite 3.52.0 показывает более раннее 32-битное чтение, поэтому несоответствия «полная ширина / короткое выделение» там не было. Исправление от 2026-04-01 изменило выделение на sqlite3_malloc64(sz). Анализ исходного кода официального тега 3.53.0 подтверждает этот исправленный вызов.
Продемонстрированный примитив — это запись за пределами кучи в процессе, размещающем SQLite. Сохранённый запуск показывает, что AddressSanitizer обнаруживает первую недопустимую запись размером один байт сразу после 40-байтовой области кучи, выделенной через sqlite3_malloc(), после чего следует аварийное завершение. Это напрямую подтверждает возможность краха процесса и отказа в обслуживании.
Для эксплуатации требуются все следующие условия:
sqlar_uncompress() с управляемым blob и значением SZ;int имеет разрядность 32 бита, а sqlite3_int64 и zlib uLongf — 64 бита; иPoC контролирует распакованные байты, что значимо для оценки серьёзности повреждения нативной кучи. Однако превращение этого примитива в выполнение кода зависело бы от раскладки аллокатора, состояния процесса, средств смягчения и подходящего маршрута на уровне приложения. Такая цепочка не тестировалась и не демонстрировалась, поэтому данный отчёт не заявляет о выполнении кода.
Сохранённый запуск не включал отрицательный контроль времени выполнения против исправленной ревизии. Две проверки на уровне исходного кода сужают объяснение: SQLite 3.52.0 считывает размер через 32-битный API, а официальный исходный код 3.53.0 выделяет память через sqlite3_malloc64(). Эти проверки подтверждают установленные внесение и исправление, но не представлены как выполненные тесты против исправленной цели. Распространённость приложений, загружающих это опциональное расширение, неизвестна.
Репозиторий включает:
poc/verify_sqlar_poc.c, который создаёт полезную нагрузку размером 4096 байт, сжимает её, загружает sqlar.so и привязывает SZ = 4294967328;poc/reproduce.sh, который клонирует зафиксированные ревизии SQLite и zlib, собирает их с AddressSanitizer, компилирует расширение и обвязку и запускает триггер; иevidence/asan-summary.txt — нормализованный по путям сводный отчёт о наблюдавшемся авторизованном запуске.Запускайте репроузер только в одноразовом окружении Linux или WSL. Он намеренно вызывает повреждение памяти и аварийное завершение AddressSanitizer. Скрипт требует git, make, компилятор C, стандартные инструменты сборки и доступ к сети:
chmod +x poc/reproduce.sh
./poc/reproduce.sh
Репроузер был запущен повторно 2026-08-21 на Ubuntu 24.04 под WSL2 и дал тот же результат AddressSanitizer. Его релевантный вывод был:
env: sizeof(int)=4 sizeof(sqlite3_int64)=8 sizeof(uLongf)=8
payload: plain=4096 compressed=42 evil_sz=4294967328 low32=32
ERROR: AddressSanitizer: heap-buffer-overflow
WRITE of size 1
#0 inflate_fast zlib/inffast.c:252
#4 uncompress zlib/uncompr.c:100
#5 sqlarUncompressFunc sqlite/ext/misc/sqlar.c:97
The write occurred immediately after a 40-byte heap region.
SUMMARY: AddressSanitizer: heap-buffer-overflow in inflate_fast
ABORTING
PoC exit status: 1
Этот вывод показывает несовместимые разрядности типов и сформированный размер, запись zlib, вызов из sqlarUncompressFunc() и нарушение границы выделенной области. Скрипт воспроизведения удаляет свой временный каталог сборки при выходе, если не задан KEEP_BUILD=1.
Вышестоящий проект (upstream) исправил уязвимое выделение памяти в коммите 34e139d:
- Bytef *pOut = sqlite3_malloc(sz);
+ Bytef *pOut = sqlite3_malloc64(sz);
Это сохраняет разрядность выделения согласованной с положительным 64-битным значением sz, сохраняемым в uLongf szf и передаваемым в zlib. Исправленный код присутствует в официальном SQLite 3.53.0. Пользователям снапшотов исходного кода или пользовательских сборок, содержащих уязвимый интервал, следует обновиться до 34e139d или более поздней версии. Приложениям, которым не требуется SQLAR, следует избегать загрузки расширения, а приложениям, которые его используют, следует не позволять недоверенным вызывающим сторонам передавать произвольные аргументы в sqlar_uncompress().
Целевой регрессионный тест должен проверять SQL-функцию с допустимым сжатым blob и значением SZ выше INT_MAX, младшие 32 бита которого малы. Он должен убедиться, что исправленная сборка не выполняет усечённое выделение памяти, и должен сохранять обычные случаи успешной распаковки и ошибок при недопустимых входных данных в качестве контролей.
CVE-2026-39113 затрагивает только снапшоты исходного кода SQLite и пользовательские сборки от 169f68e до родителя 34e139d, когда загружено опциональное расширение SQLAR и управляемые атакующим вызовы достигают sqlar_uncompress() в сборке LP64. 64-битный размер был сужен функцией sqlite3_malloc(int), тогда как zlib сохранял полное значение, что приводило к подтверждённому AddressSanitizer переполнению буфера в куче и аварийному завершению процесса. Ни один официальный релиз SQLite не был подтверждён как уязвимый, и выполнение кода продемонстрировано не было. Изменение вышестоящего проекта на sqlite3_malloc64(sz) присутствует в официальном SQLite 3.53.0 и устраняет несоответствие разрядности выделения.