1

オートコンプリートにアポストロフィを渡すのに苦労しています。データベースには、アポストロフィを持たないエントリが含まれています...代わりに、同等の 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;
4

1 に答える 1

1

スクリプトはそのままでは、エスケープ$getされずに使用されるため、SQL インジェクションに対して脆弱です。htmlentities()あなたのやり方では引用符をエンコードしません。

最初にデータを修正します。

エンコードされた値をデータベースに保存することはお勧めしません (特に のように変にエンコードされたものはそうではありません&POUND039)。したがって、最初に提案することは、データベース内のこれらの値を実際のアポストロフィに置き換えることです。

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

htmlentities()次に、 (これは、定数を渡さない限り引用符をエンコードしません)を使用する代わりにENT_QUOTES、適切にエスケープされた string を渡し$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...
于 2012-04-07T13:27:22.027 に答える