11 .net sql sanitization sqlconnection dynamic-sql
我正在生成一些动态SQL,并希望确保我的代码是安全的SQL注入.
为了争论,这里是一个如何生成它的最小例子:
var sql = string.Format("INSERT INTO {0} ({1}) VALUES (@value)",
tableName, columnName);
Run Code Online (Sandbox Code Playgroud)
在上面,tableName和columnName,以及@value来自不受信任来源的任何内容.由于占位符的使用@value是安全的SQL注入攻击,可以忽略.(该命令通过SqlCommand执行.)
但是,tableName并且columnName 不能作为占位符绑定,因此容易受到注入攻击.由于这是一个"真正动态"的场景,因此没有白名单tableName或columnName可用.
问题是:
是否有一个标准的,内置的方式来检查和/或消毒tableName和columnName?(SqlConnection,或帮助程序类等)如果没有,在不使用第三方库的情况下执行此任务的好方法是什么?
笔记:
[schema].[My Table].column,就像"安全"一样table1.更新:
刚发现这个,并认为它有点有趣:.NET4中有一个SqlFunctions.QuoteName函数(EF4?).好的,这对我来说真的没有帮助......
Jer*_*odd 23
我不确定你是否还在研究这个问题,但DbCommandBuilder课程提供了一种方法QuoteIdentifier.这样做的主要好处是它与数据库无关,并且不涉及任何RegEx混乱.
从.NET 4.5开始,您只需使用DbConnection对象即可清理表名和列名所需的一切:
DbConnection connection = GetMyConnection(); // Could be SqlConnection
DbProviderFactory factory = DbProviderFactories.GetFactory(connection);
// Sanitize the table name
DbCommandBuilder commandBuilder = factory.CreateCommandBuilder();
string tableName = "This Table Name Is Long And Bad";
string sanitizedTableName = commandBuilder.QuoteIdentifier(tableName);
IDbCommand command = connection.CreateCommand();
command.CommandText = "SELECT * FROM " + sanitizedTableName;
// Becomes 'SELECT * FROM [This Table Name Is Long And Bad]' in MS-SQL,
// 'SELECT * FROM "This Table Name Is Long And Bad"' in Oracle, etc.
Run Code Online (Sandbox Code Playgroud)
(4.5之前,您需要一些其他方式来获取您的DbProviderFactory - 可能来自应用程序配置中的数据提供程序名称或在某处进行硬编码.)
由于您使用的是SqlConnection,因此假设这是一个SQL Server数据库.
根据该假设,您可以使用遵循MSDN中定义的SQL Server标识符规则的正则表达式来验证表和字段名称.虽然我是正则表达式的完全和完全新手,但我确实发现这个应该接近:
[\p{L}{\p{Nd}}$#_][\p{L}{\p{Nd}}@$#_]*
Run Code Online (Sandbox Code Playgroud)
但是,正则表达式不会解决SQL Server关键字,并且不能确保表和/或列实际存在(尽管您指出这不是问题).
如果这是我的应用程序,我首先要确保最终用户没有尝试通过拒绝任何包含分号(;)的请求来执行注入.
接下来,我将通过删除有效的名称分隔符(",',[,]),将表名拆分一段以查看是否已指定架构,并对INFORMATION_SCHEMA.TABLES执行查询以确定表的存在.
例如:
SELECT 1
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = 'tablename'
AND TABLE_SCHEMA = 'tableschema'
Run Code Online (Sandbox Code Playgroud)
如果使用参数创建此查询,则应进一步保护自己免受注入.
最后,我将通过执行一组类似的步骤来验证每个列名称的存在,只有在确定表有效后才使用INFORMATION_SCHEMA.COLUMNS来确定列的有效性.
我可能会从SQL Server中获取此表的有效列列表,然后验证每个请求列是否在我的代码中的列表中.这样,您就可以确切地确定哪些列出错并向用户提供反馈.
| 归档时间: |
|
| 查看次数: |
4929 次 |
| 最近记录: |