Атаки подобного типа называются SQL-инъекциями (SQL-injection) и являются частным случаем атак, основанных на ошибках фильтрации и интерполяции строк. Мы словно впрыскиваем в форму запроса к базе данных собственную команду, прокалывая хакерской иглой тело уязвимого скрипта (отсюда и «инъекции»). Это не ошибка SQL-сервера (как часто принято считать). Это – ошибка разработчиков скрипта. Грамотно спроектированный скрипт должен проверять пользовательский ввод на предмет присутствия потенциально опасных символов (одиночная кавычка, точка с запятой, двойное тире, а для MySQL еще и символ звездочки) включая и их шестнадцатеричные эквиваленты, задаваемые через префикс «%», а именно: %27, %2A и %3B. Если хотя бы одно из условий фильтрации не проверяется или проверяется не везде (например, остаются не отфильтрованными строки URL или cookie), в скрипте образуется дыра, через которую его можно атаковать.
Впрочем, сделать это будет не так уж и просто. Необходимо иметь опыт программирования на Perl/PHP и знать, как может выглядеть та или иная форма запроса и как чаще всего именуются поля таблицы, в противном случае интерполяция ни к чему не приведет. Непосредственной возможности определения имен полей и таблиц у хакера нет, и ему приходится действовать методом слепого перебора (blinding).
Однако большинство администраторов и Web-мастеров слишком ленивы, чтобы разрабатывать все необходимые им скрипты самостоятельно, и чаще они используют готовые решения, исходные тексты которых свободно доступны в сети. Причем, большинство этих скриптов дырявы как ведро без дна. Взять, к примеру, тот же PHP Nuke, в котором обнаруживаются все новые и новые уязвимости.
Приблизительная стратегия поиска дыр выглядит так. Скачиваем исходные тексты PHP Nukе (или любой другой портальной системы), устанавливаем их на свой локальный компьютер, проходимся глобальным поиском по всем файлам, откладывая в сторонку все те, что обращаются к базе данных (вызов типа mysql_query/mysql_db_query или типа того). Далее прокручиваем курсор вверх и смотрим – где-то поблизости должна быть расположена строка запроса к базе (например: $query = «SELECT user_email, user_id FROM ${prefix}_users WHERE user_id = '$cookie[0]'»). Определяем имена переменных, подставляемых в базу, находим код, ответственный за передачу параметров пользовательского ввода и анализируем условия фильтрации.
В качестве наглядного примера рассмотрим одну из уязвимостей PHP Nuke 7.3, связанную с обработкой новостей. Соответствующий ей URL выглядит так: modules.php?name=News&file=categories&op=newindex&catid=1. По его внешнему виду можно предположить, что значение catid передается непосредственно в строке запроса к БД, и, если разработчик скрипта забыл о фильтрации, у нас появляется возможность модифицировать запрос по своему усмотрению. Для проверки этого предположения заменим catid с 1, допустим, на 669. Сервер немедленно отобразит в ответ пустой экран. Теперь добавим к нашему URL следующую конструкцию «'or'1'1='1» (полностью он будет выглядеть так: modules.php?name=News&file=categories&op=newindex&catid=669'or'1'='1). Сервер послушно отобразит все новостные сообщения раздела, подтверждая, что SQL-инъекция сработала!
Еще можно попытаться вызвать ошибку SQL, подсунув ей заведомо неправильный запрос (например, символ одиночной кавычки), и тогда она может сообщить много интересного. Отсутствие ошибок еще не означает, что скрипт фильтрует пользовательский ввод: быть может, он просто перехватывает сообщения об ошибках, что является нормальной практикой сетевого программирования. Также возможна ситуация, когда при возникновении ошибки возвращается код ответа 500 или происходит переадресация на главную страницу. Подобная двусмысленность ситуации существенно затрудняет поиск уязвимых серверов, но отнюдь не делает его невозможным!
Анализ показывает, что ошибки фильтрации встречаются в большом количестве скриптов (включая коммерческие), зачастую оставаясь неисправленными годами. Естественно, дыры в основных полях ввода давным-давно заткнуты, а потому рассчитывать на быстрый успех уже не приходится. Запросы, передаваемые методом POST, протестированы значительно хуже, поскольку передаются скрыто от пользователя и не могут быть модифицированы непосредственно из браузера, отсекая армаду начинающих «хакеров». Между тем, взаимодействовать с Web-сервером можно и посредством netcat (telnet), формируя POST-запросы вручную.
SQL-инъекции в очередной раз продемонстрировали миру, что программ без ошибок не бывает. Однако не стоит переоценивать их значимость. Мавр сделал свое дело, мавр может удалиться. Администраторы и девелоперы знают об опасности, и количество уязвимых сайтов тает с каждым днем. Реальную власть нас системой дают лишь принципиально новые методики атак, неизвестные широкой общественности. Найти их – наша с тобой задача. Освободи свой разум, перешагни грань неведомого и зайди на сервер с той стороны, с которой на него еще никто не заходил.
Вскрытие скрипта