Последствия многолетней уязвимости в SQLite

Интересный баг в одной из самых популярных встраиваемых СУБД.

В SQLite найдена уязвимость 22-летней давности, которую в теории могут использовать для DoS и выполнения произвольного кода.

В октябре 2022 года исследователи из компании Trail of Bits опубликовали подробный разбор уязвимости в СУБД SQLite. В статье приводятся варианты возможных атак через CVE-2022-35737, последствия которых варьируются от простого «падения» приложения до выполнения произвольного кода. Достаточно тривиальная ошибка в коде SQLite представляет интерес и несет потенциальную опасность по двум причинам. Во-первых, она присутствует в SQLite с октября 2000 года, то есть практически с самого начала разработки этого программного продукта с открытым исходным кодом. Во-вторых, особенности использования SQLite делают теоретически возможной атаку на большой ассортимент программ, которые используют SQLite в своей работе.

Особенности SQLite

SQLite — компактная встраиваемая СУБД с открытым исходным кодом, первый релиз которой состоялся 22 года назад, в августе 2000 года. «Встраиваемая» — в данном случае самое главное определение. SQLite не устанавливается как отдельное программное обеспечение. Вместо этого она используется в качестве библиотеки для разработчиков ПО, которым требуется работать с какой-либо базой данных. Это совершенно базовая функциональность огромного количества программ и операционных систем. SQLite по умолчанию встроена в Android, множество дистрибутивов операционных систем на базе ядра Linux, браузеры Google Chrome, Firefox и Safari, сетевые приложения и так далее. Причинами популярности SQLite являются открытая лицензия, надежность и, что немаловажно в данной истории, безопасность. Серьезных ошибок в коде СУБД пока действительно было обнаружено немного.

Детали уязвимости CVE-2022-35737

Эксперты обнаружили ошибку в коде функции sqlite3_snprintf, используемой для взаимодействия с базой данных в программах, написанных на языках C/C++. Если передать этой функции очень большую строку (огромную, размером более двух гигабайт), это приведет к падению программы и ошибке, то есть становится возможной атака типа «отказ в обслуживании». В коде sqlite3_snprintf использовалась целочисленная переменная для подсчета размера переданной строки. В случае если строка передается слишком большая, переменная может принимать отрицательное значение. Это, в свою очередь, приводит к выделению буфера памяти для записи полученной строки слишком маленького размера. Возникает распространенная ошибка переполнения буфера.

Скорее всего, ошибка была внесена в код 22 года назад из-за того, что передача гигабайтных параметров функции тогда была маловероятной из-за ограниченных ресурсов. Сейчас дело обстоит по-другому. Отдельным интересным моментом в отчете Trail of Bits являются предположения о том, почему такая ошибка была пропущена в ходе стандартного тестирования кода. Процедура тестирования прежде всего нацелена на проверку вновь добавляемого или изменяемого кода, здесь же код не менялся в течение более двух десятилетий. Довольно сложно обнаруживать такие уязвимости и при помощи фаззинга — автоматической подачи произвольных параметров на вход какой-то функции. Распространенные методы фаззинга не предполагают генерацию строк такого большого объема. Авторы исследования говорят, что фаззинг не может полностью заменить статический анализ кода, в том числе выполняемый вручную.

Туманные последствия

Изначальную атаку типа «отказ в обслуживании» в Trail of Bits смогли «модернизировать» до выполнения произвольного кода, аккуратно манипулируя содержимым и размером передаваемого параметра. Хотя авторы работы и показали рабочий proof of concept, демонстрирующий возможности атаки, примеры представляют собой чисто теоретическое упражнение по атаке на саму SQLite. Но, как было сказано выше, SQLite является встраиваемой СУБД, соответственно в реальных условиях речь должна идти об атаке на какое-то приложение, в которое встроен код для работы с базами данных.

Получается достаточно много допущений, и практическую возможность эксплуатации уязвимости (получившей идентификатор CVE-2022-35737) еще предстоит доказать. Существуют и другие ограничения. По данным разработчиков SQLite, ошибка релевантна только для использования интерфейса для приложений на C и только в случае компиляции кода с определенными параметрами. Исследователи Trail of Bits сами указывают на невозможность атаки, если SQLite была скомпилирована с использованием так называемых stack canaries. Это по сути дополнительный метод защиты от атак, связанных с переполнением буфера, предотвращающий выполнение произвольного кода даже в случае, когда само переполнение возможно.

Уязвимость была закрыта в версии SQLite 3.39.2, выпущенной в июле 2022 года. Но в данном случае наличие заплатки мало на что влияет. Разработчики ПО, использующие SQLite в составе собственного кода, скорее всего, должны будут обновить свои разработки и распространить новую версию софта. До этого уязвимость будет присутствовать. И не стоит забывать, что многие программы с SQLite внутри уже не поддерживаются.

Насколько уязвимость опасна, возможна ли ее практическая эксплуатация — пока непонятно. Судя по определению разработчиков SQLite, шансы на атаку «в реальных условиях» небольшие, хотя и отличные от нуля. А пока что данный баг пополнил коллекцию долгоживущих ошибок, которые потенциально могут добавить головной боли разработчикам программного обеспечения .

Советы