Безопасен ли я против SQL-инъекции
-
06-07-2019 - |
Вопрос
Я хотел бы знать, защищен ли я от SQL-инъекции, когда я использую что-то подобное с PostgresSQL:
CREATE or REPLACE FUNCTION sp_list_name( VARCHAR )
RETURNS SETOF v_player AS '
DECLARE
v_start_name ALIAS FOR $1;
r_player v_player%ROWTYPE;
v_temp VARCHAR;
BEGIN
v_temp := v_start_name || ''%'';
FOR r_player IN
SELECT first_name, last_name FROM v_player WHERE last_name like v_temp
LOOP
RETURN NEXT r_player;
END LOOP;
RETURN;
END;
' LANGUAGE 'plpgsql' VOLATILE;
Я хочу использовать эту функцию для перечисления имени игрока, начинающегося с буквы.
select * from sp_list_name( 'A' );
дает мне игроков с фамилиями , начинающимися на A.
Я попытался внедрить sql с помощью
select * from sp_list_name( 'A; delete from t_player;--' );
select * from sp_list_name( '''; delete from t_player;--' );
Я в безопасности ?
В каком случае мне можно было бы сделать инъекцию ?
С уважением
Решение
С точки зрения вашей процедуры вы кажетесь безопасными, поскольку переменная в SP не будет расширена в код, но вы все равно можете раскрыть себя, если не используете параметризованный запрос типа "SELECT * FROM sp_list_name(?);
" в твоем код приложения.Что - то вроде "SELECT * FROM sp_list_name('$start_name');
" может быть нарушен пользователем , передающим начальное имя "');delete from t_player where last_name NOT IN ('
".Поэтому используйте параметризованный запрос или проверьте правильность ваших входных данных в вашей программе.
ПРИМЕЧАНИЕ: Для других, пожалуйста, обратите внимание, что переменная в хранимой процедуре будет не разверните в код, даже если он содержит ' или ;, (исключая передачу его в ВЫПОЛНИТЬ, для чего вы бы использовали quote_literal
, не скрученный вручную replace
функции), таким образом, заменяя ;or ' совершенно не нужен (в хранимой процедуре приложение, использующее его, конечно, - это совсем другая история) и помешал бы вам всегда находить "tl;dr
" или "O'Grady
" команды.
Лео Мур, Карл, LFSR Consulting: v_temp_name
в хранимой процедуре будет НЕ быть расширен в код в SP (нет ВЫПОЛНИТЬ), проверка должна была бы выполняться в приложении, а не в SP (или вместо этого OP мог бы просто использовать параметризованный запрос в коде своего приложения).То, что предлагают другие, похоже на беспокойство о
my $bar = "foo; unlink('/etc/password');";
my $baz = $bar;
фактически выполняется отсоединение при отсутствии оценки.
Другие советы
Правило №1 для предотвращения sql-инъекции:Очистите все входные данные, поступающие от кого-то / чего-то, чему вы не можете доверять / не имеете контроля.
Сама проблема кроется не в коде базы данных, а в приложении, которое выполняет эти инструкции.
Правильный способ защиты от SQL-инъекции - это Белый список* - длинный и короткий - это набор символов, которые вы собираетесь принимать, и их фильтрация.
Неправильный способ заключается в том, чтобы Черный список - Черный список персонажей, которые не принимаются, приведет к неприятностям, потому что ты не можешь не отставайте от нападающих.Есть способы обойти черные списки с помощью таблиц ASCII, escape-символов и прочего.
Кроме того, вот хороший шпаргалка чтобы опробовать на вашем сайте.Запустите несколько тестов и попытайтесь добиться сбоя.
*
В приложении, а не в базе данных (спасибо Джеймсу)
Вы не генерируете SQL для себя, так что это выглядит безопасным (для меня).
Я не знаю, откуда берутся данные, которые вы вызываете в своей хранимой процедуре.Таким образом, вам все равно придется защищаться от переполнения буфера и т.д.
Ссылка.Белый список.Это нормально, если соблюдаются определенные другие условия.Абсолютно необходимо разбить весь ввод на простейшую форму, поэтому не просто проверяйте имена SQL-запросов, одинарные кавычки и т.д.Они могут быть представлены или закодированы с использованием других наборов символов, и именно это является частью белого списка, а не самих ключевых слов SQL.
Я работал на конкретного клиента, который разрешил использовать имя пользователя / пароль к защищенному ресурсу (что в конечном итоге могло бы дать вам пропуск в защищенные части аэропорта!).Вы могли бы обойти поле входа в систему, введя ' и затем создав оттуда SQL-запросы для извлечения учетных записей пользователей и паролей.
Проблема заключалась в том, что клиент уже потратил 200 тысяч фунтов стерлингов на создание сайта с поставщиком, который, похоже, никогда раньше не занимался веб-разработкой.Исправлением стало еще 60 тысяч фунтов стерлингов, которые были функцией validate(), которая проверяла только наличие ключевых слов union, select, having и других.Когда меня спросили о том, что они сделали для канонизации / кодирования (что мне пришлось потом объяснять), это было время перекати-поля.
Дом разработчиков и (дорогой) проект были законсервированы.
Вы могли бы рассмотреть возможность проверки содержания
v_start_name.Проверьте строку на наличие точек с запятой, символов комментариев, равенства и т.д.Не забудьте проверить наличие как символов, так и шестнадцатеричных значений.Не забудьте разрешить использование имени через дефис, например"Смит-Браун", вероятно, приемлем, "Смит-Браун" потенциально является инъекцией.
Если вы не знакомы с Hex в SQL-инъекции, ниже приведены краткие вводные
http://www.arejae.com/blog/sql-injection-attack-using-t-sql-and-hexadecimal.html
http://www.securityfocus.com/infocus/1768
DECLARE v_start_name ALIAS FOR $1; r_player v_player%ROWTYPE; v_temp VARCHAR; BEGIN -- new pseudo code here if v_start_name has bad chars exit with error message -- end pseudo code here v_temp := v_start_name || ''%''; FOR r_player IN SELECT first_name, last_name FROM v_player WHERE last_name like v_temp LOOP RETURN NEXT r_player; END LOOP; RETURN; END;
С уважением Карл
Просто замените ваше имя v_start_name, чтобы избавиться от ";" и т.д.ie
v_clean_name VARCHAR;
Select v_clean_name = Replace(v_start_name,';','');
Это заменит ;с пробелами, препятствующими атаке SQL-инъекцией
Для получения более подробной информации смотрите Строковые функции в PostgresSQL
Как также прокомментировала LFSR Consulting.Лучше внести в белый список (т. е. Не обрабатывать какие-либо входные данные с недопустимыми символами, такими как ';'), а не в черный список (т. е. попытаться очистить данные, поскольку пользователь может выполнить атаку SQL-инъекцией и на вашу замену).
Для получения дополнительной информации взгляните на Атаки с использованием SQL -инъекций