SQL 使用 SqlBuilder 在 FROM 子句中注入

SQL Injection in FROM clause with SqlBuilder

我们有一个 SQL 语句,它使用 SqlBuilder 在 from 子句中设置 table 名称。数据库是 SQL Server 2008 及更高版本。

var sqlBuilder = new SqlBuilder();

sqlBuilder.Select("*").From(tableName);
sqlBuilder.Where("...");

Connection.BuilderQuery<dynamic>(sqlBulder).Select(Map);

我想知道这是否存在 SQL 注入风险?我怎样才能减轻这种风险?或者 SqlBuilder 会处理这些事情吗?

我可以通过将 table 名称括在方括号中来降低风险吗?例如

sqlBuilder.From("[" + tableName + "]");

此外,如果有人可以在 FROM 子句中提供一些 SQL 注入攻击的示例,以便我了解它的工作原理并创建测试,我们将不胜感激。

我以前不得不做类似的事情,虽然我不知道 SqlBuilder,但我通过检查以下查询的 ExecuteScalar() 结果解决了这个问题

select count(*) from information_Schema.tables where table_name = @tbl

如果结果 > 0,我将使用以下操作(如果结果为 0,则必须脱离)

string sql = "Select a, b, c from ["+tblName+"]"

它很脏,但是使用信息模式应该保证 table 名称存在于数据库中并且变量不包含任何讨厌的东西。

我不知道 SqlBuilder 是什么,但这里有一个利用注入的例子: 假设您有一个代码:

var myFullQuery = string.Format("SELECT * FROM {0} WHERE A = 1", externalInput);

然后对数据库执行此操作。如果恶意用户将此字符串作为输入发送:ValidTableName; DELETE FROM ValidTableName; SELECT * FROM ValidTableName

myFullQuery 变量将被设置为:SELECT * FROM ValidTableName; DELETE FROM ValidTableName; SELECT * FROM ValidTableName WHERE A = 1 并且您失去了整个 table...显然,可以通过这种方式实现更多破坏性的命令...

从问题中的信息中不清楚代码是否易受攻击。 SqlBuilder 对象不太可能以安全的方式处理 table 名称,但在我们了解 SqlBuilder 的确切细节之前我们无法确定,这不是 .净框架。我们还需要了解更多关于 tableName 变量的信息,因为即使是不安全的 SqlBuilder 实现也可以使用 table 名称的安全来源。

顺便提一下,我可以肯定地说使用方括号的建议修复 不会 解决问题。鉴于此代码:

sqlBuilder.From("[" + tableName + "]");

我仍然可以像这样提供输入:

information_schema.columns];DROP TABLE x;SELECT * FROM [y

中间的部分仍然会被注入并执行。

另外,您可能正在使用这个:

https://github.com/maxtoroq/DbExtensions/blob/master/docs/SqlBuilder.md

如果是这样,在查看该类型的文档后,您应该知道这绝对不是参数安全的 table 名称,并且很可能考虑到 MySql 编写(它使用 LIMIT 子句,这是 SQL 的非标准 MySql 扩展)。

Or does the SqlBuilder take care of these things?

没有。您必须正确使用该技术来保护自己。就像有安全带的汽车一样,只有正确使用它才能得到保护。

I am wondering if this is a SQL injection risk?

也许吧。如果您在 end-user 数据上使用任何类型,那么很可能是。如果您必须询问您的最终用户他们想要填充哪个 table,我会推荐一个枚举。带有字符串标题和 int 值的下拉框;

public enum WhitelistTable
{
  Undefined = 0,
  MyTable1,
  MyTable2
}

如果用户数据不是 int,则它是无效的。您可以在每个枚举值上放置一个 DescriptionAttribute 或简单地 .ToString() 枚举值 并插入它。实施白名单优于黑名单。

var myTable = WhitelistTable.MyTable1;

sqlBuilder.From(myTable.ToString());

Could I mitigate the risk simply by wrapping the table name in square brackets?

我不这么认为,一般不会(我不是 100% 确定 SqlBuilder)。我什至不会依靠第三方来源来冒险。示例值:

SomeTable]; Drop Table SomeTable; --

产量:

sqlBuilder.From("[SomeTable]; Drop Table SomeTable; --]");
sqlBuilder.Select("*").From(tableName);

如果 tableName 数据来自用户输入,用户可以在键盘上键入或上传到文件中 = 您很容易受到 Sql 注入

sqlBuilder.Where("...");

同样的事情。 Where 通常来自用户输入。用户键入内容,然后您在 where 子句中使用该值。 SqlBuilder 是否进行参数化? - 如果答案是 NO 你很脆弱。

Quote: 或者 SqlBuilder 会处理这些事情吗?

答:你告诉我们。这里的大多数人即将结束您的问题,因为不清楚什么是 SqlBuilder 以及它是如何工作的。虽然,我至少理解它是什么,因为我们使用了相似的概念。我们的 Table 名称是常量,我们的 sql 生成器参数化值被添加到 where 子句。