この記事では、SQLインジェクションによる攻撃の詳細とその対策方法、および安全なWebサイトを作る方法について紹介します。
SQLインジェクションとは何かを理解するには、まずSQLについて知る必要があります。SQLとはコーディング言語のひとつで、データベース管理システム(DBMS)でユーザーからの情報要求をデータベースとそのデータテーブルに伝えるために使用されます。
たとえば、ユーザーがWebサイトの検索バーにキーワードを入力すると、裏でSQL文(データベースへの命令文)が生成されます。この命令文には、ユーザーが入力したキーワードと、DBMSへのコマンドが含まれています。これはデータベースに送られ、DBMSが解読して必要な情報を抽出し、ユーザーに返します。
データベースと連携するWebサイトやアプリケーションの多くは、上記で紹介した流れでユーザーからの入力情報をもとにSQL文を生成しています。しかし、アプリケーションに何らかの不備(SQLインジェクションの脆弱性)がある場合、予期しないSQL文が作成されてしまい、データベースを不正に利用される可能性があります。このアプリケーションの脆弱性を狙った攻撃を「SQLインジェクション攻撃」と呼びます。
SQLは、認識可能な英単語に依存するシンプルな言語で、コーディングコマンドとして使用されます。Webサイトやアプリケーションに脆弱性がある場合、ハッカーは不正な内容を含むSQL文を「注入(インジェクション)」し、データを盗むことができます。
ハッカーが、対策を行っていないWebサイトでSQL文を含む文字列を入力すると、DBMSはそれを実行可能な命令として読み取り、実行に移してしまうのです。このようにして、ハッカーはサイトの所有者が非公開にしている機密情報や個人情報を盗み出しています。
たとえば、ハッカーがあるオンラインストアから顧客のユーザー名とパスワードを盗み出そうとしているケースを想定してみましょう。Webサイトのセキュリティプロトコルが最新でないと、ハッカーがWebサイトの検索機能でコーディングコマンドの文字列を入力して攻撃を仕掛けることで、顧客の個人情報をすべて奪ってしまう可能性があります。
また、SQLインジェクション攻撃と同様に、脆弱なウェブサイトを狙って情報を盗み出す「クロスサイトスクリプティング」や「スクリプトインジェクション」と呼ばれる攻撃もあります。これらの攻撃は、ウェブサイトの脆弱性を狙った攻撃という点ではSQLインジェクションと共通していますが、攻撃の仕組みは大きく異なります。
SQLインジェクションの例として、UNIONコマンドが挙げられます。これは、ユーザーのメインクエリに「サブクエリ」を追加するために使用するコマンドです。これらのサブクエリにより、データベースに正規の検索結果とともに追加情報を返すように強制することができます。
この方法を悪用すると、ハッカーは、顧客のメールアドレス、ユーザー名、パスワードが含まれるデータテーブルへのアクセスが可能になります。SQLインジェクション攻撃から、ユーザーアカウントへの侵入、機密情報の盗み出し、さらにはWebサイトの管理権限の乗っ取りまでにかかる時間は微々たるもので、すぐに完了してしまいます。
前述の通り、SQLインジェクションは、Webサイトやアプリケーションに何らかのセキュリティ上の不備やバグがある場合に起こります。そのため、Webサイトやアプリケーション開発に携わる場合、脆弱性がないように作りましょう。
SQLインジェクション攻撃による被害を受けない安全なWebサイトを作るには、予期しないSQL文が送られてきても、DBMSが実行可能な命令として解読することなく、エラーとして正しく処理できるように設計することが重要です。
サイトが適切に保護されていない場合、ハッカーがSQLインジェクション攻撃を仕掛けることで、データベースにあるほとんどすべてのデータが狙われてしまいます。SQLインジェクション攻撃で想定される被害は具体的にどのようなものがあるのでしょうか?
機密情報や個人情報を扱うWebサイトやアプリケーションを運営している場合、企業の機密情報をはじめ、ユーザーのパスワードやクレジットカード情報までもが抜き取られるというリスクが考えられます。また、データの漏洩だけでなく、盗まれた情報が悪用されたり、第三者に売られたりする可能性もあります。
SQLインジェクションによる攻撃で、データベースの内容が漏洩するだけでなく、そのデータが改ざんされたり壊されたりする可能性も考えられます。万が一、Webサイトやアプリケーション内のデータが改ざんされてしまうと、業務に大きな支障をきたしたり、ユーザーを外部サイトへ誘導してマルウェアをダウンロードさせたりするというリスクがあります。
不正アクセスによりWebサイトの管理権限が乗っ取られてしまうと、上記で紹介した被害以上に深刻な問題が生じる可能性があります。Webサイトの権限を勝手に使われるだけでなく、最悪の場合サーバーごと乗っ取られることも考えられます。
また、金融サービスがSQLインジェクション攻撃の被害にあった場合、不正な送金や高額な取引が行われる恐れがあります。
データが一元管理されていれば、SQLインジェクションによる攻撃は深刻化します。たとえば、オンラインストアが攻撃に遭った場合、機密性の高いユーザーの個人情報が商品情報と同じデータベースに保管されているため、ハッキングによる被害が大きくなってしまいます。異なるデータベース間でデータを分離して保管することで、被害を最小限に抑えることができます。
SQLインジェクションを防ぐための最善策のひとつが、プリペアドステートメントの使用です。リスクの高いWebサイトでは、誰かがリクエストを送信するたびに新しいSQL文が生成され、ハッカーに独自のコードを注入する機会を与えてしまいます。
このような事態を避けるために、あらかじめ用意されたプリペアドステートメントを使用するようプログラミングします。プリペアドステートメントとは、変更する部分だけ変数のような命令文を作成することで、SQL文の特定の部分をいつでも変更できる状態にするテンプレートのことです。プリペアドステートメントを使うことで、ハッカーは文字列に新しいコマンドを追加することができなくなります。
Webサイトのバックエンドに入力バリデーションを組み込み、許容される文字や単語のホワイトリストを作成します。ホワイトリストは、検索可能な新しい項目がデータベースに追加されるたびに更新することができます。ハッカーが悪意のあるコーディングコマンドの文字列を入力したとしても、システムが入力データをホワイトリストと照合して、許可された入力値が見つからなかったら、コードは実行されず「結果なし」のメッセージが返されるだけの状態になります。