sql注入场景中的格式化函数与参数?

sql注入场景中的格式化函数与参数?,sql,delphi,sql-injection,Sql,Delphi,Sql Injection,我知道参数在sql语句中的用法,但出于好奇,使用Format函数来防止sql注入而不是使用参数是安全的 喜欢这个样品吗 sCustomer : string begin AdoSql.CommandText:=Format('Select SUM(value) result from invoices where customer=%s',[QuotedStr(sCustomer)]); end; 假设QuotedStr按预期工作,并且没有任何边缘情况可以破坏SQL注入,那么这可能是安全的。

我知道参数在sql语句中的用法,但出于好奇,使用Format函数来防止sql注入而不是使用参数是安全的

喜欢这个样品吗

sCustomer : string
begin
 AdoSql.CommandText:=Format('Select SUM(value) result from invoices where customer=%s',[QuotedStr(sCustomer)]);
end;
假设
QuotedStr
按预期工作,并且没有任何边缘情况可以破坏SQL注入,那么这可能是安全的。(这并不能保证。正如Linas在评论中指出的,MySql允许您使用
\'
来转义引号。其他DBMS可能也有类似的功能。具有足够系统理论知识的攻击者可以利用它们。)


然而,即使QuotedStr足够好,出于另一个原因使用参数仍然更好:性能。当您将参数与查询分开时,最终可能会使用不同的参数多次发送完全相同的查询代码。如果这样做,数据库可以缓存它在计算查询时所做的大量工作,因此您的数据库访问速度会更快。当您将参数混入查询代码本身时,这不起作用(或者至少不起作用)。

任何时候您通过将字符串串联在一起构建SQL字符串时,都有可能发生注入攻击,无论您认为访问这些字符串有多安全。据你所知,有人可以在调试器中运行你的应用程序,在
QuotedStr()
的结果上设置断点,并在允许
Format()
查看它之前修改它的内容

使用实际的SQL参数是最安全的方法。它不仅避免了注入,而且还允许SQL引擎根据自己的需要决定如何最好地格式化参数,这样您就不必担心在自己的代码中格式化值,它可以很好地与强类型语言(如Delphi)配合使用。更不用说能够在服务器端提前准备SQL语句,然后在代码中执行它(甚至多次),从而大大减少客户机和服务器之间的通信量并提高总体性能,这对性能有好处

var
  sCustomer : string 
begin 
  AdoSql.CommandText := 'Select SUM(value) result from invoices where customer=:Customer'; 
  AdoSql.Prepared := True;
  ... 
  AdoSql.Parameters['Customer'].Value := sCustomer; 
  AdoSql1.ExecSQL;
  ...
  AdoSql.Parameters['Customer'].Value := sCustomer;
  AdoSql1.ExecSQL;
  ...
  AdoSql.Prepared := False;
end; 

否,
格式
不提供SQL注入的安全性。在这方面,它与普通的字符串连接没有什么不同

问题中与SQL注入相反的代码部分是调用
QuotedStr
,您可以使用
格式或不使用
格式。不过,它不如真正的参数化查询那么可靠


在此上下文中,
格式
的唯一优点是整个字符串模板位于一个位置,因此与必须使用连续的
+
操作构造字符串相比,不太可能出现空格和标点错误,SQL撇号可能会在Delphi撇号中丢失。

+1关于“缓存”的注释,许多SQL服务器可以重用SQL语句的执行计划。这在MySQL中可能是不安全的,因为MySQL允许\'转义引号,所以QuotedStr在这里没有帮助。请注意,MS SQL Server可以“自动参数化”查询。例如,第一段有点傻。SQL注入基本上是获取对数据库的未经授权访问。但是,如果有人对你的应用程序本身具有调试级访问权限,他们不需要SQL注入攻击来访问数据库;可以假设他们已经可以访问它,与应用程序本身具有相同的权限级别。如果应用程序使用到数据库的加密连接,或者如果攻击者无法或不想确定正在使用的数据库类型或如何直接访问数据库,则不可以。让应用程序完成所有工作,只需更改执行的SQL。在这种情况下,使用参数也会不安全,因为用户可能会更改参数的值,这是我调试自己的应用程序时有时会做的事情。即使攻击者更改参数值,使用参数仍然更安全。正如我所说,参数允许DB引擎确保值是安全的,并且格式正确。换句话说,将不带引号的字符串传递给参数(这是您应该做的)允许引擎在执行查询时仍然正确处理字符串。这就是为什么要首先使用参数来避免注入攻击。我认为标题应该是
QuotedStr函数vs sql注入场景中的参数?
,但更改它会破坏这里的一些答案。这里的问题是关于
QuotedStr
而不是
Format