Опасная уязвимость в популярной библиотеке Sequelize

Привет, Хабр! Данная статья будет интересна тем, кто уже использует библиотеку Sequelize или же только собирается с ней работать. Под катом мы расскажем, чем встроенный функционал operatorAliases может быть вреден и как избежать утечки из собственной базы данных.

Что такое Sequelize, где он используется и для чего?

Sequelize — это ORM-библиотека на Node.js для Postgres, MySQL, MariaDB, SQLite и Microsoft SQL Server, которая осуществляет сопоставление таблиц в бд и отношений между ними с классами. При использовании Sequelize мы можем не писать SQL-запросы, а должны работать с данными как с обычными объектами. Она имеет надежную поддержку транзакций, отношения, активную и отложенную загрузку, репликацию чтения и многое другое.

Что за опция operatorAliases, и в чем заключается ее опасность?

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

А сама опция operatorAliases позволяет установить, будут ли доступны операторы-псевдонимы. Вот как выглядит пример активации в коде:

Когда все работает правильно

Рассмотрим код демо-приложения. Файл модели user.model.js содержит:

Видно, что в таблице пользователей есть три поля, и они все имеют строковой тип данных.

Файл контроллера auth.controller.js содержит:

В коде используется метод findOne к модели User. И метод findOne возвращает первую строку из базы данных, согласно переданному условию запроса. В данном случае, приложение получает от пользователя данные username и password, применяет их в запрос к таблице users.

Сгенерированный в данном случае запрос будет выглядеть примерно так:
SELECT `id`, `username`, `email`, `password`, `createdAt`, `updatedAt` FROM `users` AS `users` WHERE `users`.`username` = :username AND `users`.`password` = :password LIMIT 1;

Поскольку используется ORM для формирования запросов, банальная SQL-инъекция не сработает. Если в базе не найдется совпадений по пользователю, приложение вернет ошибку User Not found. В случае совпадений вводных данных на уровне базы данных приложение сравнит введенный пароль с паролем, хранящимся в базе, и либо вернет ошибку «Invalid Password!» при несовпадении, либо токен авторизации в случае успеха. Алгоритм проверки вводных данных выбран специально для тестирования уязвимости.

Таблица будет содержать такие данные:



Авторизация работает исправно.

А что же с операторами и псевдонимами?


Псевдонимы обозначаются символом “$”, синтаксис псевдонимов схож с MongoDB. Нам доступны операторы поиска, сравнения и многие другие. Не смотря на строгую типизацию данных в модели, передача данных от пользователя в ORM в формате JSON влечет за собой нормализацию. И тут начинается самое интересное!

Когда беда стучится в DOM

Групповая атака (Batching attack)

Такого вида запрос к приложению инициирует запрос к базе:
Executing (default): SELECT `id`, `username`, `email`, `password`, `createdAt`, `updatedAt` FROM `users` AS `users` WHERE `users`.`username` IN (‘admin’, ‘more’, ‘much more’) AND `users`.`password` = ‘wrong pass’ LIMIT 1;

При помощи этой атаки можно за один запрос к серверу проверить на валидность много логинов на конкретный пароль и наоборот. Атака работает в последней на декабрь 2020 версии библиотеки (6.3.5) и при выключенной опции operatorsAliases.

Атака преобразования типов данных

Если передать приложению данные вида…

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

Атака при помощи операторов сравнения

По данным на скришоте будет сгенерирован запрос в базу вида:
SELECT `id`, `username`, `email`, `password`, `createdAt`, `updatedAt` FROM `users` AS `users` WHERE `users`.`username` = ‘admin’ AND `users`.`password` != ‘aaa’ LIMIT 1;

База данных возвращает данные, так как есть совпадение username = admin и пароля, не равного “aaa”. Для того чтобы пройти процесс авторизации полностью, нам необходимо достать пароль.

Атака операторов регулярных выражений и поиска в строке

Получить исходные данные можно, используя псевдонимы операторов поиска $like или операторов для работы с регулярными выражениями $regexp.

Когда символ не сойдется, возникнет ошибка, что пользователь не найден.

Если символ сойдется, будет ошибка о неверном пароле. В базу выполняется запрос вида:
SELECT `id`, `username`, `email`, `password`, `createdAt`, `updatedAt` FROM `users` AS `users` WHERE `users`.`username` = ‘admin’ AND `users`.`password` LIKE ‘E%’ LIMIT 1;

Таким образом, посимвольно можно восстановить данные из таблицы.

Атака сравнения столбцов в таблице

Есть интересный псевдоним $col, который позволяет сравнить поле с полем.

Запрос в базу будет:
SELECT `id`, `username`, `email`, `password`, `createdAt`, `updatedAt` FROM `users` AS `users` WHERE `users`.`username` = ‘admin’ AND `users`.`password` = `aaaaa` LIMIT 1;

Выполнит в базу следующий запрос:
SELECT `id`, `username`, `email`, `password`, `createdAt`, `updatedAt` FROM `users` AS `users` WHERE `users`.`username` = ‘admin’ AND `users`.`password` = `password` LIMIT 1;
Тем самым выполнив логическое условие на уровне базы данных.

Избавляемся от уязвимостей

  • Необходимо установить последнюю версию библиотеки Sequalize, где была убрана поддержка псевдонимов.

    (Источник)
  • Отключить использование псевдонимов, установив значение operatorAliases: false.
  • Тщательно проверять типы и их значения данных от пользователя до их использования в ORM.

Спасибо за интерес!

Let’s block ads! (Why?)

Read More

Recent Posts

VK купила 40% билетной платформы Intickets.ru

VK объявляет о приобретении 40% компании Intickets.ru (Интикетс). Это облачный сервис для контроля и управления продажей билетов на мероприятия. Сумма…

19 часов ago

OpenAI готовится запустить поисковую систему на базе ChatGPT

OpenAI готовится запустить собственную поисковую систему на базе ChatGPT. Информацию об этом публикуют западные издания. Ожидается, что новый поисковик может…

1 день ago

Роскомнадзор рекомендовал хостинг-провайдерам ограничить сбор данных с сайтов для иностранных ботов

Центр управления связью общего пользования (ЦМУ ССОП) Роскомнадзора рекомендовал компаниям из реестра провайдеров ограничить доступ поисковых ботов к информации на российских сайтах.…

2 дня ago

Apple возобновила переговоры с OpenAI и Google для интеграции ИИ в iPhone

Apple возобновила переговоры с OpenAI о возможности внедрения ИИ-технологий в iOS 18, на основе данной операционной системы будут работать новые…

7 дней ago

Российская «дочка» Google подготовила 23 иска к крупнейшим игрокам рекламного рынка

Конкурсный управляющий российской «дочки» Google подготовил 23 иска к участникам рекламного рынка. Общая сумма исков составляет 16 млрд рублей –…

1 неделя ago

Google завершил обновление основного алгоритма March 2024 Core Update

Google завершил обновление основного алгоритма March 2024 Core Update. Раскатка обновлений была завершена 19 апреля, но сообщил об этом поисковик…

1 неделя ago