Обход аутентификации через SQLI
Рассмотрим классический случай аутентификации с помощью SQL-инъекции.
Цель-развить «правильное» мышление или не «правильное». В приложении для проверки пользователя в аутентификации иcпользуется следующая классическая конструкция:
SELECT * FROM table WHERE user-name = '$user' AND password = '$pass'
где $user и $pass — данные от пользователя.
To есть если пользователь с указанным именем и (AND) паролем существует, то все ОК — пропускай.
А для того, чтобы обойти аутентификацию, у нас есть пара вариантов.
Первый послать в обоих полях «' OR 1 ='1», и тогда логика в ПО будет примерно такой:
SELECT * FROM table WHERE username = ' ' OR 1='1' AND password = ' ' OR 1='1'
По сути элементарное добавление ветвления и логики. И к каждой части проверки мы добавляем выражение, которое даст положительный результат в любом случае (or 1=1 — всегда true).
Второй классический вариант — «' OR 1 = 1 --». Мы выставляем логическое выражение только для первой проверки с username, а остальную часть комментируем (AND password = "):
SELECT * FROM table WHERE username = ' ' OR 1=1-- AND -password = ''
Давайте посмотрим на это подробней.
Вариант 1.
Он основывается на сравнение нескольких строк.
Например, выражение «'aaa'= 'ааа'='ааа'» возможно. И данное выражение возвратит нам true. И даже такое выражение тоже будет true «'aaa'= 'bbb'='ccc'».
Почему так и где логика? Согласен, странное поведение MySQL Наверно тебе тоже интересно?! В Сети можно найти следующее объяснение:
Предположим, у нас есть выражение «'aaa'= 'bbb'='ccc'». MySQL его приводит к виду «('aaa'= 'bbb')='ccc'». И проводит первое сравнение: ааа — это не bbb, значит — false. Хотя, если говорить точнее, это не совсем false (с точки зрения типов), а 0. Что тоже распространенная практика в приведении типов.
И теперь мы имеем выражение «0='ccc'», которое по логике должно быть опять-таки false. Так как 0 — это тип integer, а ссс — строка, то MySQL необходимо привести последнюю к числовому значению. Но MySQL приводит «ссс» тоже к нулю, так как считает, что это ближайшее числовое значение. В итоге мы имеем сравнение «0=0».
Таким образом, для обхода аутентификации нам надо вставить в оба поля «aaa'='bbb», а с учетом возможности использования пустых строк мы упрощаем до вида «'='»:
SELECT * FROM table WHERE username = ' ' = ' ' AND password = ' ' = ' '
В итоге получаем два тройных сравнения с пустыми строками, результатами каждого из которых будет true. Смотрим дальше.
Вариант 2.
Атакуем логику: в первое поле вводим «' or 1=1 OR "='», во второе — «1» (хотя все равно что). В итоге мы получим:
SELECT * FROM table WHERE username = ‘ ‘ or 1=1 OR ‘ ‘ = ‘ ‘ and password ='1'
В итоге мы меняем логику выражений за счет добавления дополнительного OR. И имеем два выражения, соединенных «OR»:
1. «username = " or 1=1», которое всегда будет true из-за "1=1";
2. «"=" and password ='1'», которое всегда будет false из-за некорректности пароля.
Мы убираем проверку пароля и получим "true OR false", то есть опять-таки обход аутентификации. Чем этот метод проще классических?
Возможным упрощением.
Избавляемся от «"="» , оставив пустую строку «"» во второй части выражения. На логику это не влияет. А далее меняем «OR» на «||».
Далее «| | 1=1» на логический эквивалент — «-0» и избавляемся от пробелов.
В ходе этих преобразований мы все до короткой формы. В логин вводим «'-0| |'», в пароль — как обычно «1», а в приложении имеем следующее:
SELECT * FROM table WHERE username = ' '-0||' ' AND password ='1'
Аутентификация удалась.
Автор: xvzL Просмотров: 2918