同事维护的站点遇到一个SQL注入漏洞,最后发现是由于对in_array()的理解错误(一直以为是绝对匹配才会返回true),同时拼接SQL语句时也没有使用Prepared Statement导致。代码中使用in_array($var, $white_set)判断从Query String获得的变量是否符合要求,参见下面示例代码($var为一整型变量,取用时没有使用intval($var)或者(int)$var强制转换为整型)。
$white_set = array(11, 13, 16);
$var = $_GET['var'];
if (in_array($var, $white_set)) {
$query = ‘ … column = ‘ . $var . ‘ … ‘;
…
}
访问 http://www.example.com/path/to?var=16′ and ‘x’='
时,$var=16′ and ‘x’='
,使用in_array($var, $white_set)
判断会得到 true
,因为 in_array
的第三个参数默认为 false
,此时在依次比较 $var
和 $white_set
中的元素会进行类型转换,相当于使用 ==
进行比较;如果第三个参数为 true
,则相当于使用 ===
进行比较,两个变量只有完全一致才会返回 true
。
总结:in_array()
第三个参数决定变量和数组中元素如何进行比较。
值为 false
时(默认),相当于 ==
;值为true时,相当于 ===
。