Создание безопасных операторов SQL в виде строк

Я использую С# и .NET 3.5. Мне нужно сгенерировать и сохранить некоторые инструкции вставки T-SQL, которые будут выполняться позже на удаленном сервере.

Например, у меня есть массив Employees:

new Employee[]
{
   new Employee { ID = 5, Name = "Frank Grimes" },
   new Employee { ID = 6, Name = "Tim O'Reilly" }
}

и мне нужно закончить массив строк, например:

"INSERT INTO Employees (id, name) VALUES (5, 'Frank Grimes')",
"INSERT INTO Employees (id, name) VALUES (6, 'Tim O''Reilly')"

Я просматриваю код, который создает инструкции insert в String.Format, но это не так. Я рассматривал использование SqlCommand (надеясь сделать что-то вроде этого), но он не предлагает способ комбинировать текст команды с параметрами.

Достаточно ли просто заменить одиночные кавычки и построить строку?

string.Format("INSERT INTO Employees (id, name) VALUES ({0}, '{1}')",
    employee.ID,
    replaceQuotes(employee.Name)
    );

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

EDIT: просто хочу указать, что в этом случае у меня нет SqlConnection или любого способа прямого подключения к SQL Server. Это конкретное приложение должно генерировать операторы sql и ставить их в очередь для выполнения где-то в другом месте - иначе я бы использовал SqlCommand.Parameters.AddWithValue()

Ответы

Ответ 1

Использовать параметризованные команды. Передайте параметры вместе с вашим удаленным сервером, и получите это, чтобы позвонить в SQL Server, все еще сохраняя различие между самим SQL и значениями параметров.

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

Ответ 2

Создайте свой объект SqlCommand следующим образом:

SqlCommand cmd = new SqlCommand(
        "INSERT INTO Employees (id, name) VALUES (@id, @name)", conn);

SqlParameter param  = new SqlParameter();
param.ParameterName = "@id";
param.Value         = employee.ID;

cmd.Parameters.Add(param);

param  = new SqlParameter();
param.ParameterName = "@name";
param.Value         = employee.Name;

cmd.Parameters.Add(param);

cmd.ExecuteNonQuery();

Ответ 3

Исправьте функцию замены кавычек следующим образом:

void string replaceQuotes(string value) {
     string tmp = value;
     tmp = tmp.Replace("'", "''");
     return tmp;
}

Ура!

Ответ 4

Хм, я согласен со всеми, что вы должны использовать параметризованные запросы и оставите это на этом. Но как вы собираетесь передавать эти SQL-заявления на ваш удаленный сервер? Есть ли у вас какой-то сервис, например веб-сервис, который будет принимать и выполнять произвольные команды Sql или ваше клиентское приложение сразу попадет в базу данных?

Если вы проходите через какой-то прокси-сервер, то независимо от того, насколько вы дезинфицируете свои данные на клиенте, хакер может просто обойти ваше приложение и воспользоваться сервисом. В этом случае сделайте то, что Cade рекомендует и передает данные как XML, например, или любой другой формат, который вы выберете (JSON, Binary и т.д.). Затем создайте свой SQL прямо перед тем, как выполнить команду.

Ответ 5

Чтобы избежать инъекции, вам необходимо отправить данные на удаленный сервер (возможно, в формате XML), а затем на удаленный сервер, данные должны быть преобразованы обратно в соответствующие типы данных и использованы в параметризованных запросах или сохраненных процедурах.