2010-06-25 35 views
3

我正在更新一些不正确处理用户输入的遗留代码。该代码确实做了少量的消毒,但未涵盖所有已知的威胁。输入消毒和参数化查询是否互斥?

我们较新的代码使用参数化查询。据我了解,查询是预编译的,输入被视为无法执行的数据。在那种情况下,消毒不是必需的。是对的吗?换句话说,如果我在这个遗留代码中对查询进行参数化,是否可以消除它目前所做的消毒处理?或者我错过了参数化之外的一些额外的卫生消毒好处?

回答

5

的确,SQL查询参数可以很好地防御SQL注入。嵌入式引号或其他特殊字符不能造成恶作剧。

但是,SQL查询的某些组件不能参数化。例如。表名,列名,SQL关键字。

$sql = "SELECT * FROM MyTable ORDER BY {$columnname} {$ASC_or_DESC}"; 

因此,有可能需要插成一个SQL查询之前验证动态内容的一些例子。白名单值也是一种很好的技术。

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

  • 假设您存储了信用卡号码。信用卡号码有一些有效的模式,图书馆可以从无效的模式中识别出有效的模式。

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

  • 或者,如果他们订购一定数量的商品,您可能需要将数量作为整数存储,但您希望确保其数量大于零,并且如果数量大于1000,检查用户是否正确输入。

+0

我希望那些$ columnname和$ ASC_OR_DESC不是来自用户!这些应该是代码中的硬常量,并对从常量到变量到SQL的数据路径进行全面审计,以确保它是您的变量之一。 (如果该路径非常短,那么它就更容易了,所以它只是一个参数,只是一个很低的级别,在更高的级别上,它应该是不同的函数调用,没有以SQL代码结尾的参数) – Javier 2010-06-25 18:42:40

+0

@Javier:是不是它是一种常见的UI功能,允许用户点击列的头部按该列进行排序?但是,是的,您需要验证UI输入是否与列名相对应,使用白名单或某种地图。 UI中的值甚至不需要是列的文字名称,它可以是您的代码可以关联到有效列名称列表中的条目的值。 – 2010-06-25 18:49:00

2

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

查看my previous answers之一就可以了。

+0

换句话说,对于与SQL注入无关的其他原因,清理可能仍然有用? – 2010-06-25 18:07:33

+0

是的,@ aardvark。 – 2010-06-25 18:08:20

1

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

但是,您仍然应该进行一些验证。例如,如果您期望varchar(10)并且用户输入的内容比这更长,则最终会出现异常。

5

参数化查询将有助于防止SQL注入,但他们不会对跨站点脚本执行任何操作。您需要其他措施,如HTML编码或HTML检测/验证,以防止这种情况发生。如果你关心的只是SQL注入,参数化查询可能就足够了。

1

总之没有。输入清理和参数化查询的使用并不相互排斥,它们是独立的:既不能单独使用,也不能使用两者。他们防止不同类型的攻击。使用两者都是最好的方法。

1

作为一个小问题,需要注意的是,有时编写包含动态SQL的存储过程有时很有用。在这种情况下,输入参数化的事实并不是针对SQL注入的自动防御。这可能看起来很明显,但我经常碰到那些认为因为他们的输入被参数化的人,他们可以停止担心SQL注入。