PDA

Просмотр полной версии : Защита от атаки SQL-Injection



SDA
11.08.2005, 14:17
SQL-инъекция — это возможность пользователя неправомерно выполнять SQL-запросы на сервере. От этого определения, собственно, и нужно танцевать. Чтобы хакер не передал на сервер свой SQL-запрос, надо лишить его такой возможности, залатав все дыры. Рассмотрим небольшой пример.

Многие сайты имеют систему авторизации пользователя на сервере. Как правило, она реализована крайне просто: специальный скрипт сверяет введенные юзером логин/пароль с данными из базы, после чего выдает соответствующий результат. На практике это выглядит примерно так:

$valid = mysql_query("SELECT Username, Password FROM Users WHERE Username = ' ".$_POST['username']." ' and Password = ' ".$_POST['password']." ' ");

С первого взгляда вполне безопасный код, но… Стоит ввести в поле имени пользователя «' OR 1=1 #» (без кавычек), и серверу передастся следующий запрос:

SELECT Username, Password FROM Users WHERE Username = '' OR 1=1 #' and Password = ''

Хэш-символ (#) в SQL-запросах используется как указатель на комментарии, а все, что идет после него (все необходимые условия для выполнения запроса), сервером попросту игнорируется. Единица всегда равна единице (1=1), поэтому логическое условие OR 1=1 не накладывает ограничения на результат запроса. В итоге сервер, имея на то полные основания, вернет в качестве результата таблицу со всеми логинами и паролями. Как тебе?

Чтобы избавиться от бага, в нашем случае достаточно проверять введенную пользователем информацию на наличие кавычек. Не будет кавычек — не будет изменено условие запроса, а значит, не будет и инъекции. Для этого воспользуемся следующей функцией, которая добавляет перед кавычкой слэш и превращает его в управляющую последовательность: \'. Она не изменит запрос, а просто станет частью условия наравне со всеми остальными символами.

function safe_term($variable) {

$variable = addslashes(trim($variable));

return $variable;

}

А теперь с ее помощью изменим наш запрос:

$username = safe_term($_POST['username']);

$password = safe_term($_POST['password']);

$check = mysql_query("SELECT Username, Password, UserLevel FROM Users WHERE Username = ' ".$username." ' and Password = ' ".$password." ' ");