Я в безопасности от SQL-инъекций? - PullRequest
3 голосов
/ 09 марта 2009

Я хотел бы знать, безопасен ли я от внедрения 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;--' );

Я в безопасности?

В каком случае мне можно сделать инъекцию?

Привет

Ответы [ 7 ]

7 голосов
/ 10 марта 2009

С точки зрения вашей процедуры вы выглядите в безопасности, поскольку переменная в SP не будет расширена до кода, но вы все равно можете разоблачить себя, если не используете параметризованный запрос, такой как "SELECT * FROM sp_list_name(?); "в вашем коде приложения . Пользователь может передать что-то вроде "SELECT * FROM sp_list_name('$start_name');", передав начальное имя "');delete from t_player where last_name NOT IN ('". Так что используйте параметризованный запрос или здравый смысл, проверьте свои входные данные в вашей программе.

NB: Обратите внимание, что переменная в хранимой процедуре не расширится до кода, даже если он содержит 'или;, (исключая передачу его в EXECUTE , для которого вы будете использовать функции quote_literal, а не функции ручного прокрутки replace), чтобы заменить; или 'совершенно не требуется (в хранимой процедуре, разумеется, приложение, использующее его, - это отдельная история) и не позволит вам всегда находить команды "tl;dr" или "O'Grady".

Лео Мур, Карл, LFSR Consulting : v_temp_name в хранимой процедуре НЕ будет расширен до кода в SP (нет EXECUTE ), проверка должна быть выполнена в приложении, а не в SP (или OP может просто использовать параметризованный запрос в своем коде приложения). То, что предлагают другие, похоже на беспокойство по поводу

my $bar = "foo; unlink('/etc/password');"; 
my $baz = $bar;

на самом деле работает unlink в отсутствие eval.

6 голосов
/ 09 марта 2009

Правило № 1 для предотвращения SQL-инъекций: очистите все входные данные, поступающие от кого-то / чего-то, кому вы не можете доверять / не можете контролировать.

Сама проблема заключается не в коде базы данных, а в приложении, которое выполняет эти операторы.

4 голосов
/ 10 марта 2009

Правильный способ защиты от SQL-инъекций - через Белый список * - длинные и короткие задают символы, которые вы собираетесь принять, и отфильтровывайте их.

Неправильный способ - Черный список - черный список того, какие символы не приняты, может привести к неприятностям, потому что вы не можете не отставать от атакующих. Существуют способы обхода черных списков через таблицы ASCII, экранирующие символы и тому подобное.

Кроме того, вот хороший шпаргалка , чтобы попробовать на вашем сайте. Запустите несколько тестов и попытайтесь привести к сбою.

* В приложении, а не в БД (спасибо Джеймс)

1 голос
/ 11 марта 2009

Ref. Белый листинг. Это нормально, если соблюдены определенные другие условия. Абсолютно необходимо разбить весь ввод данных в его простейшую форму, поэтому не просто проверяйте имена запросов SQL, одинарные кавычки и т. Д. Они могут быть представлены или закодированы с использованием других наборов символов, и именно это формирует часть белого списка не специально Сами ключевые слова SQL.

Я работал на конкретного клиента, который разрешил имя пользователя / пароль для защищенного ресурса (что в конечном итоге могло бы дать вам пропуск в безопасные части аэропорта!). Вы можете обойти поле входа в систему, введя 'и затем создавая SQL-запросы оттуда, чтобы получить учетные записи пользователей и пароли.

Проблема была в том, что клиент уже потратил 200 000 фунтов стерлингов на создание сайта с поставщиком, который, казалось, никогда раньше не занимался веб-разработкой. Исправление было еще 60 000 фунтов стерлингов, что было валидной функцией (), которая проверяла только объединение, выбор, наличие и другие ключевые слова. Когда его спросили о том, что они сделали для canicolisation / кодирования (что я тогда должен был объяснить), это было время перекатывания.

Дом разработчиков и (дорогой) проект получили консервы.

1 голос
/ 09 марта 2009

Вы не генерируете SQL для себя, так что это выглядит безопасно (для меня).

Я не знаю, откуда поступают данные, которые вы вызываете из хранимой процедуры. Таким образом, вы все равно должны защититься от переполнения буфера и т. Д.

0 голосов
/ 10 марта 2009

Просто сделайте замену вашего v_start_name, чтобы избавиться от ";" и т. д.

v_clean_name VARCHAR;
Select v_clean_name = Replace(v_start_name,';','');

Это заменит; с пробелами, препятствующими атаке SQL-инъекцией

Подробнее см. Строковые функции в PostgresSQL

Как прокомментировала LFSR Consulting. Лучше использовать WhiteList (т. Е. Не обрабатывать ввод с недопустимыми символами, такими как ';'), а не BlackList (т. Е. Пытаться очистить данные, поскольку пользователь также может выполнить атаку SQL-инъекцией на ваш Replace).

Для получения дополнительной информации посмотрите Атаки SQL-инъекции

0 голосов
/ 10 марта 2009

Вы можете рассмотреть возможность проверки содержания

v_start_name 
. Проверьте строку на наличие точек с запятой, символов комментария, равенства и т. Д. Не забудьте проверить значения как символов, так и шестнадцатеричных значений. Не забудьте разрешить использование дефиса, например «Смит-Браун», вероятно, является приемлемым, «Смит-Браун» - это, возможно, инъекция.

Если вы не знакомы с шестнадцатеричным в 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;

С уважением Karl

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...