Сохраняют ли хранимые процедуры SQL-инъекцию?

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

Является ли реализация хранимой процедуры в ядре PostgreSQL предотвращать атаки SQL-инъекций или это что-то еще? Или PostgreSQL также восприимчив к SQL-инъекции, даже если мы используем только хранимые процедуры? Если да, пожалуйста, покажите мне пример (например, книгу, сайт, документ и т. Д.).

81 голос | спросил Am1rr3zA 4 Jam1000000amTue, 04 Jan 2011 10:24:30 +030011 2011, 10:24:30

6 ответов


69

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

Этот код сервера sql:

CREATE PROCEDURE [dbo]. [sp_colunmName2]
    @columnName как nvarchar (30),
    @type как nvarchar (30),
    @searchText как nvarchar (30)
В ВИДЕ
НАЧАТЬ
    DECLARE @SQLStatement NVARCHAR (4000)
    НАЧАТЬ
        SELECT @SQLStatement = 'select * from Stations, где'
            + @columnName + '' + @type + '' + '' '' + @searchText + '' ''
        EXEC (@SQLStatement)
    КОНЕЦ
КОНЕЦ
ИДТИ

примерно эквивалентно postgres:

СОЗДАТЬ или заменить FUNCTION public.sp_colunmName2 (
    columnName varchar (30),
    тип varchar (30),
    searchText varchar (30)) RETURNS SETOF станции LANGUAGE plpgsql
В ВИДЕ
$$
DECLARE SQLStatement VARCHAR (4000);
НАЧАТЬ
    SQLStatement = 'select * from Stations, где'
            || columnName || '' || тип || '' || '' '' || searchText || '' '';
    RETURN QUERY EXECUTE SQLStatement;
КОНЕЦ
$$;

Идея разработчика заключалась в том, чтобы создать универсальную процедуру поиска, но результатом является то, что предложение WHERE может содержать все, что хочет пользователь, позволяя посетить немного Bobby Tables .

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

ответил Kyralessa 9 FebruaryEurope/MoscowbWed, 09 Feb 2011 21:15:19 +0300000000pmWed, 09 Feb 2011 21:15:19 +030011 2011, 21:15:19
44

Атаки SQL-Injection - это те, где ненадежный ввод представляет собой непосредственно добавленные запросы, позволяя пользователю эффективно выполнять произвольный код, как показано на этом каноническом XKCD-комиксе .

Таким образом, мы получаем ситуацию:

userInput = getFromHTML # «Robert») Студенты, занимающиеся кассовым столом, - «

Query = "Select * from students where studentName =" + userInput

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

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

создать сохраненный procdure foo (
выберите * у студентов, где studentName =: 1
);

Затем, когда программа желает получить доступ, она вызывает foo (userInput) и с радостью извлекает результат.

Хранимая процедура не является магической защитой от SQL-Injection, так как люди вполне способны записывать хранимые процедуры bad . Однако предварительно скомпилированные запросы, хранящиеся в базе данных или в программе, гораздо труднее открыть дыры безопасности в , если вы понимаете, как работает SQL-Injection.

Подробнее о SQL-Injection вы можете узнать:

ответил Brian Ballsun-Stanton 4 Jpm1000000pmTue, 04 Jan 2011 12:09:58 +030011 2011, 12:09:58
27

Да, в некоторой степени.
Только сохраненные процедуры не будут препятствовать внедрению SQL.

Позвольте мне сначала указать о SQL Injection из OWASP

  

Активация SQL-инъекций состоит из вставки или «инъекции» SQL-запроса через входные данные от клиента к приложению. Успешный эксплойт SQL-инъекции может считывать конфиденциальные данные из базы данных, изменять данные базы данных (вставка /обновление /удаление), выполнять операции администрирования в базе данных (например, выключение СУБД), восстанавливать содержимое данного файла, присутствующего в файле СУБД системы и в некоторых случаях выдавать команды операционной системе. Атаки SQL-инъекций - это тип инъекционной атаки, в которой SQL-команды вводятся в ввод данных в плоскости данных, чтобы выполнить выполнение предопределенных SQL-команд.

Вы должны дезинформировать пользовательские входы и не конкатенировать операторы SQL, даже если вы используете хранимую процедуру.

Джефф Этвуд объяснил последствия слияния sql в " Дайте мне параметризованный SQL или дайте мне смерть "

Ниже приведен интересный мультфильм, который приходит мне на ум, когда я слышу SQL Injection alt text Я думаю, вы поняли: -)

Взгляните на Cheat Sheet , методы профилактики подробно описаны ...

ответил CoderHawk 4 Jpm1000000pmTue, 04 Jan 2011 12:03:36 +030011 2011, 12:03:36
10

Конкатенация строк является причиной SQL Injection. Этого можно избежать с помощью параметризации.

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

Итак, ваш код выше вызван конкатенацией этих строк

  • exec sp_GetUser '
  • x 'AND 1 = (SELECT COUNT (*) FROM Client); -
  • ','
  • обезьяна

Это дает недопустимый синтаксис, к счастью

Параметризация дала бы

exec sp_GetUser 'x' 'AND 1 = (SELECT COUNT (*) FROM Client); --' , 'обезьяна'

Это означает

  • @UserName = x 'AND 1 = (SELECT COUNT (*) FROM Client); -
  • @Password = обезьяна

Теперь в приведенном выше коде вы не получите строк, потому что я предполагаю, что у вас нет пользователя x 'AND 1 = (SELECT COUNT (*) FROM Client); -

Если хранимый процесс выглядит так (используя конкатенированный динамический SQL ), то ваш параметризованный хранимый вызов proc все равно разрешит SQL Injection

...
SET @sql = 'SELECT userName от пользователей, где userName =' '' +
               @UserName +
               '' 'и userPass =' ​​'' +
               @Password +
               «» «»
EXEC (@sql)
....

Итак, как показано, конкатенация строк является основным врагом для SQL-инъекции

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

Вы можете посмотреть Stack Overflow для получения дополнительной информации о параметризации

ответил gbn 8 Mayam12 2012, 11:08:41
8

«Атаки SQL-инъекций происходят, когда пользовательский ввод неправильно закодирован. Обычно пользовательский ввод - это некоторые данные, которые пользователь отправляет с ее запросом, то есть значения в $ _ GET , $ _ POST, $ _ COOKIE, $ _ REQUEST или $ _ SERVER). Однако вход пользователя также может появиться из множества других источников, таких как сокеты, удаленные веб-сайты, файлы и т. д. Поэтому вы действительно должны обрабатывать все, кроме констант (например, 'foobar') как пользовательский ввод . "

Я недавно тщательно изучал эту тему и хотел бы поделиться с другими довольно интересным материалом, тем самым сделав этот пост более полным и поучительным для всех.



От YouTube


Материал из Википедии


Из OWASP


Из руководства PHP


От Microsoft и Oracle


Переполнение стека


Сканер внедрения SQL

ответил Ilia Rostovtsev 28 PM000000120000005431 2012, 12:22:54
1

Хранимые процедуры не волшебным образом предотвращают внедрение SQL, но они делают предотвращение намного проще. Все, что вам нужно сделать, это что-то вроде следующего (пример Postgres):

СОЗДАТЬ ИЛИ ЗАМЕНИТЬ ФУНКЦИЮ my_func (
  IN in_user_id INT
)
[Надрез]
  SELECT user_id, имя, адрес FROM my_table WHERE user_id = in_user_id; --BAM! SQL INJECTION IMMUNE !!
[Надрез]

Вот и все! Проблема возникает только при формировании запроса посредством конкатенации строк (т. Е. Динамического SQL), и даже в тех случаях, которые вы можете связать! (Зависит от базы данных.)

Как избежать SQL-инъекции в динамическом запросе:

Шаг 1) Спросите себя, действительно ли вам нужен динамический запрос. Если вы вставляете строки вместе, чтобы установить вход, тогда вы, вероятно, ошибаетесь. (Есть исключения из этого правила - одно исключение - это сообщение о запросах в некоторых базах данных, могут возникать проблемы с производительностью, если вы не вынуждаете его компилировать новый запрос с каждым исполнением. Но исследуйте этот вопрос, прежде чем переходить на него. )

Шаг 2) Изучите правильный способ установки переменной для вашей конкретной СУБД. Например, Oracle позволяет сделать следующее (цитируя их документы):

sql_stmt: = 'Сотрудники UPDATE SET зарплата = зарплата +: 1 WHERE'
           || v_column || '=: 2';
EXECUTE IMMEDIATE sql_stmt ИСПОЛЬЗОВАНИЕ amount, column_value; ИНИМАЦИЯ ИММУНИЗАЦИЯ !!

Здесь вы еще не конкатенируете ввод. Вы смело связываете! Ура!

Если ваша база данных не поддерживает что-то вроде вышеуказанного (надеюсь, что ни один из них все еще не так плох, но я не удивлюсь) - или если вам по-прежнему необходимо объединить ваши данные (например, в случае «иногда» отправляя запросы, как я намекал выше), тогда вы должны использовать правильную функцию экранирования. Не пишите сами. Например, postgres предоставляет функцию quote_literal (). Итак, вы запустите:

sql_stmt: = 'ВЫБЕРИТЕ зарплату от сотрудников WHERE name =' || quote_literal (in_name);

Таким образом, если in_name - это нечто вроде «[snip] или 1 = 1» (часть «или 1 = 1» означает выбор всех строк, позволяющих пользователю видеть зарплаты, которые он не должен!), then quote_literal сохраняет ваш прикладом, создав результирующую строку:

ВЫБЕРИТЕ зарплату ОТ сотрудников WHERE name = '[snip] или 1 = 1'

Никаких результатов не будет найдено (если у вас нет сотрудников с действительно странными именами.)

В этом суть! Теперь позвольте мне просто оставить вас со ссылкой на классический пост от гуру Oracle Тома Ките по теме SQL Injection, чтобы вести главную точку: Linky

ответил MWDB 10 AM00000060000005231 2015, 06:50:52

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132