Сохраняют ли хранимые процедуры SQL-инъекцию?
Правда ли, что хранимые процедуры предотвращают атаки SQL-инъекций на базы данных PostgreSQL? Я провел небольшое исследование и выяснил, что SQL Server, Oracle и MySQL не являются безопасными для SQL-инъекций, даже если мы используем только хранимые процедуры. Однако эта проблема не существует в PostgreSQL.
Является ли реализация хранимой процедуры в ядре PostgreSQL предотвращать атаки SQL-инъекций или это что-то еще? Или PostgreSQL также восприимчив к SQL-инъекции, даже если мы используем только хранимые процедуры? Если да, пожалуйста, покажите мне пример (например, книгу, сайт, документ и т. Д.).
6 ответов
Нет, хранимые процедуры не предотвращают 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-инъекцию.
Атаки 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 вы можете узнать:
- В этой дискуссии Джефф Этвуд
- предупреждение об обмане
- Как атаковать свой собственный код (убедитесь, что ваш QA включает тестирование безопасности. Если это не так, ваш сайт будет проверен на безопасность снаружи. Это плохая вещь.)
Да, в некоторой степени.
Только сохраненные процедуры не будут препятствовать внедрению SQL.
Позвольте мне сначала указать о SQL Injection из OWASP
Активация SQL-инъекций состоит из вставки или «инъекции» SQL-запроса через входные данные от клиента к приложению. Успешный эксплойт SQL-инъекции может считывать конфиденциальные данные из базы данных, изменять данные базы данных (вставка /обновление /удаление), выполнять операции администрирования в базе данных (например, выключение СУБД), восстанавливать содержимое данного файла, присутствующего в файле СУБД системы и в некоторых случаях выдавать команды операционной системе. Атаки SQL-инъекций - это тип инъекционной атаки, в которой SQL-команды вводятся в ввод данных в плоскости данных, чтобы выполнить выполнение предопределенных SQL-команд.
Вы должны дезинформировать пользовательские входы и не конкатенировать операторы SQL, даже если вы используете хранимую процедуру.
Джефф Этвуд объяснил последствия слияния sql в " Дайте мне параметризованный SQL или дайте мне смерть "
Ниже приведен интересный мультфильм, который приходит мне на ум, когда я слышу SQL Injection
Я думаю, вы поняли: -)
Взгляните на Cheat Sheet , методы профилактики подробно описаны ...
Конкатенация строк является причиной 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 для получения дополнительной информации о параметризации
«Атаки SQL-инъекций происходят, когда пользовательский ввод неправильно закодирован. Обычно пользовательский ввод - это некоторые данные, которые пользователь отправляет с ее запросом, то есть значения в $ _ GET
, $ _ POST
, $ _ COOKIE
, $ _ REQUEST
или $ _ SERVER
). Однако вход пользователя также может появиться из множества других источников, таких как сокеты, удаленные веб-сайты, файлы и т. д. Поэтому вы действительно должны обрабатывать все, кроме констант (например, 'foobar'
) как пользовательский ввод . "
Я недавно тщательно изучал эту тему и хотел бы поделиться с другими довольно интересным материалом, тем самым сделав этот пост более полным и поучительным для всех.
- Предотвращение SQL-инъекций с помощью PHP от John Nebel
- Уголок безопасности - SQL-инъекция Криса Шифлетта
- Неожиданная инъекция SQL от Александра Андонова
- Mysql_real_escape_string () по сравнению с подготовленными заявлениями Илья Алшанецкого
- Атака и защита SQL от Sagar Joshi
- Атаки на SQL-инъекции профессора Джима Уайтхеда
- addslashes () vs mysql_real_escape_string () от Chris Шифлетт
-
Что такое ошибка SQL Injection от Joel Spolsky
- Предотвращение внедрения MySQL-SQL
- Прохождение SQL-инъекций
- Шифрование SQL Injection Cheat
- Подготовленные выражения в PHP и MySQLi
От YouTube
- Миграции SQL Injection & Ошибки: лучшие практики защиты Билла Карвина
- Учебники по PHP: безопасность - SQL-инъекция
- Как внедрить SQL с помощью SQLMAP в Backtrack5 RC1
Материал из Википедии
Из OWASP
- SQL Injection
- Руководство по внедрению SQL
- OWASP - предотвращение внедрения SQL
- Шлюз для защиты от инъекций SQL
- Тестирование для SQL-инъекций >
Из руководства PHP
- SQL Injection
- класс PDO - подготовленные операторы и хранимые процедуры
- улучшенное расширение MySQL
- mysql_real_escape_string ()
От Microsoft и Oracle
- <аhref = "http://blogs.msdn.com/b/brian_swan/archive/2010/03/04/what_2700_s-the-right-way-to-avoid-sql-injection-in-php-scripts_3f00_.aspx" rel = "nofollow noreferrer"> Каков правильный способ предотвратить внедрение SQL в PHP-скрипты Microsoft
- Остановить атаки SQL-инъекций, прежде чем они остановят вас от Microsoft
- Защита от SQL-инъекций от Oracle
Переполнение стека
- SQL-инъекции и библиотека ADOdb! Общая безопасность веб-сайта PHP с примерами
- Лучший способ предотвратить SQL Injection в PHP
- Внедрение XKCD SQL - объясните, пожалуйста,
- Каков наилучший способ избежать SQL-инъекций атаки?
- Что такое SQL-инъекция?
- SQL-инъекция на INSERT
- Как защитить эту функцию от SQL-инъекция?
- Достаточно ли параметров, чтобы предотвратить инъекции Sql?
- Есть ли сегодня инъекция SQL?
- SQL Injection
- Этические взломы SQL Injection
- Предотвращает ли этот код инъекцию SQL?
Сканер внедрения SQL
Хранимые процедуры не волшебным образом предотвращают внедрение 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