はじめに
このインタラクティブな実験へようこそ!今回は、Web アプリケーションにとって広く存在し深刻なリスクとなっている SQL インジェクション脆弱性に焦点を当てます。簡単に言うと、SQL インジェクション攻撃は、アプリケーションが適切にチェックまたはコーディングされていないデータを受け取り、そのデータが SQL クエリに含まれる場合に発生します。この脆弱性により、サイバー攻撃者は有害な SQL コマンドを実行でき、機密データへの不正アクセスやその他の有害な行為を引き起こす可能性があります。
この実験の目的は 2 つあります。まず、SQL インジェクション脆弱性の核心概念を解き明かし、理解しやすい形に分解することです。次に、悪意を持ってではなく、これらの脆弱性をよりよく理解し防止するために、実践的な演習を提供し、これらの脆弱性を悪用する方法を学ぶ手助けをします。この実践的なアプローチにより、アプリケーションをこのような脅威から守るための知識とスキルを身につけることができます。
ラボ環境をセットアップする
このセクションでは、SQL インジェクション攻撃を練習できる実験環境のセットアップ手順を案内します。
DVWA Docker イメージの取得: DVWA の Docker イメージは Docker Hub で入手できます。以下のコマンドを使用して取得できます。
docker pull vulnerables/web-dvwaDVWA Docker コンテナの実行: イメージを取得した後、以下のコマンドで実行できます。
docker run -d -p 80:80 --name dvwa vulnerables/web-dvwaこのコマンドは新しいコンテナを起動し、コンテナ内のポート 80 をホストマシンのポート 80 にマッピングします。
上記の手順で実験に必要な環境が整います。セットアップが完了したら、デスクトップの Firefox ブラウザを起動し、以下の URL を入力します:http://localhost。
しばらくすると、ログインページにアクセスできます。デフォルトの認証情報は以下の通りです:ユーザー名 - "admin"、パスワード - "password"。
DVWA (Damn Vulnerable Web Application) のウェブページが表示されます。「Create/Reset Database」ボタンをクリックして、アプリケーション用の新しいデータベースを作成します。
重要な注意: この実験では、セキュリティレベルを「low」に設定します。この設定により、SQL インジェクション脆弱性がより明確になります。これを行うには、「Security Level」のドロップダウンメニューから「low」を選択し、「Submit」ボタンをクリックします。
SQL インジェクションポイントを特定する
このモジュールでは、アプリケーション内の SQL インジェクション脆弱性の存在を明らかにします。
ステップ 1: SQL インジェクションページに移動する
アプリケーションの左側のメニューに「SQL Injection」というリンクがあります。このリンクをクリックして、SQL インジェクションページに移動します。ここでは、ユーザーID を求めるフォームが表示されます。
ステップ 2: サンプルのユーザーID を入力する
ユーザーID を入力して、何が起こるかを確認しましょう。
サンプル入力:
1
フォームに「1」と入力し、「Submit」ボタンをクリックします。出力には、ID が 1 のユーザーの詳細が表示されるはずです。
ステップ 3: ソースコードを確認する
「View Source」ボタンをクリックすると、ページのソースコードを確認できます。以下のような PHP コードが表示されるはずです。
$id = $_GET['id'];
$sql = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
$result = mysqli_query($conn, $sql);
このコードから、アプリケーションがユーザーの入力を直接 SQL 文に連結して SQL クエリを構築していることがわかります。これは、SQL インジェクション脆弱性を引き起こす可能性のある一般的なエラーです。
ステップ 4: SQL インジェクション脆弱性を確認する
SQL インジェクション脆弱性の存在を検証するために、値「1」の後にシングルクォート (') を注入してみましょう。フォームに以下を入力します。
1'
データベースエラーメッセージが表示された場合、アプリケーションが実際に SQL インジェクション攻撃に対して脆弱であることを意味します。これは、このような脆弱性を特定し、その後対処するための重要なステップです。
SQL インジェクションの種類とデータベースの種類を特定する
このセクションでは、与えられたアプリケーションが持つ SQL インジェクション脆弱性のタイプと使用されているデータベースのタイプを特定する手順を案内します。
まず、元の SQL クエリが返す列の数を特定します。これを行うために、ORDER BY句を使用します。
サンプルコード:
1' ORDER BY 1#
1' ORDER BY 2#
1' ORDER BY 3#
上記の SQL 文を順にフォームに入力してください。アプリケーションが正常に動作している場合、最初の 2 つのクエリはエラーなく実行され、3 つ目のクエリは失敗します。この失敗は、元の SQL クエリが 2 つの列を返していることを示しています。
これに続いて、UNION演算子を使用してデータベースから追加のデータを抽出することができます。
サンプルコード:
1' UNION SELECT version(), @@version_compile_os#
この SQL 文は、データベースのバージョンとそれが実行されているオペレーティングシステムのバージョンを取得します。
このクエリを実行した後、出力にはデータベースのバージョンとオペレーティングシステムに関する情報が表示されるはずです。
データベース名を取得する
このレッスンでは、アプリケーションが使用しているデータベースの名前を取得する手順を案内します。これは、特にデータベースの構造と組織を理解しようとする際に必要なスキルです。
サンプルコード:
1' UNION SELECT database(), user()#
上記の SQL クエリは、「SQL インジェクション」と呼ばれる手法の例です。これは、攻撃者がアプリケーションのデータベース層に存在するセキュリティ脆弱性を悪用するために使用するコードインジェクション手法です。この特定のクエリは、現在のデータベース名とクエリを実行しているユーザーを取得します。
以下に、具体的な動作を説明します。
1' UNION: これは SQL インジェクションの最初の部分です。1'の部分は、アプリケーションが実行している可能性のあるクエリを完成させるためのものです。UNIONキーワードは、2 つ以上の SELECT 文の結果を重複する行を返さずに結合するために使用されます。SELECT database(), user()#: このクエリの部分は、注入するペイロードです。database()関数は現在のデータベースの名前を取得し、user()関数はクエリを実行しているユーザーの名前を取得します。
クエリを送信した後、出力にデータベース名とユーザー情報が表示されることが期待されます。この情報は、データベース構造とアプリケーションのコンテキストにおけるユーザーの権限をさらに理解するために重要です。
これらの手法を理解することは、脆弱性を悪用するだけでなく、防御すべき点を知ることでセキュアなアプリケーションを作成するのにも役立つことを忘れないでください。
テーブル名を取得する
このレッスンでは、データベース内のテーブル名を取得することで、データベースの構造についてさらに詳しく調べます。データベース内のデータを抽出または操作しようとする場合、テーブル構造を理解することは非常に重要です。
サンプルコード:
1' UNION SELECT table_name, table_schema FROM information_schema.tables WHERE table_schema = 'dvwa'#
上記の SQL クエリは、引き続き SQL インジェクション手法を利用しています。今回は、データベース内のテーブル名とそれぞれのデータベーススキーマを取得するために使用されています。
以下に詳細を解説します。
1' UNION: 前に説明した通り、この部分はアプリケーションが実行している可能性のあるクエリを完成させ、それを注入したペイロードと結合するためのものです。SELECT table_name, table_schema FROM information_schema.tables WHERE table_schema = 'dvwa': このクエリの部分は、注入したペイロードです。information_schema.tablesシステムテーブルから、特に 'dvwa' スキーマに属するテーブル名とそれぞれのデータベーススキーマを取得します。
information_schema.tables は、データベース内のすべてのテーブルに関する情報を保持するシステムテーブルです。table_schema は、テーブルが属するデータベースの名前を指し、table_name はテーブルの名前です。
クエリを送信した後、出力にテーブル名とそれぞれのデータベーススキーマが表示されることが期待されます。この情報は、データベースのさらなる探索や悪用のためのロードマップとなります。
いつものように、これらの手法を理解することは、脆弱性を悪用するだけでなく、防御すべき点を理解することでセキュアなアプリケーションを作成するためにも不可欠です。
列名とデータを取得する
このレッスンでは、特定のテーブルの列名を取得することで、データベース構造をより深く調べます。この知識を利用して、テーブルから潜在的に機密性の高いデータを抽出することができます。
サンプルコード:
1' UNION SELECT 1, group_concat(column_name) FROM information_schema.columns WHERE table_name = 'users'#
上記の SQL クエリは、SQL インジェクションを使用して 'users' テーブルの列名を取得します。これらの列名は、閲覧しやすいように 1 つの文字列に連結されます。
以下に詳細を解説します。
1' UNION: 前に説明した通り、この部分はアプリケーションが実行している可能性のあるクエリを完成させ、それを注入したペイロードと結合するためのものです。SELECT 1, group_concat(column_name) FROM information_schema.columns WHERE table_name = 'users': このクエリの部分は、注入したペイロードです。'users' テーブルから列名を取得し、group_concat関数を使用してそれらを 1 つの文字列に連結します。
クエリを送信した後、出力に列名が表示されることが期待されます。
これで列名がわかったので、'users' テーブルから機密データを取得することができます。
サンプルコード:
1' UNION SELECT user, password FROM users#
この SQL クエリは、SQL インジェクションを使用して 'users' テーブルから 'user' 列と 'password' 列を取得します。
クエリを送信した後、出力にユーザー名とハッシュ化されたパスワードが表示されることが期待されます。この情報は非常に機密性が高く、このような情報がどのように抽出されるかを理解することは、脆弱性を悪用するためにも、このような攻撃から防御するためにも不可欠です。
これらの手法を理解する目的は 2 つあります。潜在的な脆弱性を特定することと、よりセキュアなアプリケーションを構築することです。このことを忘れないでください。
まとめ
この実験では、SQL インジェクション脆弱性について学び、実践を通じてそれを悪用する方法を習得しました。脆弱な Web アプリケーションをセットアップし、SQL インジェクションポイントを特定し、SQL インジェクションのタイプとデータベースのタイプを判断し、SQL インジェクション脆弱性を悪用してデータベースから機密情報を取得しました。
この実験を完了することで、最も一般的で危険な Web アプリケーション脆弱性の 1 つである SQL インジェクション脆弱性を理解し、悪用する実践的な経験を積むことができました。この知識は、実際のシナリオでこのような脆弱性を特定し、軽減するのに役立ち、Web アプリケーションのセキュリティスキルを向上させるでしょう。