web-dev-qa-db-ja.com

これは実用的なSQLインジェクションです。サーバー側のクエリ文字列はどのように見えますか?

この質問は、より大きな学校の課題の細部についてです。私はこの小さな問題に長い間取り組んできました。

ABCTFは今年初めに開催されたCapture-the-Flagコンテストをアレンジしました。この競争における問題の1つは、SQLインジェクションでした。 これはURL からタスクの説明へ、 これはURL から注入されるログインフォームへ。この問題に対する公開された解決策があり、次のようになります。

ユーザー名:-1 'union select 1,1,1,1#

パスワード:1

バックエンドクエリ文字列がどのように見えるかを理解する必要があります。最も単純で最も単純な仮定は、

String query = "SELECT FROM user WHERE username = '" + inputA + "' AND password = '" + inputB + "';";
execute(query);

しかし、これは

String query = "SELECT FROM users WHERE username = '-1' union select 1,1,1,1 #' AND password = '1';";
execute(query);

これの最も明白な問題は、引用符が不均衡であることです。さらに、SELECTステートメントが生成する出力がわかりません。私が理解しているように、「#」文字は、「#temporary_table」のように、MS SQL Serverの一時テーブルを示すために使用されます。私は他の単純なステートメントでも遊んだことがありますが、意味がありません。

バックエンドクエリがどのように見えるかを理解している人はいますか?任意の提案をいただければ幸いです。

4
Magnus

リンクは、解決策には、すべての値が1であるunionを介してまったく新しい偽の行を追加することが含まれることを示しています。行。例は次のコードです。

password = execute("SELECT password FROM users WHERE username = '{$username}'");
if( password != $password ) fail();
pass();

その結果

password = execute("SELECT password FROM users WHERE username = '-1' union select 1,1,1,1 #'");
// no username called -1 means that the only row returned is the artificial row, so password = 1
if( password != 1 ) fail();
pass();

SQLのみからWebアプリケーションの脆弱性まで、このコードが機能する方法は数百万あることに注意してください。ただし、この方法が最も現実的であることがわかりました。

2
James Cameron

MySQLでは、#記号は、 コメントマーカーとして使用できます。 コメント内の引用符のバランスをとる必要はありません。

すべてのSQLインスタンスがMicrosoftデータベースで実行されるわけではありません。

7
John Deters