1

所以我试图围绕如何安全地组合三个冲突的东西(绑定参数、正则表达式、使用用户输入的部分匹配搜索)来解决问题,我不确定我是否找到了正确/安全的方法来处理这些事物。这不应该是一个不常见的问题,但是处理 PDO 和 php 的所有三个安全因素的交集的文档要么很难找到,要么不存在。

我的需求比较简单和标准,按优先级排列:

  1. 我想防止sql注入(目前我正在使用绑定参数)
  2. 我想防止正则表达式注入
  3. 我想使用用户输入字符串进行部分匹配搜索

因此,例如,我想允许用户搜索不区分大小写的部分匹配的用户名,例如搜索Xiu将显示用户名XiuXiulu并且xiuislowercase

目前我有以下声明:

select * from users where username ilike :search_string || '%'

在其他地方,我使用正则表达式运算符使用更复杂的情况,类似于:

select * from users where username ~* :search_string || '%'

php pdo中的绑定语句在哪里:search_string,数据库是postgresql。这执行了正确的搜索,返回了正确的结果,并且我有理由确定它是针对 sql 注入的证明,因为它是一个绑定参数。但是,我不确定它是否可以防止正则表达式注入,并且我不知道如何在证明它可以防止 sql-injection 的同时证明它可以防止正则表达式注入。
我如何使用 php、PDO 和 postgresql 完全保护它免受正则表达式注入?

4

1 回答 1

2

LIKE不支持正则表达式,它只有有限的模式匹配元字符%_. 因此,如果您在将参数值传递给字符串之前使用字符串中的反斜杠转义这两个字符,那么您应该是安全的。

<?php
$search_string = preg_replace('/[%_]/', '\\\\$0', $search_string);
$pdoStmt->execute(array('search_string'=>$search_string));

或者,您可以将用户名的左子字符串与您的输入进行比较,然后将其与没有元字符模式匹配功能的固定字符串进行比较。

select * from users where left(username, :search_string_length) = :search_string

回复您的评论:

避免代码注入的一般规则是:永远不要将任意用户输入作为代码执行。

这当然适用于 SQL 注入,这就是为什么我们使用参数来强制用户输入被解释为值,而不是修改 SQL 语句的语法。

但它也适用于 SQL 操作中正则表达式字符串中的“代码”。正则表达式本身就是一种代码逻辑,它是用于匹配输入的有限状态机的非常紧凑的表示。

避免代码注入的解决方案是可以让用户输入选择代码(如白名单),但不要让用户输入被解释代码。

于 2012-12-28T19:18:31.427 回答