Рассмотрим представленный псевдоисходник:
http://quiz.ngsec.biz:8080/game1/level5/validate_achtung.txt

$result=mysql_db_query($db,"SELECT * FROM $table WHERE user='$login' AND pass='$password'");
$num_rows=mysql_num_rows($result);
mysql_close($link);
if ($num_rows!=0)
{ // AUTHENTICATION COMPLETED }
else
{ // AUTHENTICATION ERROR }
 

Как мы видим, авторизация проходит, если количество строк, которые вернул запрос, не равны нулю. Попробуем такие значения переменных login и password (с кавычками):

' or ''='

Тогда sql-строка будет такой:

SELECT * FROM $table WHERE user='' or ''='' AND pass='' or ''=''

что означает то же самое, что 

SELECT * FROM $table WHERE false or true AND false or true

или просто SELECT * FROM $table

Такой запрос вернет все строки, содержащиеся в таблице. Т.к. их число больше 0, авторизация будет успешной... Но нам надо не совсем это.

Мы можем знать результат обработки запроса с точностью до двух вариантов:

а) Запрос вернул 0 строк, тогда скрипт сообщит "авторизация неудачна"
б) Запрос вернул больше 0 строк, тогда скрипт сообщит "авторизация пройдена".

Этим мы и воспользуемся для "чтения" данных из таблицы. Попробуем подставить username: dgkjsdhfgkjdfhskgj (при том же пароле, что и выше). Авторизация успешна. Это означает одно из двух: либо есть такой пользователь с каким-нибудь паролем, либо sql считает, что false AND false OR true - это true. Догадаемся, что верным является второй вариант.

Первый шаг - подберем какой-нибудь правильный пароль. При любом username в качестве пароля подставим (опять с кавычками):

' or pass>'a

Авторизация пройдена.

Перебираем буквы: a, b, c, d... и получаем наконец:

' or pass>'u

Авторизация не пройдена. Так мы узнали, что ни один из паролей из таблице не "больше", чем 'u'. Очевидно, что наибольший пароль либо начинается на 't', либо равен 'u'. Второй вариант мы исключаем проверкой:

' or pass='u

Подбираем следующие символы. В конце концов
мы получим, что один из паролей равен t34t53g3t34t - определенно, его набивали случайным
стучанием по клавиатуре.

Дальше аналогичным способом мы подбираем имя пользователя, соответствующее этому паролю: в качестве пароля вводим уже не что-нибудь с кавычками, а "нормальный" пароль, а username подбираем тем же методом. Получается, что username равен fgergbrwbregre - опять кто-то стучал по клаве.

Ну и последнее - проверяем, есть ли в таблице другие строки. В качестве имени пользователя опять подставим "универсальное" (то, что в самом начале), а в качестве пароля -

' or ''='' and user<>'fgergbrwbregre

Авторизация неудачна. Это значит, что в таблице нет других пользователей (или есть, но с таким же username). Вот и все.

  • Подпишись на наc в Telegram!

    Только важные новости и лучшие статьи

    Подписаться

  • Подписаться
    Уведомить о
    0 комментариев
    Межтекстовые Отзывы
    Посмотреть все комментарии