Например, у меня есть пример кода ниже.
updateData(Dictionary<string,string> data){
string strTemp = string.Empty;
foreach(KeyValuePair<string, string> values in data){
strTemp = values.Key + "='" values.Value + "',";
}
string query = "update tablename set " + strTemp + "modDate = sysdate"
//execute query against oracle db
}
Не зная, что находится в словаре, данных и очень мало зная об остальной части приложения, как лучше всего защититься от SQL-инъекций? Могу ли я динамически параметризовать как имена столбцов, так и значения?
Динамически параметризуйте значения. Внесите ключи в белый список; они не могут быть параметризованы, и вы, вероятно, действительно не хотите позволять им касаться всех столбцов в любом случае.
Вы действительно можете динамически построить параметризуемый запрос. Другой подход - Prepared Statements - имел ограничение, которое не позволяло сделать это безопасно.





«Пуленепробиваемый» способ избежать внедрения SQL - это параметризация вашего запроса:
UpdateData(Dictionary<string,string> data) {
var assignments = string.Join(
", "
, data.Keys.Select(key => $"{0}=:{0}", key)
);
string query = $"update tablename set {assignments}, modDate = sysdate"
//execute query against oracle db
Command cmd = ...
foreach (var kvp in data) {
cmd.Parameters.AddWithValue(kvp.Key, kvp.Value);
}
...
}
Сначала в оператор assignments добавляется строка FieldName=:FieldName, состоящая из частей UPDATE. После этого каждый элемент из словаря data привязывается к соответствующему параметру с помощью метода AddWithValue в сборе параметров SQL.
Примечание: Приведенное выше предполагает, что у вас есть полный контроль над ключами в словаре data, потому что они должны соответствовать именам столбцов в вашей таблице. Если весь словарь поступает из внешнего ввода, важно, чтобы вы проверили ключи по метаданным вашей таблицы перед построением запроса, чтобы предотвратить попытку использования имен ключей для SQL-инъекции.
Что, если имена ключей в data являются значениями, использующими SQL-инъекцию?
@BillKarwin Верно, я сделал предположение, что ключи предварительно проверены. Я отредактировал ответ, чтобы прямо заявить об этом. Спасибо!
Спасибо за редактирование. Хотя это маловероятно (и находится под вашим контролем), вполне законно иметь столбец с именем ; drop table users --. Если вы не уверены, что можете избежать этого имени столбца, тогда ваш запрос должен разделять имена столбцов.
@BillKarwin Вы правы. Однако разделение имен в Oracle создает дополнительную проблему, потому что, как только вы указываете идентификатор, он становится чувствительным к регистру.
просто передайте параметр в свой запрос sql, вот и все