Sql 输入清理和参数化查询是否相互排斥?

Sql 输入清理和参数化查询是否相互排斥?,sql,database,language-agnostic,sanitization,parameterized,Sql,Database,Language Agnostic,Sanitization,Parameterized,我正在更新一些不能正确处理用户输入的遗留代码。该代码只进行了少量的消毒,但并没有覆盖所有已知的威胁 我们较新的代码使用参数化查询。据我所知,查询是预编译的,输入只是作为无法执行的数据处理。在这种情况下,不需要消毒。是这样吗 换句话说,如果我在这段遗留代码中参数化查询,那么消除它当前所做的清理是否可以?或者说,除了参数化之外,我还缺少了清理的其他好处吗?清理和验证的原因有很多,包括防止跨站点脚本编写,以及只是希望字段的内容正确(电话号码中没有姓名)。参数化查询消除了手动清理或转义SQL注入的需要

我正在更新一些不能正确处理用户输入的遗留代码。该代码只进行了少量的消毒,但并没有覆盖所有已知的威胁

我们较新的代码使用参数化查询。据我所知,查询是预编译的,输入只是作为无法执行的数据处理。在这种情况下,不需要消毒。是这样吗


换句话说,如果我在这段遗留代码中参数化查询,那么消除它当前所做的清理是否可以?或者说,除了参数化之外,我还缺少了清理的其他好处吗?

清理和验证的原因有很多,包括防止跨站点脚本编写,以及只是希望字段的内容正确(电话号码中没有姓名)。参数化查询消除了手动清理或转义SQL注入的需要


你是对的,SQL参数不是可执行代码,所以你不必担心这一点


但是,您仍然应该进行一些验证。例如,如果您期望一个varchar(10),而用户输入的长度超过这个值,那么您将得到一个异常。

参数化查询将有助于防止SQL注入,但它们不会完全阻止跨站点脚本编写。您需要其他措施,如HTML编码或HTML检测/验证来防止这种情况。如果您只关心SQL注入,那么参数化查询可能就足够了。

确实,SQL查询参数可以很好地抵御SQL注入。嵌入引号或其他特殊字符不能进行恶作剧

但是SQL查询的某些组件无法参数化。例如表名、列名、SQL关键字

$sql = "SELECT * FROM MyTable ORDER BY {$columnname} {$ASC_or_DESC}";
因此,在插入SQL查询之前,可能需要验证一些动态内容的示例。白名单值也是一种很好的技术

此外,您可以使用列的数据类型允许的值,但这些值是无意义的。对于这些情况,使用应用程序代码进行验证通常比尝试在SQL约束中进行验证更容易

  • 假设您存储了一个信用卡号。信用卡号有有效的模式,库可以识别有效的和无效的

  • 或者当用户定义密码时又如何?您可能希望确保足够的密码强度,或者验证用户是否在两个密码输入字段中输入了相同的字符串

  • 或者,如果他们订购了一定数量的商品,您可能需要将数量存储为整数,但您需要确保数量大于零,如果数量大于1000,您可能需要与用户再次确认其输入是否正确


简而言之,不。输入清理和参数化查询的使用不是相互排斥的,它们是独立的:您既可以单独使用,也可以同时使用。它们可以防止不同类型的攻击。使用这两种方法是最好的方法。

需要注意的一点是,编写包含动态SQL的存储过程有时很有用。在这种情况下,输入参数化的事实并不是针对SQL注入的自动防御。这似乎是一个相当明显的观点,但我经常遇到这样的人:因为他们的输入是参数化的,所以他们可以不再担心SQL注入。

换句话说,由于与SQL注入无关的其他原因,清理可能仍然有用?我希望$columnname和$ASC_或_DESC不是来自用户!这些应该是代码中的硬常量,并对从常量到变量再到SQL的数据路径进行全面审核,以确保它是您的变量之一。(如果路径很短,那么就更容易了,因此它只是一个非常低级别的参数,在紧接着更高级别,它应该是不同的函数调用,没有任何以SQL代码结尾的参数)@Javier:允许用户单击列的标题按该列排序,这不是一个常见的UI功能吗?但是是的,您需要使用白名单或某种映射来验证UI输入是否对应于列名。UI中的值甚至不需要是列的文字名称,它可以是代码可以与有效列名列表中的条目关联的值。