web-dev-qa-db-ja.com

パスMD5でのSQLインジェクション

ログインフォームでSQLインジェクションが可能かどうかを知りたい。ある場合、エクスプロイトのWebフォームエントリはどのように見えるでしょうか?ユーザー名とパスワードをHTML形式(POST)で送信します。ログイン機能コードは次のとおりです。

 
 $ username = $ _POST ['user']; 
 $ password = $ _POST ['pwd']; 
 $ password = md5(password); 
 
 $ sql = "SELECT id_user、name FROM 'TAB_USER' WHERE user = '$ username' AND passwd = '$ password' AND enable = 'Y'"; 
 
 $ result = mysql_query($ sql、$ dbCon); 
 $ check = mysql_num_rows($ result); 
 mysql_free_result($ result); 
 
 if($ check == '1'){
 $ result = mysql_query($ sql、$ dbCon); 
 $ array = mysql_fetch_array($ result); 
 
 $ id = $ array ['id_user']; 
 $ name = $ array ['name']; 
 
 $ _SESSION ['SES_id_user'] = $ id ; 
 $ _SESSION ['SES_name'] = $ name; 
 
 return $ id; 
} 
 else return false; 
 
1
stefano

短い答え:いまいましい脆弱です。

理由あなたはPOSTによって与えられる値を連結します。これらはユーザーが入力したものから直接来ます。したがって、クエリを操作するのは非常に簡単です。また、廃止予定のmysql拡張機能を使用しています。インジェクションから保護する準備済みステートメントを作成するには、mysqliまたはPDOを使用する必要があります。

Stackoverflowの question は、問題の詳細と解決方法を説明しています。

余談ですが、MD5は壊れたアルゴリズムであるため、パスワードの暗号化にしないでください。説明されているようにbcryptまたはPBKDF2の使用を検討してください ここ

15
Simon

あなたはこれを書きます:

$sql = "SELECT id_user, name FROM 'TAB_USER' WHERE user = '$username'
                                                           ^^^^^^^^^
                                                    SQL injection is here

悪者は "username"として送信し、置換後、SQLコマンドは次のようになります。

SELECT id_user, name FROM 'TAB_USER' WHERE user = 'Admin'; -- (some stuff here)

つまり、攻撃者は「ユーザー名」を次の文字列に設定します:Admin'; --

気の利いた引用文字を参照してください。それが攻撃のてこです。コードはSQLコマンドの$usernameを「クライアントが提供したもの」で残酷に置き換えるため、クライアントは、文字列定数を終了する終了引用文字、コマンドを終了するセミコロン、次にコマンドに終了する--データベース「行のその他はすべてコメントです。無視してください」。そして、データベースが行うことは無視してください!

これにより、使用したパスワードに関係なく、攻撃者は管理者としてログインできます。これは教科書SQLインジェクションです。注意してください:あなたは問題が「引用」文字から来ていると結論づけたくなるかもしれません、そして単にフィルタリングするだけで攻撃を回避するのに十分でしょう。これはそうではありません。あなたが行うような残忍な置換を悪用する方法はいくつかありますが、それらすべてを捕まえることは非常に困難です。ポケモンのように、SQLデータベースソフトウェアの新しいバージョンごとに新しい種が導入されます。人々はSQLインジェクションを「厄介な文字のエスケープ」問題と考えようとしました。したがって、彼らは この関数 を設計しました。それから彼らは 再試行 です。そして、それはまだ失敗しました。この道では悲しみだけがあなたを待っています。歩かないで。 mysql_really_escape_string_this_time_i_said_please()を待つ必要はありません。代わりに、 準備済みステートメント を使用します。

10
Thomas Pornin

ユーザー入力のみが脆弱であり、パスワードは安全です。

クエリSQLインジェクションパターンの例(ユーザー入力に使用する必要があります)。

'or'1'='1 and enable='Y'--
user'or 1=1--
'or 1=1--

攻撃者は、16進のMD5であり、16進のMD5出力パターンは([a-fA-F\d] {32})であるため、pwdパラメータを使用して注入できず、クエリの注入を制御できません。

さらに、すべてのCookieがSES_id_userおよびSES_nameと連携してユーザーのログインをチェックする場合、メカニズムは安全ではありません。

-------

更新:

PHP mysql_queryメソッドは複数の(スタックされた)クエリをサポートしていません であるため、攻撃者はDROPやETCなどのスタックされたクエリを実行できません。

4
Sajjad Pourali

これは、基本的な自動化された攻撃に対しても脆弱です。 "'; Drop Table' TAB_USER '; SELECT id_user、name FROM' TAB_USER 'WHERE user =' someuser"( "s"を除く)などの入力により、スクリプトから3つのコマンドが実行されます。最初のコマンドは有効な選択です、2番目はテーブルを完全に削除し、3番目は別の選択を実行します(テーブルがなくなったため、3番目のクエリは失敗しますが、これは一般的な考え方を提供します)。

クエリに進む前にユーザー入力を検証するか、パラメーター化されたSQLを使用する必要があります。たとえば、ユーザー名の場合、実際には句読点のない英数字である必要があります。これにより、挿入に対して安全になります。 SQLステートメントはそれがユーザー値であり、コマンドを含むべきではないことをSQLステートメントが理解しているため、パラメータ化されたSQLは優れた二次防御線です。

他の人が述べたように、パスワードストレージメカニズムはハッシュ化されておらず高速アルゴリズムであるため、非常に安全ではありません。そのため、指定されたハッシュを生成するプレーンテキスト値を検索するために使用できる大きなRainbowテーブルが存在します。 DB。これらを組み合わせることで、データベースを悪用するだけでなく、DBをまったく変更せずに別のユーザーにログインすることも簡単になります(セッションへのHASHを選択し、後でダンプして、パスワードを検索することにより、 MD5用の既存のRainbowテーブル。

3
AJ Henderson