自动完成撇号和注射攻击

时间:2012-04-07 12:55:58

标签: php ajax autocomplete

我在将撇号传递到自动完成功能时遇到了困难。数据库包含没有撇号的条目...而是正在使用html等效项(& POUND039;)。我对ajax还很新,所以我非常感谢你的帮助。问题是,如何传入撇号的值并使其匹配?另外,我的代码是否容易受到注入攻击?在此先感谢您的帮助!

代码是这样的:

<script type="text/javascript">
var options = {
        serviceUrl:'autocomplete/autoQuery.php',
            minChars:2, 
            delimiter: /(,|;)\s*/, // regex or character
            maxHeight:400,
            width:500,
            zIndex: 9999,
            deferRequestBy: 0, //miliseconds
            params: { country:'Yes' }, //aditional parameters
            noCache: false, //default is false, set to true to disable caching
            // callback function:
            // onSelect: function(value, data){ alert('You selected: ' + value + ', ' + data); },
            onSelect: function(value, data){ window.location = "textbooks.php?bk=" + data;}
    }; 
$('#query').autocomplete(options);
</script>

我有一个PHP脚本发送回查询结果。该页面名为query.php,代码如下:

$get = htmlentities($_GET['query']);
$query = "SELECT title,author,id,isbn10,isbn13 FROM textbook
        WHERE title LIKE '%" . $get . "%'
        OR author LIKE '" . $get . "%'
        OR isbn10 LIKE '" . $get . "%'
        OR isbn13 LIKE '" . $get . "%'
        LIMIT 5
        ";
$result = mysql_query($query,$connection);
if(mysql_num_rows($result) == 0){
$resString = "'No result found. Click here',";
$idString = "'unknown',";
}else{
$resString = "";
$idString = "";
while($data = mysql_fetch_array($result)){
    $resString .= "'" . $data['title'] . " by " . $data['author'] . "',";
    $idString .= "'" . $data['id'] . "',";
}   
}

$resString = rtrim($resString, ',');
$idString = rtrim($idString, ',');
$code = "{\n";
$code .= "query:'" . $get . "',\n";
$code .= "suggestions:[" . $resString . "],\n";
$code .= "data:[" . $idString . "]\n";
$code .= "}";
echo $code;

1 个答案:

答案 0 :(得分:1)

您的脚本原样, 容易受到SQL注入攻击,因为$get未被使用。 htmlentities()你拥有它的方式不会对引号进行编码。

首先修复数据:

不建议在数据库中存储编码值(尤其不是像&POUND039那样奇怪编码的值)。所以我建议的第一件事就是用实际的撇号替换数据库中的那些值。

UPDATE textbook 
SET 
  title = REPLACE(title, '&POUND039', '\''),
  author = REPLACE(author, '&POUND039', '\''),
  etc...

然后,不使用htmlentities()(顺便说一下,除非你传递ENT_QUOTES常量,否则不会对引号进行编码,而是传入一个正常转义的字符串$get,它将与常规字符串匹配数据库中的单引号。注意,转义包含文字%_的字符串以在LIKE语句中使用时还有其他问题,所以这只是最小的可以做到。

$get = mysql_real_escape_string($_GET['query']);
$query = "SELECT title,author,id,isbn10,isbn13 FROM textbook
        WHERE title LIKE '%" . $get . "%'
        OR author LIKE '" . $get . "%'
        OR isbn10 LIKE '" . $get . "%'
        OR isbn13 LIKE '" . $get . "%'
        LIMIT 5
        ";

真正的解决方案:

但是,正如评论中所建议的那样,如果您使用PDO和绑定参数,这将更加顺利,无需担心注入:

// PDO connection information omitted...
$query = "SELECT title,author,id,isbn10,isbn13 FROM textbook
        WHERE title LIKE CONCAT('%', :get, '%')
        OR author LIKE CONCAT(:get, '%')
        OR isbn10 LIKE CONCAT(:get, '%')
        OR isbn13 LIKE CONCAT(:get, '%')
        LIMIT 5
        ";

$stmt = $db->prepare($query);
$stmt->execute(array(':get', $_GET['query']);
while ($data = $stmt->fetch(PDO::FETCH_ASSOC)) {
  $resString .= "'" . $data['title'] . " by " . $data['author'] . "',";
  $idString .= "'" . $data['id'] . "',";
}
// etc...