使用 C# 检测破坏性 SQL 查询
detectecting destructive SQL queries with C#
所以我希望找到一种更有效的方法来确定我编写的这段 C# 代码中数组中字符串的所有变体。我可以遍历整个字符串并将 sqltext 中的每个字符与它之前的字符进行比较并使其过于复杂,或者我可以尝试学习新的东西。我在想必须有一种更有效的方法。我把它拿给一位同事看,她建议我使用正则表达式。我稍微研究了正则表达式,但似乎找不到正确的表达式。
我正在寻找的是一个版本,它采用这段代码中数组索引的所有变体:
public bool securitycheck(String sqltext)
{
string[] badSqlList = new string[] {"insert","Insert","INSERT",
"update","Update","UPDATE",
"delete","Delete","DELETE",
"drop","Drop", "DROP"};
for (int i = 0; i < badSqlList.Count(); i++)
{
if (sqltext.Contains(badSqlList[i]) == true)
{
return true;
}
}
return false;
}
但考虑到替代拼写。例如,这段代码没有考虑 "iNsert, UpDate, dELETE, DrOP" 但根据我的同事的说法,有一种使用正则表达式来考虑这一点的方法。
您认为最好的方法是什么?
[更新]
谢谢大家,这里有很多非常好的信息,它确实让我大开眼界以编程方式处理 SQL。我正在构建的这个工具的范围非常小,任何有权访问这个工具并且有恶意的人都是可以直接访问数据库的人。这些检查或多或少地防止了懒惰。用例不允许参数化查询,否则我会这样做。您的见解很有教育意义,感谢您的所有帮助!
你可以这样做:
if (badSqlList.Any(r => sqltext.IndexOf(r, StringComparison.InvariantCultureIgnoreCase) >= 0))
{
//bad SQL found
}
IndexOf
与 StringComparison
枚举值将确保不区分大小写的比较。
另一种方法可能是:
return sqltext.Split()
.Intersect(badSqlList,StringComparer.InvariantCultureIgnoreCase)
.Any()
Split
你的 Sql 白色 space 然后将每个单词与你的白名单数组进行比较。如果您的 合法 table 名称包含 INESRTEDStudents
等关键字,这可以为您节省时间
不太确定您的要求,但是,通常,更好的选择是首先使用参数化查询。你不能 100% 确定你的白名单,仍然有办法绕过它。
不要重新发明轮子 - 就像这里的每个人告诉你的那样使用参数化查询(解决比你目前意识到的更多的问题),你会感谢所有在未来...
但是请务必使用它来清理 WHERE
子句中的所有过滤器字符串:
public static string EscapeSpecial(string s)
{
Contract.Requires(s != null);
var sb = new StringBuilder();
foreach(char c in s)
{
switch(c)
{
case '[':
case ']':
case '%':
case '*':
{
sb.AppendFormat(CultureInfo.InvariantCulture, "[{0}]", c);
break;
}
case '\'':
{
sb.Append("''");
break;
}
default:
{
sb.Append(c);
break;
}
}
}
return sb.ToString();
}
所以我希望找到一种更有效的方法来确定我编写的这段 C# 代码中数组中字符串的所有变体。我可以遍历整个字符串并将 sqltext 中的每个字符与它之前的字符进行比较并使其过于复杂,或者我可以尝试学习新的东西。我在想必须有一种更有效的方法。我把它拿给一位同事看,她建议我使用正则表达式。我稍微研究了正则表达式,但似乎找不到正确的表达式。
我正在寻找的是一个版本,它采用这段代码中数组索引的所有变体:
public bool securitycheck(String sqltext)
{
string[] badSqlList = new string[] {"insert","Insert","INSERT",
"update","Update","UPDATE",
"delete","Delete","DELETE",
"drop","Drop", "DROP"};
for (int i = 0; i < badSqlList.Count(); i++)
{
if (sqltext.Contains(badSqlList[i]) == true)
{
return true;
}
}
return false;
}
但考虑到替代拼写。例如,这段代码没有考虑 "iNsert, UpDate, dELETE, DrOP" 但根据我的同事的说法,有一种使用正则表达式来考虑这一点的方法。
您认为最好的方法是什么?
[更新]
谢谢大家,这里有很多非常好的信息,它确实让我大开眼界以编程方式处理 SQL。我正在构建的这个工具的范围非常小,任何有权访问这个工具并且有恶意的人都是可以直接访问数据库的人。这些检查或多或少地防止了懒惰。用例不允许参数化查询,否则我会这样做。您的见解很有教育意义,感谢您的所有帮助!
你可以这样做:
if (badSqlList.Any(r => sqltext.IndexOf(r, StringComparison.InvariantCultureIgnoreCase) >= 0))
{
//bad SQL found
}
IndexOf
与 StringComparison
枚举值将确保不区分大小写的比较。
另一种方法可能是:
return sqltext.Split()
.Intersect(badSqlList,StringComparer.InvariantCultureIgnoreCase)
.Any()
Split
你的 Sql 白色 space 然后将每个单词与你的白名单数组进行比较。如果您的 合法 table 名称包含 INESRTEDStudents
不太确定您的要求,但是,通常,更好的选择是首先使用参数化查询。你不能 100% 确定你的白名单,仍然有办法绕过它。
不要重新发明轮子 - 就像这里的每个人告诉你的那样使用参数化查询(解决比你目前意识到的更多的问题),你会感谢所有在未来...
但是请务必使用它来清理 WHERE
子句中的所有过滤器字符串:
public static string EscapeSpecial(string s)
{
Contract.Requires(s != null);
var sb = new StringBuilder();
foreach(char c in s)
{
switch(c)
{
case '[':
case ']':
case '%':
case '*':
{
sb.AppendFormat(CultureInfo.InvariantCulture, "[{0}]", c);
break;
}
case '\'':
{
sb.Append("''");
break;
}
default:
{
sb.Append(c);
break;
}
}
}
return sb.ToString();
}