Уязвимость усечения SQL возникает, когда база данных усекает вводимые пользователем данные из-за ограничения на длину. Злоумышленники могут собирать информацию о длине критического поля (например, имени пользователя) и использовать эту информацию для получения несанкционированного доступа. Злоумышленники могут войти в систему как другой пользователь, например, администратор, со своим зарегистрированным паролем.
Уязвимость усечения SQL обычно существует в базах данных MySQL. Эта уязвимость была впервые описана в CVE-2008-4106, который относился к CMS WordPress.
Как работают атаки усечения в SQL
Эта атака работает из-за усечения пользовательского ввода в базах данных с помощью функций «выбора» и «вставки».
- Когда ввод задан в поле формы, функция select проверяет избыточность, соответствующую вводам в базе данных.
- После проверки на избыточность функция «вставки» проверяет длину ввода, и ввод пользователя будет обрезан, если длина превысит.
Предположим, что разработчик создает таблицу «users» с помощью следующего запроса:
create table users( user_id INT NOT NULL AUTO_INCREMENT, user_name VARCHAR(20) NOT NULL, password VARCHAR(40) NOT NULL, PRIMARY KEY ( user_id ) );
Используя эту схему, если разработчик создает учетную запись администратора со следующим:
user_name = ‘admin’ password = “secret_p4ssw0ord”
Очевидно, что эти учетные данные не являются общедоступными. В базе данных есть только одна учетная запись администратора, и если злоумышленник попытается зарегистрировать другую учетную запись с именем пользователя «admin», злоумышленник потерпит неудачу из-за проверки избыточности базы данных. Злоумышленник может обойти эту проверку избыточности, чтобы добавить еще одну учетную запись администратора, используя уязвимость усечения SQL. Предположим, что злоумышленник регистрирует другую учетную запись со следующими данными:
User_name = ‘adminxxxxxxxxxxxxxxxrandom’ (x are the spaces) & Password = ”RandomUser”
База данных возьмет “user_name” (26 символов) и проверит, существует ли оно уже. Затем ввод user_name будет усечен, и в базу данных будет введено «admin » («admin» с пробелом), в результате чего появятся два дублирующих пользователя admin.
Затем злоумышленник может создать пользователя «admin» со своим собственным паролем. Теперь в базе данных есть две записи admin в поле ‘user_name’, но с разными паролями. Злоумышленник может войти в систему с вновь созданными учетными данными, чтобы получить панель администратора, поскольку имена пользователей «admin» и «admin » равны для уровня базы данных. Теперь мы рассмотрим образец практической атаки.
Образец атаки
В этом примере мы возьмем сценарий с веб-сайта overthewire.org. Сообщество Overthewire предоставляет CTF для варгеймов, на которых мы можем практиковать наши концепции безопасности. Сценарий усечения SQL происходит на уровнях игры natas26->27. Мы можем получить доступ к уровню, используя следующее:
URL: http://natas27.natas.labs.overthewire.org Username: natas27 Password: 55TBjpPZUUJgVP5b3BnbG6ON9uDPVzCJ
Этот уровень доступен по адресу: https://overthewire.org/wargames/natas/natas27.html. Вам будет показана страница входа в систему, которая уязвима для атаки усечения SQL.
Изучив исходный код, вы увидите, что длина имени пользователя равна 64.
Пользователь с именем natas28 уже существует. Наша цель – создать другого пользователя с именем natas28, используя атаку SQL_truncation. Итак, мы введем andreyex, затем 57 пробелов и случайный алфавит (в нашем случае a), имя пользователя и любой пароль. Буква «а» не видна на скриншоте из-за 65-значного имени пользователя. После создания учетной записи пользователя вы увидите значок «а».
Если база данных содержит уязвимость sql_truncation, то теперь в базе данных должно быть два имени пользователя andreyex. Одно имя пользователя будет содержать наш пароль. Попробуем ввести учетные данные на странице входа.
Смягчение
Чтобы смягчить эту атаку, нам нужно будет рассмотреть несколько факторов.
- Мы не должны допускать дублирования важных идентификаторов, таких как имя пользователя. Мы должны сделать эти удостоверения первичными ключами.
- Функция усечения должна быть реализована для всех полей форм внешнего интерфейса, а также для внутреннего кода, чтобы базы данных получали усеченные входные данные.
- Строгий режим должен быть включен на уровне базы данных. Без включенного строгого режима базы данных выдают только предупреждения в бэкэнде, но при этом сохраняют дублированные данные. В строгом режиме базы данных выдают ошибки в случае дублирования и избегают сохранения данных.
Например, давайте проверим строгий режим, используя следующий запрос:
mysql> select @@sql_mode
Мы создадим базу данных и таблицу «users».
mysql> CREATE DATABASE test Query OK, 1 row affected (0.02 sec) mysql> Use test Database changed mysql> CREATE TABLE users (username VARCHAR(10), password VARCHAR(10)); Query OK, 0 rows affected (0.05 sec)
Затем мы создадим пользователя-администратора с учетными данными с помощью запроса INSERT.
mysql> INSERT INTO users VALUES (‘admin’, ‘password1’); Query OK, 1 row affected (0.01 sec)
Мы можем увидеть информацию в таблице «users», используя опцию «select * from users».
Длина имени пользователя составляет 10 символов. Теперь мы попробуем атаку усечения SQL.
Когда мы пытаемся ввести следующее:
Username = ‘adminxxxxxa’ (x are the spaces) & Password = ‘pass2’
Мы получим ошибку, означающую, что строгий режим полностью эффективен.
mysql> INSERT INTO users values(‘admin a’, ‘pass2’) ERROR 1406 (22001): Data too long for column ‘username’ at row 1
Без включения строгого режима база данных будет выводить предупреждения, но все равно будет вставлять данные в таблицу.
Вывод
Злоумышленники могут получить доступ к учетным записям с высоким уровнем привилегий, если в вашем приложении существует уязвимость sql_trunction. Злоумышленник может легко получить информацию об имени пользователя и длине его базы данных, используя критические поля, а затем создать такое же имя пользователя, за которым следуют пробелы и случайный алфавит после минимальной длины, что приведет к созданию нескольких учетных записей с высоким уровнем привилегий. Эта уязвимость является критической, но ее можно избежать, если принять некоторые меры безопасности, такие как активация строгого режима для пользовательского ввода и установка конфиденциального поля в качестве первичного ключа в базе данных.