Member 14479161 Ответов: 2

Как изменить хранимую процедуру, имеющую обычный оператор select, чтобы предотвратить атаки SQL-инъекций?


Если у меня есть такой код SQL

create procedure selectStatment
as
begin 
   select * from spacific_table;
end;


как я могу гарантировать, что SQL-инъекция невозможна?

Что я уже пробовал:

Я попытался добавить параметр в процедуру, но он не работает

Patrice T

"я попытался добавить prameter в порядке, но я то ничего лучше обычного работает"
Покажите, что вы пробовали, это самое интересное.

2 Ответов

Рейтинг:
6

OriginalGriff

Этот оператор SELECT (и, следовательно, хранимая процедура) не уязвим для SQL-инъекции, поскольку он вообще не использует никаких строк, а тем более тех, которые могут содержать вредный материал. Все, что он делает, это выбирает все столбцы и все строки из таблицы; everythign фиксируется заранее.

Когда вы объединяете строки, вы вызываете проблемы, потому что SQL получает такие команды, как:

SELECT * FROM MyTable WHERE StreetAddress = 'Baker's Wood'
Цитата, добавленная пользователем, завершает строку в том, что касается SQL, и вы получаете проблемы. Но могло быть и хуже. Если я приду и наберу вместо этого: "x';DROP TABLE MyTable;--", то SQL получит совсем другую команду:
SELECT * FROM MyTable WHERE StreetAddress = 'x';DROP TABLE MyTable;--'
Которые SQL видит как три отдельные команды:
SELECT * FROM MyTable WHERE StreetAddress = 'x';
Совершенно правильный выбор
DROP TABLE MyTable;
Вполне допустимая команда "удалить таблицу"
--'
А все остальное-это комментарии.
Так оно и происходит: выбирает любые совпадающие строки, удаляет таблицу из базы данных и игнорирует все остальное.

Таким образом, вы уязвимы только тогда, когда вы объединяете строки, и вы этого не делаете вообще!


Member 14479161

это означает, что если я объединяю a select statment со значением, которое приходит из текстового поля с помощью'+', то это может быть сделано для SQL Injectio in asp.net

MadMyche

Да, и эта уязвимость является языковой агностикой.
Это влияет почти на все языки программирования, которые будут говорить с любым вкусом RDBMSSQL.

Рейтинг:
15

MadMyche

Вызов хранимой процедуры и добавление строки к команде имеет почти одинаковый уровень риска внедрения SQL.

Чтобы добавить параметр в хранимую процедуру, вы добавляете его на уровне объявления. Обратите внимание, что скобки (в любом случае ниже) не требуются, но я использую их для удобства чтения

CREATE PROCEDURE selectSttment (
  @ParamName1 INT
) as
BEGIN 
  SELECT *
  FROM   spacific_table
  WHERE  (ID = @ParamName1)
END
Это мой общий способ вызова хранимой процедуры в C# (VB очень похож). Используя using блок будет выполнять очистку всех ресурсов, используемых в нем, поэтому большая часть кода в нем наконец это лишнее.. но это хорошая практика, чтобы использовать все три в try...catch...finally
string CmdName = "selectSttment";
int IDtoFind = 123;
SqlDataReader reader;
using (SqlConnection conn = new SqlConnection("ConnectionInfo")) {
   using (SqlCommand cmd = new SqlCommand(CmdName, conn)) {
      cmd.CommandType = CommandType.StoredProcedure;
      cmd.Parameters.AddWithValue("@ParamName1", IDtoFind);

      try {
         conn.Open();
         reader = cmd.ExecuteReader();
         // your script to read...
      }
      catch (SqlException sx) {
         // your error handling for SQL specific exception
      }
      catch (Exception ex) {
         // your error handling for general exception
      }
      finally {
         // cleanup code regardless of success
         cmd.Dispose();
         conn.Close();
         conn.Dispose();
      }
   }
}


Maciej Los

5ed!

Richard Deeming

С using блоки, все о коде в законе finally блок не нужен. :)

Но вы должны были бы обернуть его SqlDataReader в using блок тоже.

const string CmdName = "selectSttment"; // Make it "const" so you can't inject values.
int IDtoFind = 42;

using (SqlConnection conn = new SqlConnection("..."))
using (SqlCommand cmd = new SqlCommand(CmdName, conn))
{
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.Parameters.AddWithValue("@ParamName1", IDtoFind);
    
    conn.Open();
    using (SqlDataReader reader = cmd.ExecuteReader())
    {
        while (reader.Read())
        {
            ...
        }
    }
}

MadMyche

Согласился, и я сделал предисловие к Кодексу так что большая часть кода в finally является излишней.

Member 14479161

вы передаете параметр на asp.net файл но что делать если я не хочу передавать этот параметр

const string CmdName = "selectSttment"; // Make it "const" so you can't inject values.
int IDtoFind = @ParamName1;

using (SqlConnection conn = new SqlConnection("..."))
using (SqlCommand cmd = new SqlCommand(CmdName, conn))
{
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.Parameters.AddWithValue("@ParamName1", IDtoFind);
    
    conn.Open();
    using (SqlDataReader reader = cmd.ExecuteReader())
    {
        while (reader.Read())
        {
            ...
        }
    }
}
<pre>

MadMyche

Вы спросили о добавлении параметра, и я показал вам, как это сделать.
Если вы хотите, чтобы этот параметр был необязательным, то вы устанавливаете значение по умолчанию в объявлении хранимой процедуры и соответствующим образом корректируете ее

CREATE PROCEDURE selectSttment (
   @ParamName1 INT = -1
) as
BEGIN
   IF ( @ParamName1 > 0) BEGIN
      SELECT *
      FROM   spacific_table
      WHERE  (ID = @ParamName1)
   END; ELSE BEGIN
      SELECT *
      FROM   spacific_table
   END
END