- 不要将撇号 (
'
) 存储在数据库的字符字段中,而应始终将撇号翻译为某些不被识别为 SQL 语法且在数据中不太常见或没有意义的唯一替代符号. - 在接收直接用户输入(例如来自 GET、POST 等的输入)时,请务必将值中的撇号翻译为您选择的替代符号,从而过滤掉这些值中的撇号。
- 对于所有包含用户输入的 SQL 语句,请始终将撇号括在文字值周围。例如,像这样:
SELECT Name FROM Client WHERE TYPE = '1';
。这应该强制所有非撇号字符被视为文字值本身的一部分,无论它们是反引号、大括号、分号、反斜杠、正斜杠等。所以类似SELECT Name FROM Client WHERE TYPE = ' -- /* comment the rest ';
不会有不同的解释。 - 每当将用户输入合并到 SQL 语句的非文字部分(例如 ORDER BY 子句中的列名)时,请从值中完全过滤掉标点符号,或根据预定义的安全集对其进行验证。里>
- 每当从数据库输出数据(以 HTML、XML 等形式)时,请始终通过用撇号替换您选择的替代符号来反转此过滤过程,以便客户可以轻松阅读。
(注意:我们使用的是 SQL Server,它无法将反引号符号识别为有效的 SQL 标点符号,但如果使用 MySQL,我们还需要翻译反引号。)
我已经用每一个可以想象到的可能会阻塞 SQL 的符号对此进行了测试,到目前为止它已经经受住了一切。我是不是忽略了什么?在生产系统上尝试之前,我想获得一些社区反馈。
<小时/>我们的环境:
- Linux(非 Windows)
- PHP 5.4
- ADOdb 版本? (文档:旧版 = http://phplens.com/lens/adodb/docs-adodb.htm ;新版 = http://adodb.sourceforge.net/ )
- 驱动程序=“mssql”
最佳答案
我不了解 MySQL 方面的情况,但由于这主要是关于 SQL Server 的,所以我可以说,这种方法不会给您带来任何好处,而参数化查询和/或使用存储过程则无法给您带来好处。但它确实有以下缺点:
- 实现需要时间
- 它使系统更容易出错(即忘记进行翻译的地方)
- 这使得数据不易移植/可导出/可报告,因为所有客户都需要了解这种不明显的翻译
- 关于执行
SELECT Name FROM Cient WHERE TYPE = '1';
,如果TYPE
字段是数字类型,那么您最多只会损害性能,最坏的情况是出现转换错误 - 您现在拥有一个过于复杂的系统,这会增加培训和支持时间(让新程序员加快速度、发现/解决问题所需的时间等)。
只需使用参数,无论是作为存储过程的输入,还是参数化的即席 SQL 语句。如果使用 .NET,则在这两种情况下都会使用 SqlParameter
。
ADOdb 支持参数化查询和存储过程(本质上是参数化的)。请参阅:
- http://phplens.com/lens/adodb/docs-adodb.htm#prepare ,并且
- http://phplens.com/lens/adodb/docs-adodb.htm#preparesp
他们甚至提到了 PDO(转到此处,其下一小节: http://phplens.com/lens/adodb/docs-adodb.htm#connect_ex ),但我不确定这是否有帮助或无用。这里还提到了 PDO:http://adodb.sourceforge.net/docs-adodb.htm#php5 .
关于mysql - 你能看出以下SQL注入(inject)防御方案中的漏洞吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33746307/