1

重複の可能性:
PHP で SQL インジェクションを防ぐ方法は?

SQL インジェクションからの保護についていくつか質問したいと思います。私がこれまで読んできたものから、次の 3 つのことに出くわします。

  • ストリップスラッシュ
  • これは magic_quotes_gpc と組み合わせて使用​​されます
  • mysql_real_escape_string (または、新しい php の mysqli だと思いますか?)

問題は、これらの両方を使用する必要があるか、または real_escape_string で十分かということです。

たとえば、登録ページに関連する次のコード行があります (sqli ヘルパーを使用すると、データベースに関するすべてを見つけることができるため、脆弱であることがわかっています:(上記のいずれもまだ実装していないため):

    if(isset($_POST['submit'])){
    //cleanup the variables
    $username = ($_POST['username']);
    $password = ($_POST['password']);
    $email = ($_POST['email']);
    $username = sanitise($username);
    $password = sanitise($password);
    $email = sanitise($email);
    //quick/simple validation
    if(empty($username)){ $action['result'] = 'error'; array_push($text,'Please type in a username'); }
    if(empty($password)){ $action['result'] = 'error'; array_push($text,'Please type in a password'); }
if($action['result'] != 'error'){
        $password = md5($password); 
        //add to the database
        $add = mysql_query("INSERT INTO Users VALUES(NULL,'$username','$password','$email',0, 'First', 'Last', 'Phone Number Here', '...', 'Something about me...')");
        if($add){
            //get the new user id
            $userid = mysql_insert_id();    
            //create a random key
            $key = $username . $email . date('mY');
            $key = md5($key);
            //add confirm row
            $confirm = mysql_query("INSERT INTO Confirm VALUES(NULL,'$userid','$key','$email')");   
            if($confirm){
                //include the swift class
                include_once 'swift/swift_required.php';
                //put info into an array to send to the function
                $info = array(
                    'username' => $username,
                    'email' => $email,
                    'key' => $key);
                //send the email
                if(send_email($info)){
                    //email sent
                    $action['result'] = 'success';
                    array_push($text,'Thanks for signing up. Please check your e-mail for confirmation.');
                }else{
                    $action['result'] = 'error';
                    array_push($text,'Could not send confirmation e-mail');
                }
            }else{
                $action['result'] = 'error';
                array_push($text,'Confirm row was not added to the database. Reason: ' . mysql_error());
            }
        }else{
            $action['result'] = 'error';
            array_push($text,'User could not be added to the database. Reason: ' . mysql_error());
        }
    }
    $action['text'] = $text;
}
?>

私のサニタイズ機能が役立つと思いました-オンラインで取得しましたが、少し役に立たないようです. あるいは、クロス サイト スクリプティングの防止に役立つだけかもしれません。ここにあります:

 function cleanInput($input) {
        $search = array(
            '@<script[^>]*?>
.*?</script>@si',   // Strip out javascript
    '@<[\/\!]*?[^<>]*?>@si',            // Strip out HTML tags
    '@<style[^>]*?>.*?
    </style>
@siU',    // Strip style tags properly
    '@<![\s\S]*?--[ \t\n\r]*>@'         // Strip multi-line comments
    );
    $output = preg_replace($search, '', $input);
    return $output;
    }
function sanitise($input) {
    if (is_array($input)) {
    foreach($input as $var=>$val) {
    $output[$var] = sanitise($val);
    }
    }
    else {
    if (get_magic_quotes_gpc()) {
    $input = stripslashes($input);
    }
    $input  = cleanInput($input);
    $output = $input;
    }
    return $output;
}

その機能が役に立たないことを示唆しますか?

もしそうなら、元のコードのビットを保護するにはどうすればよいですか? すなわち:

    $username = ($_POST['username']);
    $password = ($_POST['password']);
    $email = ($_POST['email']);
4

3 に答える 3

3

プリペアド ステートメント、PDO または mysqli を使用します。私は個人的に PDO を好みますが、どちらも機能します。

于 2013-01-22T07:43:34.103 に答える
3

何をするにしても、ここで注射について読んでください。このサイトでわかるように、できれば PDO を使用して、準備済みステートメントを使用するのがよい方法です。

$stmt = $pdo->prepare('SELECT foo from db.bar WHERE foobar = :something;');
$stmt->execute(array(':something' => $_POST['something']));

魔法の引用符のような非推奨の機能に頼る必要はありません。また、実際には、そのmysql_*拡張機能に含まれるものは何もありません。後者は完全に廃止されており、最終的には言語から完全に削除されるためです (できれば近いうちに)。

あなた(または他の誰か)がなぜPDOが好まれると思うのか疑問に思っている場合:

  • 複数のドライバー (MySQL、MSSQL、PostrgreSQL など) をサポートしています。完全なリストはこちら
  • mysqli_*その OO API は、手続き型 API も提供しているのに対し、時代に合わせて調整されています。これは、主に OOP に慣れていない人にとってプラスと見なされますが、遅かれ早かれ学ぶ必要があります。
  • 個人的には、PDO の方が広く使用されているという印象を受けます。PHP はオープン ソースの製品であるため、重要なのはコミュニティが使用するものです。サポート期間が長くなり、より適切にテストされるでしょう (そして、より多くの人々によって)そしてあなたが立ち往生している場合は、より多くのピアサポートがあります.
  • PDO は準備をエミュレートします。これをオフにすることはできますが、速度が低下します。また、エミュレートするとき、PDO は使用しているプレースホルダーを詳しく調べます。たとえば、一部の奇抜なドライバーが名前付きプレースホルダーをサポートしていない場合でも、それらを使用できますが、PDO はそれらを に置き換える?か、man ページで「より適切なもの」と述べています。全体として、PDO は非常に賢いです :)
于 2013-01-22T07:47:02.340 に答える
0

リストした関数はどれもSQLインジェクションに接続されていません:)

  • ストリップスラッシュは、魔法の引用符から回復するためのものです
  • 魔法の引用符は誤った機能であり、言語から既に削除されています
  • mysql_real_escape_string (使用方法) - マジック クォートの手動レプリカ

実際のところ、エスケープ (マジック クォートと real_escape によって行われる) は、適切に作成されたクエリに必要な実際の書式設定のほんの一部にすぎません。「すべてをエスケープすれば大丈夫」という1つのルールだけでなく、一連のルール全体に従う必要があります。

それにもかかわらず、それが注射からあなたを守る魔法の杖としてではなく、その場所で使用されている限り、逃げることは本質的に悪いことではありません. たとえば、PDO は内部でずっと使用しています。

「準備されたステートメントを使用する」も魔法の杖ではなく、「すべてをエスケープする」と同じマントラであることに注意してください-不十分で安全でもありません。

以前投稿したいくつかの説明

その機能が役に立たないことを示唆しますか?

この機能は非常に有害であることをお勧めします

同様の質問からのいくつかの説明

これを行う本当に良い方法はありますか?

クエリに動的部分を追加するには、常にプレースホルダーを使用してください。安全性が高く、非常に便利に使用できます。準備されたステートメントがプレースホルダーを使用する唯一の方法ではなく、明らかに最も信頼できるものではないことに注意してください。

また、アプリケーション コードで生の API 呼び出しを使用することは、PDO、mysqli、mysql のいずれであっても同様に悪いことに注意してください。生の API 関数ではなく、抽象化ライブラリを使用して SQL を処理する必要があります。

また、PDO を宣伝するほとんどの人は、実際のプロジェクトで PDO を使用したことがないこと、または少なくともその「利点」の一部を使用したことがないことを覚えておいてください。彼らは実際、他の人から聞いたのと同じテキストを繰り返すだけです ;)

  • たとえば、「複数データベースのサポート」は頻繁に使用されるものではありません。もちろん、DSN 文字列を変更するだけの簡単なことでもありません。データベースを切り替えるのは非常に面倒な作業であり、さまざまな API 関数があれば問題はほとんどありません。
  • または、「エミュレーションをオフにすると遅くなる」と言う人は、実際に試したことがないだけです:)
  • または、「PDO は非常に賢い」と言う人に、配列から入力された IN 句を使用して単純なクエリを作成するよう依頼してください ;)
于 2013-01-22T07:39:32.207 に答える