提问人:Neema 提问时间:4/21/2018 最后编辑:Neema 更新时间:9/21/2018 访问量:760
保护动态生成的 SQL 查询免受 SQL 注入的影响。C#
Protect a dynamically generated SQL query from SQL injections. C#
问:
例如,我在下面有一些示例代码。
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 注入的最佳方法是什么?是否可以动态参数化列名和值?
答:
1赞
Sergey Kalinichenko
4/21/2018
#1
避免 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);
}
...
}
首先,将部分组成的字符串添加到语句中。之后,字典中的每个项目都使用 SQL 参数集合上的方法绑定到其相应的参数。assignments
FieldName=:FieldName
UPDATE
data
AddWithValue
注意:上面假设您对字典中的键具有完全控制权,因为它们必须与表中的列名匹配。如果整个字典来自外部输入,则必须在构造查询之前根据表的元数据验证键,以防止尝试利用键名称进行 SQL 注入。data
评论
0赞
Bill Karwin
4/21/2018
如果中的键名称是利用 SQL 注入的值,该怎么办?data
1赞
Sergey Kalinichenko
4/21/2018
@BillKarwin 是的,我在这里做了一个假设,即密钥是预先验证的。我编辑了答案以明确说明这一点。谢谢!
0赞
Bill Karwin
4/21/2018
感谢您的编辑。尽管这不太可能(并且在您的控制之下),但拥有一个名为 .如果不确定是否可以避免使用该列名,则查询应分隔列名。; drop table users --
0赞
Sergey Kalinichenko
4/21/2018
@BillKarwin 你是对的。但是,在 Oracle 中分隔名称会带来额外的挑战,因为一旦您引用标识符,它就会变得区分大小写。
评论