SQLインジェクションに関する探偵小説、時には盲目

良い一日!



私はそれについての記事を書くとは思わないだろう、なぜなら 私はこのトピックはかなりハッキーだと思った。 しかし、 この記事から判断すると、聴衆は興味深いです。 このコメントを書く必要があると確信した。



この話は「私の知り合いのなじみのある知り合い」で起こりましたが、簡潔にするために、「I」だけを使用して彼の言葉から引用を書きます。 一週間半前でした。 行こう



あるヨーロッパの国への移動の可能性に照らして、私はヨーロッパの言語を一つ学ぶ必要がありました。 そして、ポッドキャストを使って言語を学ぶことが提案されている素晴らしいサイトを見つけました。 ポッドキャスト自体は無料ですが、レッスンノートと演習が含まれたPDFを購入できます。 私はこれらの記録は本当に必要ありませんが、私の妻は私のとは異なり、まったく監査員ではなく、彼女はまた言語を学ぶ必要がありました。 インターネットで何かを購入する前に、販売者のウェブサイトを注意深く調べます。データがどこかに漏洩することは望ましくありません。 そしてこの場合、すべてが悪い以上であることが判明しました。 何かを買いたいという欲求はすぐに消えました。 しかし、PDFなしで残ることはスポーツマンらしくない。 最後に、見つかった脆弱性のいずれかを使用することを決定しました。 私は基本的に自動脆弱性スキャナーを使用せず、原則としてリソースのユーザーを傷つけないことをすぐに言わなければなりません。リソースの所有者が不器用に書いたのは彼らのせいではありません。 したがって、私のツールは、脆弱性の出現と使用の理由に対する理解と理論的知識です。



開始する


まず、PDFとしてダウンロードできるいくつかのデモを見ました。 まず、ユーザーは次の宛先に送信されました。



/guide.php?id=lesson_id







この時点で、現在のユーザーが指定されたPDFをダウンロードする権利を持っているかどうかがチェックされます。 その場合、次へのリダイレクトがあります。



/download.php?f=filename.pdf







すぐに、このスクリプトは何もチェックせずに指定されたファイルを提供することが判明しました。 なぜなら レッスン番号1のアクセス可能な例のファイル名は001.pdfでした。私は総当たりですべてのファイルを取得しようとすることにしました。 すべてが非常に単純な場合は、何も書く必要はありません。 しかし、この方法では最初の100個のファイルのみが取得されました。 残りの名前には作成時間のタイムスタンプがあり、それらを整理することが不可能になりました。 作成時間は数か月異なりました。



SQLインジェクションを解きます


GETパラメーターで最も一般的なSQLインジェクションがすぐに検出されました。



/some_script.php?id=123







さらにその使用は非常に単純に構築されているようです:

  1. リクエスト内のパラメーターの数を決定する
  2. テーブルとフィールドの名前を選択します(MySQL 5.0以降の場合-information_schemaから選択します)
  3. 目的のファイル名を取得する
  4. ファイル自体をダウンロードする


しかし、問題は最初の点から始まりました-要求内のフィールドの数を決定することはできませんでした。 UNION SELECTの任意の数のフィールドおよびORDER BY nの任意の数について、「構文にエラーがあります...」というメッセージを受け取りました。



実際、偶然、問題が正確に何であるかを推測しました-GROUP BY 1を実行しようとしています。これで「cntでグループ化できません」というエラーが発生しました。 脆弱なパラメーターが2回使用されていることが判明しました(少なくとも、この仮定に反論することはできませんでした)。



最初に、指定されたIDを持つレコードの数が選択されます。



SELECT count(*) FROM table where id=123







エントリ数が0の場合、ページが見つからないと見なされ、メインページへのリダイレクトが発生します。 レコード0がない場合、情報が取り出されます。



SELECT * FROM table where id=123







これで、クエリ内のフィールドの数を見つけることができなかった理由が明らかになりました。フィールドは2つあり、そのうち1つは常にUNIONのフィールド数が間違っています。 UNIONの異なる数のフィールドを最初のリクエストと2番目のリクエストに挿入する方法を思いつきませんでした。 そしてその瞬間、SQLインジェクションは盲目になりました。 ファイルパスでテーブルの名前を見つけることができませんでしたが、ユーザーデータでテーブルの名前を見つけることができました(MySQL 4.1)。



開発者各位、2つのリクエストをしないでください。 この場合、SELECTカウント(*)の代わりに、SELECT *クエリによって返されたレコードの数を確認できました。



今では、有用な情報を取得する方法を考え出す必要があります。 私はこれが好きでした:



/script.php?id=123 limit 0,0 union all select length(username)>4 from tablename limit 0,1--







ここに見えるもの:



したがって、HTTPヘッダーを使用して、正しい条件を渡したかどうかを判断できます。 最初に、ユーザー名の長さを決定し、次にバイナリ検索で、名前自体を引き出します(下位(substr(username、1,1))in( 'a'、 'b'、 'c'))。 次に、パスワードを一文字ずつ引き出します。 しかし、パスワードはmd5でハッシュされていることがわかります。 ハッシュはソルトフリーですが、サイト管理者のパスワードを見つけることはまだできませんでした(レインボーテーブルはありませんでしたが、ネットブックでブルートフォースをしたくありませんでした。また、スポーツマンらしくないです)。



いくつかの考えの後、それは他の方法で行くことに決めました。 なぜなら データベースは60,000人以上のユーザーであることが判明したため、それらの多くが一般的なパスワードを持っていると思いました。 そして、パスワードハッシュがmd5(「パスワード」)であるユーザー名を1文字ずつ取り出すだけで済みました。それらは100以上あり、その中に必要なPDFを購入した人がいました。 そして、彼らは親切に私とそれらを共有することに同意しました。



これはすべて、HEADリクエストを送信する非常にシンプルなスクリプトを使用して行われ(ページの本文が必要な理由は?)、応答ヘッダーを確認しました。 200の場合、条件は真であり、302の場合、真ではありません。



おわりに


なぜこれがすべて書かれているのですか? 脆弱性の本質と原因を知る必要があり、それらの使用方法を暗記する必要がないことを示すため。 インターネットで見たSQLインジェクションを使用するすべての方法は、ORDER BY 5またはUNION SELECT 1,2,3によってフィールドの数を決定することを提案しました...そして、考えたくない人はサイトを何も残さないでしょう。



また、ハッシュを壊すのではなく、私の回避策に少し誇りを持っています。 さて、 それほど前はないが、現代のインターネット上でのこのような脆弱性の存在とブラインドSQLインジェクションの実際の使用について懐疑論が表明されました。



PS現実とのすべての偶然の一致はランダムです。 有名人の声がシミュレートされ、悲惨です。



All Articles