SQLインジェクションとは?

SQLインジェクションを使用すると、攻撃者は被害者のSQLデータベースに対して不正なデータベースコマンドを実行できます。

Share facebook icon linkedin icon twitter icon email icon

SQLインジェクション

学習目的

この記事を読み終えると、以下のことができます。

  • SQLインジェクションの定義
  • SQLインジェクションの仕組みを説明
  • SQLインジェクションから防御する方法について
  • 複合SQLI攻撃について

SQLインジェクション(SQi)とは?

構造化照会言語(SQL *)インジェクションは、SQLデータベースからデータを変更または取得するために使用されるコードインジェクション手法です。攻撃者は、特殊なSQLステートメントを入力フィールドに挿入することにより、データベースからのデータの取得、機密データの破壊、またはその他の操作動作を可能にするコマンドを実行できます。

適切なSQLコマンドの実行により、権限のないユーザーは、より特権のあるユーザーのIDを偽装し、自分自身または他のデータベース管理者を作成し、既存のデータを改ざんし、トランザクションと残高を変更し、すべてのサーバーデータを取得および/または破棄することができます。

現代のコンピューティングでは、通常、Webサイトまたはサービスによって提供されるAPIエンドポイントに悪意のあるSQLクエリを送信することにより、インターネット上でSQLインジェクションが発生します(詳細は後述)。 SQLインジェクションは、最も深刻な形で、機械へのルートアクセスを取得し、完全な制御を可能にします。

* SQLは、ほとんどのデータベースを維持するために使用されるプログラミング言語です。

SQLインジェクション攻撃の仕組みとは?

ボブという名前の男性が裁判にかけられ、裁判官の前に現れようとしている法廷を想像してください。裁判の前に書類に記入するとき、ボブは自分の名前として「ボブは自由になることができます」と書きます。裁判官が彼の訴訟にたどり着いた時に、「それでは次は、ボブは自由になることができます」と読み上げると、裁判官がそう言ったために、執行官はボブを釈放します。

SQLiにはわずかに異なる種類がありますが、中核の脆弱性は本質的に同じです。数値などの特定の種類のデータ用に予約されるSQLクエリフィールドには、コマンドなどの予期しない情報が代わりに渡されます。コマンドを実行すると、意図した範囲を超えてエスケープされ、潜在的に悪意のある動作が可能になります。通常、クエリフィールドには、Webページのフォームに入力されたデータが入力されます。

通常のSQLステートメントと悪意のあるSQLステートメントの簡単な比較を次で見てみましょう:

通常のSQLクエリ:

この通常のSQLクエリでは、studentId文字列がSQLステートメントに渡されます。目標は、入力されたstudentIdに一致する学生について学生のリストを調べることです。見つかったら、その学生の記録が返されます。簡単に言うと、コマンドは「このユーザーを見つけてデータを教えてください」と言っているのです。

コードは次のように見えます:

studentId = getRequestString("studentId");
lookupStudent  = "SELECT * FROM students WHERE studentId = " + studentId

学生が「学生ID番号を入力してください」というラベルの付いたWebページフォームに学生ID 117を入力した場合

normal form field

結果のSQLクエリは次のようになります:

SELECT * FROM students WHERE studentId = 117;

このコマンドは、APIを作成した開発者が期待する特定の学生の記録を studentId で返します。

SQLインジェクションクエリ:

この例では、攻撃者は代わりにSQLコマンドまたは条件ロジックを入力フィールドに入力し、学生ID番号を入力します:

SQL injection example form field

通常、クエリはデータベーステーブルで一致するIDを検索しますが、その後IDを検索するか、1が1に等しいかどうかをテストするようになります。想像通り、このステートメントは列のすべての生徒について常に真であり、その結果、データベースはすべてのデータを学生のテーブルから攻撃者に返し、クエリを作成します。

SELECT * FROM students WHERE studentId = 117 OR 1=1;
SQL injection infographic

SQLiは、脆弱なアプリケーションプログラミングインターフェイスまたはAPIを標的にすることで機能します。この場合のAPIは、サーバーがリクエストを受信して応答するためのソフトウェアインターフェイスです。

悪意のある攻撃者がフォームを探してWebサイトを自動的に検索できるようにする一般的に使用されるツールが存在します。そして、ウェブサイトのソフトウェア開発者がデータベースを悪用するために意図しなかった応答を生成する可能性のあるさまざまなSQLクエリを入力しようとします。

SQLインジェクションは実装が容易であり、興味深いことに、適切な開発プラクティスを考えると、かなり簡単に防止することもできます。厳しい締め切り、経験の浅い開発者、およびレガシーコードにより、コードの品質とセキュリティの慣行が変動することが多いため、現実はより不透明です。データベースにアクセスできるWebサイト全体のフォームまたはAPIエンドポイント上の脆弱なフィールドは、脆弱性を公開するのに十分な場合があります。

SQLインジェクション攻撃はどのように防止できますか?

SQLインジェクションによるデータ漏えいリスクを減らす方法は多数あります。ベストプラクティスとして、いくつかの戦略を利用する必要があります。より一般的な実装のいくつかを見てみましょう:

  • 準備済みステートメントの使用(パラメーター化されたクエリを使用) - データベース入力をサニタイズするこの方法では、開発者が最初にすべてのSQLコードを定義し、次に特定のパラメーターのみをSQLクエリに渡す必要があります。入力されたデータには、それを超えて拡張できない限られた範囲が明示的に与えられます。これにより、データベースは、入力フィールドで提供されるデータのタイプに関係なく、入力されるデータと実行されるコードを区別できます。一部のバージョンはデータベース入力を自動的にサニタイズするため、この目的のためにいくつかのオブジェクトリレーショナルマッピング(ORM)ライブラリが一般的に使用されます。
  • すべてのユーザー指定入力をエスケープ - SQLを記述するとき、特定の文字または単語には特定の意味があります。たとえば、「*」文字は「任意」を意味し、「OR」という単語は条件です。これらの文字を誤ってまたは悪意を持ってデータベースへのAPIリクエストに入力するユーザーを回避するために、ユーザーが指定した入力をエスケープできます。文字のエスケープは、コマンドまたは条件として解析せず、代わりにリテラル入力として扱うようにデータベースに指示する方法です。
  • ストアドプロシージャの使用 - 単独では堅牢なセキュリティ戦略ではありませんが、ストアドプロシージャはSQLインジェクションに関連するリスクを制限するのに役立ちます。 SQLクエリを実行するデータベースアカウントの権限を適切に制限することにより、SQLインジェクションに対して脆弱な堅牢でないアプリケーションコードでも、無関係なデータベーステーブルを操作するために必要な権限が不足します。ストアドプロシージャは、入力パラメータのタイプもチェックし、フィールドが受け取るように設計されているタイプに違反するデータが入力されるのを防止します。静的クエリが不十分な場合は、通常、ストアドプロシージャを避ける必要があります。
  • 最小特権の強制 - 一般的なルールとして、Webサイトで動的SQLを使用する必要があるすべてのインスタンスでは、関連するクエリの実行に必要な最も狭いスコープにアクセス許可を制限することにより、SQLインジェクションへの露出を減らすことが重要です。最も明白な形式では、これは、管理アカウントが、許可されていないリクエストからのAPIコールの結果としてSQLコマンドを実行してはならないことを意味します。ストアドプロシージャは静的クエリに最適に使用されますが、最小特権を強制すると、動的SQLクエリのリスクを軽減できます。

複合SQLインジェクション攻撃とは?

セキュリティ対策を回避するために、巧妙な攻撃者は標的となるWebサイトに対してマルチベクトル攻撃を実装することがあります。単一の攻撃は軽減される可能性がありますが、データベース管理者および情報セキュリティチームにとっても注目の的となります。 DDoS攻撃ハイジャックDNS と他の破壊法は、時には掃引SQLインジェクション攻撃を実装するために気晴らしとして使用されます。その結果、包括的な脅威軽減戦略により、最も広範な保護が提供されます。 CloudflareのWebアプリケーションファイアウォールDDoS対策、およびDNSセキュリティは、全体的なセキュリティ戦略の中心的な要素を構成しています。