コンテンツにスキップ

SQL インジェクション

データベースからデータを盗み出そう

近年では Gmail や Outlook.com といった Web メールがよく用いられています。 通常メールのやり取りの中には膨大な個人情報が含まれており、ハッカーにとっては美味しい標的です。 ハッカーになった気持ちで、セキュリティ上の欠陥がある Web メールサービスから他人のメールを盗み出してみましょう。

Web サーバーとデータベース

Web サービスは様々な要素で構成されていますが、通常はあなたの端末(パソコンやスマホなど)と直接通信する Web サーバーと、データを保存しておくデータベースを持っています。 Web サーバーはあなたの要求に合わせ、データベースから必要なデータを取り出し、あなたのために表示します。

さて、このメールサービスには検索機能がついており、あなたは友人の Aさん からのメールを検索したとしましょう。 あなたの端末は、まず Web サーバーに「Aさん からのメールが見たいです」と要求します。

すると、Web サーバーは、データベースに対して必要なデータを問い合わせます。このやりとりは、SQL と呼ばれる言葉を介して行われます。

SQL はプログラミング言語のようなものなので、Web サービスを作るプログラマが事前に用意しておかなければなりません。 しかし、この例のような検索機能では、データベースに問い合わせを行う際の条件はあなたの操作に応じて変わるので、データベースの問い合わせに用いる SQL もその条件に応じて変わります。 そこで、Web サービスのプログラマは、SQL の雛型のみを用意し、その雛型にあなたが指定した条件を埋め込みます。

例えば、プログラマが用意した SQL の雛型が

差出人=「⭐️」かつ受取人=「🌙」であるようなメールを取得

のようなものであったとしましょう。 あなたが Aさん からのメールが欲しいと Web サーバーに要求すれば、Web サーバーはこの雛型の ⭐️Aさん に、🌙あなた に置き換えます。 これにより最終的にデータベースに対して送られる SQL は

差出人=「Aさん」かつ受取人=「あなた」であるようなメールを取得

になるのです。

悪意のある要求

Aさん があなたに送ったメールは、当然あなたしか閲覧できないはずです。 しかし、不届き者のハッカー、Xさん がこのメールを盗み見ようとしていました。

前項でお話ししたように、Web サーバーがデータベースに問い合わせを行う際、Web サーバーは検索条件に Web サービスの使用者が受取人と一致するという条件を加えます。 このため、Xさん が見られるのは受取人が Xさん であるようなメールだけであるはずです。 しかし、このサービスには欠陥があるため、Xさん はこの制限を掻い潜って他の人のメールを覗き見ることができてしまいます。

Xさん は何をしたのでしょうか。 答えはそこまで複雑ではありません。 Xさん は、検索条件として 「」 (かぎかっこ) を含むような文字列を指定したのです。 具体的には、「Aさん」または差出人=「Aさん からのメールが見たいです」のように Web サーバーに要求します。

すると、先ほどと同じように、Web サーバーは雛型の ⭐️Aさん」または差出人=「Aさん に、🌙Xさん に置き換えます。 これにより最終的にデータベースに対して送られる SQL は

差出人=「Aさん」または差出人=「Aさん」かつ受取人=「Xさん」であるようなメールを取得

のようになります。

SQL では、通常「かつ」は「または」より優先されます。 ですので、差出人=「Aさん」または差出人=「Aさん」かつ受取人=「Xさん」 という条件は、

  1. 差出人=「Aさん」
  2. 差出人=「Aさん」かつ受取人=「Xさん」

の条件のいずれかが満たされたときに満たされます。 2 の条件が満たされれば 1 の条件は常に満たされますので、この 2 つの条件は実質的に 差出人=「Aさん」 のみしか指定できていません。 したがって、XさんAさん が送ったメールを全て盗み見ることができてしまうのです。 このような攻撃手法を、SQL インジェクションと呼びます。

SQL インジェクションの実践

あなたはF国のプロ野球リーグの調査委員会のメンバーです。最近、F国のプロ野球リーグで八百長の疑惑が持ち上がり、リーグの試合結果が不正に 操作されている可能性があるとされています。あなたの任務は、この疑惑を解明し、関連する証拠を収集することです。調査の一環として、リーグ 関係者がやり取りするメールの内容を確認する必要があります。

SQL インジェクションの脆弱性を持つメールサービスを開く

SQL によりデータを取得するには、SELECT 文を用います。 事前情報により、このメールサービスでは、SQL の雛型として、次のような SELECT 文を用いていることが分かっています。

SELECT * FROM "Mail" WHERE "from" = '⭐️' AND "to" = 'あなた';

メールサイト上部にある入力欄に入力された内容が上の⭐️に代入されます。例えば、入力欄に Aさん と入力すると

SELECT * FROM "Mail" WHERE "from" = 'Aさん' AND "to" = 'あなた';

というSQL文になります。これによって、『送信者』が「Aさん」かつ『宛先』が「あなた」のメールを検索できます。

SELECT 文は、次のような構文を持ちます。

SELECT 取得する属性名 FROM データの種類 WHERE 条件

この例では、データの種類として Mail (メールのデータ)、取得する属性として * (メールが持つ全ての属性) を指定しています。

条件は、次のような書式で設定できます。属性名は " (ダブルクォーテーション)、値は ' (シングルクォーテーション) で囲まれていることに注意してください。 AND は「かつ」、OR は「または」を表しています。

"属性名" = '' ANDまたはOR "属性名" = '' ANDまたはOR ...

メールが持つ属性は

  • from: 差出人の名前
  • toType: toかccかbccか
  • to: 受取人の名前
  • date: 送信日時
  • subject: メールの件名
  • content: メールの本文

の 6 つであることが分かっています。

課題のヒント

入力欄に Aさん' OR "from"='Aさんと入力すると、 sql SELECT * FROM "Mail" WHERE "from" = '⭐️' AND "to" = 'あなた'; の⭐️に、入力内容が代入されるので、 データベースに送信されるSQL文は sql SELECT * FROM "Mail" WHERE "from" = 'Aさん' OR "from"='Aさん' AND "to" = 'あなた'; となり、Aさんが送信したメールをすべて抽出することができます。 ⭐️がAさん' OR "from"='Aさんに置き換わることで、全体としての意味が大きく変化していることに注目してください。