Здесь $userlogin – переменная, содержащая имя пользователя, а $userPassword – его пароль. Обрати внимание, что обе переменные размещены внутри текстовой строки, окаймленной кавычками. Это необычно для Си, но типично для интерпретируемых языков вроде Perl и PHP. Подобный механизм называется интерполяцией строк и позволяет автоматически подставлять вместо переменной ее фактическое значение.
Допустим, пользователь введет KPNC/passwd. Тогда строка запроса будет выглядеть так: «select * from userTable where login = 'KPNC' and password = 'passwd'».
Если такой логин/пароль действительно присутствует в базе, функция сообщает идентификатор результата, в противном случае возвращается FALSE.
Хочешь войти в систему под именем другого пользователя, зная его логин, но не зная пароль? Воспользуйся тем, что механизм интерполяции позволяет атакующему воздействовать на строку запроса, видоизменяя ее по своему усмотрению. Посмотрим, что произойдет, если вместо пароля ввести последовательность «fuck' or '1'= '1» (без кавычек): «select * from userTable where login = 'KPNC' and password = 'fuck' or '1' = '1'».
Смотри: кавычка, стоящая после fuck, замкнула пользовательский пароль, а весь последующий ввод попал в логическое выражение, навязанное базе данных атакующим. Поскольку один всегда равен одному, запрос будет считаться выполненным при любом введенном пароле и SQL-сервер возвратит все-все-все записи из таблицы (в том числе и не относящиеся к логину KPNC)!
Рассмотрим другой пример: «SELECT * FROM userTable WHERE msg='$msg' AND ID=669».
Здесь msg – номер сообщения, извлекаемого из базы, а ID – идентификатор пользователя, автоматически подставляемый скриптом в строку запроса и непосредственно не связанный с пользовательским вводом. Константная переменная использована по соображениям наглядности, в конечном скрипте будет, скорее всего, использована конструкция типа: ID='$userID'. Чтобы получить доступ к остальным полям базы (а не только к тем, чей ID равен 669), необходимо отсечь последнее логическое условие. Это можно сделать, внедрив в строку пользовательского ввода символы комментария («-» и «/*» для MS SQL и MySQL соответственно). Текст, расположенный правее символов комментария, игнорируется. Если вместо номера сообщения ввести «1' AND ID=666 -», строка запроса примет следующий вид: «SELECT * FROM userTable WHERE msg='1' and ID= 666 -' AND ID=669» .
Как следствие, атакующий получит возможность самостоятельно формировать ID, читая сообщения, предназначенные совсем для других пользователей.
Причем одним лишь видоизменением полей SELECT'а дело не огранивается, и существует угроза прорыва за его пределы. Некоторые SQL-сервера поддерживают возможность задания нескольких команд в одной строке, разделяя их знаком «;„, что позволяет атакующему выполнить любые SQL-команды, какие ему только заблагорассудится. Например, последовательность « '; DROP TABLE 'userTable' -“, введенная в качестве имени пользователя или пароля, удаляет всю userTable!
Еще атакующий может сохранять часть таблицы в файл, подсовывая базе данных запрос типа «SELECT * FROM userTable INTO OUTFILE 'FileName'». Соответствующий ему URL уязвимого скрипта может выглядеть, например, так: www.victim.com/admin.php?op=login&pwd=123&aid=Admin'%20INTO%20OUTFILE%20'/path_to_file/pwd.txt, где path_to_file – путь к файлу pwd.txt, в который будет записан админовский пароль. Удобное средство для похищения данных, не так ли? Главное – размесить файл в таком месте, откуда его потом будет можно беспрепятственно утянуть, например, в одном из публичных WWW-каталогов. Тогда полный путь к файлу должен выглядеть приблизительно как: «../../../../WWW/myfile.txt» (точная форма запроса зависит от конфигурации сервера). Но это еще только цветочки! Возможность создания файлов на сервере позволяет засылать на атакуемую машину собственные скрипты (например, скрипт, дающий удаленный shell – « passthru($cmd) ?> »). Естественно, максимальный размер скрипта ограничен предельно допустимой длиной формы пользовательского ввода, но это ограничение зачастую удается обойти ручным формированием запроса в URL или использованием SQL-команды INSERT INTO, добавляющей новые записи в таблицу.
Скорректированный URL-запрос может быть таким:таким:/*.
Последний запрос работает только на MySQL версии 4.х и выше, поддерживающей union (объединение нескольких запросов в одной строке). Здесь table1 – имя таблицы, содержимое которой необходимо вывести на экран.