1

SQL インジェクションの可能性があるプロジェクトを調査しています (1 人のユーザーが報告しました)。

ログイン スクリプトの一部を次に示します。

  $loginemail = $_POST['loginemail'];                 
            $loginemail_sql = mysql_real_escape_string($loginemail);                

            $password = $_POST['loginpass'];                 
            $password_sql = mysql_real_escape_string($password);                

             //get user data
            $q = 'SELECT uid, full_name, score, status FROM users WHERE email="'.$loginemail.'" AND password="'.$password_sql.'" LIMIT 1';

これが注入できるコードの一部である場合、私は今したいですか? $loginemail と $password が正しく扱われず、危険な "SQL 部分" が含まれる可能性があるという問題はありますか?

4

6 に答える 6

6

どれどれ:

mysql_*新しいコードで関数を使用しないでください。それらはもはや維持されておらず、公式に非推奨になっています。赤いボックスがか?代わりにプリペアドステートメントについて学び、 PDOまたはMySQLiを使用してください-この記事はどちらを決定するのに役立ちます。PDOを選択した場合は、ここに優れたチュートリアルがあります。

手始めに。

次に、エスケープしていますが$loginemail、(の代わりに$loginmail_sql)エスケープされていないバージョンを使用しています。

第三に、パスワードをそのままデータベースに保存することがコードによって暗示されます。あなたはすべきではありません。攻撃者がデータベースを手に入れると、パスワードが危険にさらされます。パスワードをハッシュし、そこにハッシュを保存する必要があります。

于 2013-03-20T19:58:02.847 に答える
2

はい、$loginemail変更されていないクエリで使用しています。$loginemail_sql代わりに使用してください。

詳細については、PHPでSQLインジェクションを防ぐ方法をご覧ください。

于 2013-03-20T19:56:55.517 に答える
2

@Madara Uchiha が言ったように、mysql_* 関数の使用をやめるのは良いことです。しかし、彼は例を挙げませんでした。だから私はします。私の英語でごめんなさい、私はブラジル人です:)

PDO:

<?php
$loginemail = $_POST['loginemail'];
$password = $_POST['loginpass'];

// open a PDO connection within mysql driver
// PDO uses DSN string for connections they look like: "driver:options"
$dsn = 'mysql:dbname=testdb;host=127.0.0.1';
// DB username
$dbUser = 'dbuser';
// DB password
$dbPassword = 'dbpass';
// PDO is instantiable, so you need to create an object for each connection
$dbh = new PDO($dsn, $dbUser, $dbPassword);
// You must prepare your query, PDO uses a placeholder system for sanitize data and avoid injection, params can be passed using "?" or ":varname"
$stmt = $dbh->prepare('SELECT uid, full_name, score, status FROM users WHERE email= :email AND password= :password LIMIT 1');
// Binding a param called :email
$stmt->bindValue(':email', $loginemail);
// Binding a param called :password
$stmt->bindValue(':password', $password);
// Execute the PDOStatement
$stmt->execute();
// Then fetch result
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
// ALSO, you can fetch only one row using
$firstRow = $stmt->fetch(PDO::FETCH_ASSOC);
于 2013-03-20T20:20:50.200 に答える
1

1つには、$ loginmailをエスケープしていますが、クエリでエスケープされていないバージョンを使用しています。

可能であれば、PDOとプリペアドステートメントを使用して、エスケープとパラメーターの置換を簡素化することを検討してください。

于 2013-03-20T19:56:55.537 に答える
1

$loginemailに到達するためにmysql_real_escape_stringを$loginemail_sql使用しますが、クエリでの使用を停止します。

$q = 'SELECT uid, full_name, score, status FROM users WHERE email="'.$loginemail.'" AND password="'.$password_sql.'" LIMIT 1';
于 2013-03-20T19:57:01.470 に答える
1

私はSQLインジェクションの専門家ではありませんが、文字列をエスケープすることは素晴らしい最初のステップであり、実行できることはおそらくもっとありますが、それで十分なはずです。

コードに関する私の最大の問題は、データベースのプランテキストにパスワードを保存しているように見えることです。それらを保存するには、ソルトハッシュを使用する必要があります。詳細については、こちらをご覧ください: PHPパスワードの安全なハッシュとソルト

また、あなたはこのコードを間違えました:

$q = 'SELECT uid, full_name, score, status FROM users WHERE email="'.$loginemail.'" AND password="'.$password_sql.'" LIMIT 1';

する必要があります:

$q = 'SELECT uid, full_name, score, status FROM users WHERE email="'.$loginemail_sql.'" AND password="'.$password_sql.'" LIMIT 1';
于 2013-03-20T19:57:13.953 に答える