Для защиты от данного типа атак необходимо тщательно фильтровать входные параметры, значения которых будут использованы для построения SQL-запроса.
Фильтрация строковых параметров
Предположим, что код, генерирующий запрос (на языке программирования Паскаль), выглядит так: statement := 'SELECT * FROM users WHERE name = "' + userName + '";'; Чтобы внедрение кода (закрытие строки, начинающейся с кавычки, другой кавычкой до её завершения текущей закрывающей кавычкой для разделения запроса на две части) было невозможно, для некоторых СУБД, в том числе, для MySQL, требуется брать в кавычки все строковые параметры. В само́м параметре заменяют кавычки на \", апостроф на \', обратную косую черту на \\ (это называется «экранировать спецсимволы»). Это можно делать таким кодом: statement := 'SELECT * FROM users WHERE name = ' + QuoteParam(userName) + ';'; function QuoteParam(s : string) : string; { на входе — строка; на выходе — строка в кавычках и с заменёнными спецсимволами } var i : integer; Dest : string; begin Dest := '"'; for i:=1 to length(s) do case s[i] of '''' : Dest := Dest + '\'''; '"' : Dest := Dest + '\"'; '\' : Dest := Dest + '\\'; else Dest := Dest + s[i]; end; QuoteParam := Dest + '"'; end;
Для PHP фильтрация может быть такой:
$query = "SELECT * FROM users WHERE user='".mysql_real_escape_string($user)."';"; ?> Фильтрация целочисленных параметров
Возьмём другой запрос: statement := 'SELECT * FROM users WHERE id = ' + id + ';'; В данном случае поле id имеет числовой тип, и его чаще всего не берут в кавычки. Поэтому «закавычивание» и замена спецсимволов на escape-последовательности не проходит. В таком случае помогает проверка типа; если переменная id не является числом, запрос вообще не должен выполняться.
Например, на Delphi для противодействия таким инъекциям помогает код: if TryStrToInt(id, id_int) then statement := Format('SELECT * FROM users WHERE id = %0:d;', [id_int]); Для PHP этот метод будет выглядеть так: $query = 'SELECT * FROM users WHERE id = ' . (int)$id;
Усечение входных параметров
Для внесения изменений в логику выполнения SQL-запроса требуется внедрение достаточно длинных строк. Так, минимальная длина внедряемой строки в вышеприведённых примерах составляет 8 символов («1 OR 1=1»). Если максимальная длина корректного значения параметра невелика, то одним из методов защиты может быть максимальное усечение значений входных параметров.
Например, если известно, что поле id в вышеприведённых примерах может принимать значения не более 9999, можно «отрезать лишние» символы, оставив не более четырёх:
statement := 'SELECT * FROM users WHERE id = ' + LeftStr(id, 4) + ';';