Предупреждение: атаки с использованием SQL-инъекций

#c# #interop #fxcop

#c# #взаимодействие #fxcop

Вопрос:

Я пытался адаптировать свой код к правилам FxCop и обнаружил это предупреждение: CA2100 Просматривает строку запроса, переданную в ‘OleDbDataAdapter.OleDbDataAdapter(строка, OleDbConnection)’ в ‘WavesShaperNew.Parse(строка, int)’ для возможных атак с использованием SQL-инъекций. Если строка составлена с использованием любого пользовательского ввода, рассмотрите возможность использования хранимой процедуры или параметризованного SQL-запроса вместо построения запроса с помощью конкатенаций строк.

Я искал на официальном сайте Microsoft и подобные вопросы, но все еще не понимаю, что означает это предупреждение и как его решить.

 ComboBox sheets = new ComboBox();
TextBox startRange = new TextBox();
TextBox endRange = new TextBox();

string query = string.Format("SELECT * FROM["   sheets.SelectedItem   startRange.Text   ":"   endRange.Text   "]");
query = query.Replace("'", "");

OleDbDataAdapter adapter = new OleDbDataAdapter(query, con);
  

Комментарии:

1. SELECT * FROM customers; delete from customers; blah blah blah Вы только что потеряли всех своих клиентов…. Когда вы обнаруживаете, что создаете параметры на основе пользовательского ввода и необработанного sql, вы только что открыли для себя мир боли. Исправление заключается в том, чтобы ВСЕГДА использовать параметризованные запросы

2. Или показан другой способ

3. @MichaelRandall Единственная проблема здесь заключается в том, что имена таблиц не могут быть параметризованы. Способ избежать SQL-инъекции здесь — внести имена таблиц в белый список.

4. @JohnathanBarclay и как было бы внести имена таблиц в белый список?

Ответ №1:

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

Однако имена таблиц не могут быть параметризованы.

Чтобы избежать SQL-инъекции здесь, вы можете внести допустимые имена таблиц в белый список:

 var queryableTables = new HashSet<string>
{
    "table1",
    "table2",
    // etc.
};

string tableName = sheets.SelectedItem   startRange.Text;

if (!queryableTables.Contains(tableName))
{
    throw new InvalidOperationException($"{tableName} is not queryable");
}

string query = $"SELECT * FROM [{tableName}]");
  

Комментарии:

1. Это не очень эффективно. «table1; удалить из table1;» по-прежнему является допустимым вводом, поскольку он содержит допустимое имя таблицы.

2. @oerkelens Нет, это не так. Contains здесь HashSet<T>.Contains нет string.Contains . Ваша логика применима к queryableTables.Any(tableName.Contains) .