我确实理解准备好的语句是寻求防止sql注入的最终方法.但是,它们以有限的方式提供覆盖;例如,在我让用户决定操作顺序如何(即ASC或DESC等等)的情况下,我没有用准备好的语句覆盖那里.
@H_502_24@
无论是使用预处理语句还是使用MysqL转义函数,总是需要使用white-lists来表示诸如表名或列名之类的东西.
我知道我可以将用户输入映射到预定义的白名单.但是,这只有在事先可以创建或猜测白名单时才有可能.
例如,在我上面提到的情况(ASC或DESC)中,可以根据接受的值列表轻松映射和验证.但是,是否存在无法针对白名单验证sql语句部分的情况?
如果存在这种情况,那么推荐的方法是什么?
如果我要使用底层数据库的内置转义实用程序(例如mysql的MysqL_real_escape_string)来逃避user_input,我将在哪里失败?
我问这个问题的假设是我总是使用引用值构造我的sql语句 – 即使对于整数……
让我们看看下面的例子并反思它.
select {$fields} from {$table} where Age='{$age}' order by {$orderby_pref}
假设所有变量都是用户提供的.
如果我是MysqL_real_escape_string上面的sql中的所有变量(而不是使用准备好的语句,这只包括我中途迫使我为另一半的白名单提供它无法帮助),它不会同样安全(并且更容易编码)?如果没有,输入方案转义实用程序将失败?
$fields = MysqL_escape($fields); $table = MysqL_escape($table); $age = MysqL_escape($age); $orderby_pref = MysqL_escape($orderby_pref); select {$fields} from {$table} where Age='{$age}' order by {$orderby_pref}
问题是表名和列名不是用单引号或双引号引用的,所以如果你使用一个专门引用这些字符的函数(当然还有一些……),它对你的表名不起作用.
考虑表名my_table; DELETE * FROM MysqL; SELECT * FROM my_table.这个字符串中的任何内容都不会被MysqL的转义函数转义,但它绝对是一个你想要检查白名单的字符串.