不要将撇号('
)存储在数据库的字符字段中,而是始终将撇号转换为某些唯一的替代符号,该替代符号无法识别为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/