我使用以下代码创建SqlCommand
,其中包含用户在UserStoredProcedureName
中指定的存储过程的名称:
new SqlCommand(UserStoredProcedureName, connection)
{ CommandType = CommandType.StoredProcedure }
用户在UserStoredProcedureName
中提供的字符串未进行验证。用户是否只能在数据库中指定存储过程的名称?用户是否能够通过制作恶意存储过程名称来执行SQL注入攻击?
例如:
UserStoredProcedureName = "SELECT * FROM USERS";
答案 0 :(得分:4)
sql注入攻击不会发生在存储过程本身,但它可能发生在提供的参数/参数上。 There's a good article that explains it a bit。
例如,您可以调用SP_MYPROC,这很好,但我可以注入第一个参数:
;drop table users
不,如果找不到它们,除了失败之外,每个存储过程的说法都没有“验证”。
一般来说,我认为允许某人用文本编写然后作为语句执行,这是一个非常糟糕的想法,特别是如果登录具有写访问权限。如果您想要更安全,可以通过查询可用的存储过程来构建下拉菜单,然后当您运行一个时,您可以验证要求运行的内容与可用的过程名称之间的1 = 1匹配。
但是为了允许参数方面的自由格式文本,这就是它快速向南移动的地方。
我只熟悉明确指定参数,例如:
sqlcommand.parameters.addwithvalue(x,y);
但在这种情况下,程序的名称和参数是硬编码的。
答案 1 :(得分:4)
您不应该让外部代码提供存储过程名称。理由:存储过程可以是sp_executesql
,它可以运行您作为第一个参数提供的任何内容。它也可以是xp_cmdshell
或类似的。
所以:您仍应通过白名单控制输入存储过程名称。如果名称来自您自己的代码,则不应该是一个问题,并且在该方案中对于white-list是不正常的。
注意:如果存储过程在内部使用EXEC (@sql)
或EXEC sp_executesql @sql
,那么它仍然可以呈现SQL注入攻击,具体取决于@sql
是否包含恶意的非参数化SQL。请注意,sp_executesql
是设计的,以允许您完全参数化动态SQL,以避免SQL注入攻击甚至在SQL内部生成的SQL内。