#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, вы только что открыли для себя мир боли. Исправление заключается в том, чтобы ВСЕГДА использовать параметризованные запросы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)
.