Как генерировать строки, которые не уязвимы для внедрения SQL - PullRequest
0 голосов
/ 25 сентября 2018

У меня есть утилита, которая генерирует строки запроса, но статические анализаторы кода (и мои коллеги) жалуются из-за риска «Атака SQL-инъекцией» .

Вот мой C #код

    public static string[] GenerateQueries(string TableName, string ColumnName)
    {
        return new string[] {
            "SELECT * FROM " + TableName,
            "SELECT * FROM " + TableName + " WHERE 1=2",
            "SELECT * FROM " + TableName + " WHERE [" + TableName + "Id] = @id",
            "SELECT * FROM " + TableName + " WHERE [" + TableName + "Id] = IDENT_CURRENT('" + TableName + "')",
            "SELECT * FROM " + TableName + " WHERE [" + ColumnName + "] = @value"
        };
    }

В коде I всегда назовите его только с постоянными строками, такими как

var queryList = GenerateQueries("Person", "Name");

Есть ли способпереписать эту функцию, чтобы она была "безопасной"?Например, если бы я использовал C вместо C #, я мог бы написать макрос для безопасной генерации строк.

На данный момент единственный выбор, который у меня есть, - это copy/ paste этот блок инструкций SELECT для каждой таблицы , что является уродливым и трудоемким обслуживанием.

Является ли копирование / вставка действительно единственным вариантом?

РЕДАКТИРОВАТЬ:

Спасибо за ответы, особенно Уильям Лидер.Теперь я вижу, что мой вопрос ошибочен.Дело не только в том, что я объединяю строки запросов, но и храню их в переменной .Единственный правильный способ сделать это - построить SqlDataAdapter, используя константу , такую ​​как

var adapter = new SqlDataAdapter("SELECT * FROM PERSON");

Другого выбора нет.Так что да, будет много копирования / вставки.Я начинаю сожалеть, что не использовал EF.

Ответы [ 2 ]

0 голосов
/ 25 сентября 2018

Сначала я был шокирован, но, если подумать, это ничем не отличается от того, что в вашем коде уже есть оператор SQL, который выглядит следующим образом:

"SELECT * FROM Person"

Мы делаем такие вещи постоянно.

IF

Здесь есть важное предупреждение.Это остается верным , если вы можете контролировать, как вызывается функция.Так что если этот метод является приватным членом класса уровня данных где-то, вы могли бы быть в порядке.Но мне также интересно, насколько это полезно на самом деле.Похоже, вы не экономите много по сравнению с тем, что получаете от написания запросов.

Кроме того, нехорошо иметь привычку игнорировать инструменты статического анализа.Иногда они дают вам то, что вы знаете, что это неправильно, но вы все равно меняете это так, что когда они делают находят что-то важное, вы не обязаны игнорировать это.

0 голосов
/ 25 сентября 2018

Анализатор кода говорит вам, что вам, скорее всего, следует вызывать процедуру с некоторыми параметрами, а не отправлять SQL по проводам.

Это не имеет значения, независимо от того, используете ли вымакрос для генерации ваших операторов SQL. Если вы отправляете необработанный SQL по проводам, вы открыты для Атаки SQL-инъекций

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

Вы все еще можете полагаться на одну процедуру длявызывая ваши обновления, но если вы решите перейти к процедурам, зачем вам это нужно?

EDITED , чтобы привести пример

create PROC sp_CommonSelectFromTableProc @tableName varchar(32)
AS
   -- code to check the tableName parameter does not contain SQL and/or is a valid tableName

   -- your procedure code here will probable use 
   --  exec mydynamicSQLString  
   -- where mydynamicSQLString is constructed using @tableName  
END;

или, может быть, специфичная для таблицы процедура

create PROC sp_SelectFromSpecificTableProc 
AS
   SELECT * FROM SpecificTable
END;

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

Это просто явно, когда приложение содержит такие конструкции, как

return new string[] {
            "SELECT * FROM " + TableName,
            "SELECT * FROM " + TableName + " WHERE 1=2",
            "SELECT * FROM " + TableName + " WHERE [" + TableName + "Id] = @id",
            "SELECT * FROM " + TableName + " WHERE [" + TableName + "Id] = IDENT_CURRENT('" + TableName + "')",
            "SELECT * FROM " + TableName + " WHERE [" + ColumnName + "] = @value"

SQL-инъекция должна быть адресована на обоих концах канала данных.

Здесь является довольно хорошей отправной точкой для понимания того, как уменьшить атаки SQL Injection

...