Dokploy:メンバー アカウントからホスト root への RCE
Dokploy のメンバーがデータベースのパスワードにバッククォートを入れ、ホストで root としてコマンドを実行できる。修正は canary のみ。
要点
- データベース サービスを作成できる Dokploy 組織のメンバーは、ホストで root としてコマンドを実行できます。手段はデータベースのパスワードにバッククォートを入れること(バリデータが許可します)、またはデータベースのユーザー名にセミコロンを入れること(ユーザー名にはバリデータがありません)です。
- Dokploy v0.29.0 から v0.31.0 が影響を受け、2026 年 11 月 5 日に公開された v0.31.0 が現在の脆弱なリリースです。攻撃者にはサービス作成権限を持つメンバー アカウントが必要で、未認証の欠陥ではありません。
- この問題に CVE や CVSS スコアは割り当てられていません。研究者は公式 v0.31.0 イメージに対するライブ証明を報告し、Dokploy が同じ前提条件クラスを CVE-2026-72868 で 9.9 と採点したと述べています。現実の攻撃は確認されておらず、2026 年 11 月 10 日時点で CISA の Known Exploited Vulnerabilities (KEV) カタログにも掲載されていません。
- 修正は Dokploy の canary ブランチにマージ済みで、タグ付きリリースには含まれていません。信頼できないメンバーからサービス作成権限を今すぐ外してください。パッチを適用するか、修正を含むリリースを待ってください。「修正方法」を参照してください。
影響を受けますか?
次のすべてに当てはまる場合に影響を受けます。
- セルフホストの Dokploy v0.29.0 から v0.31.0 を実行している。脆弱なパスワード バリデータは v0.29.0 で導入され、研究者はすべてのブランチで変更されていないと述べています。
- 組織のメンバーにサービス作成権限とデータベース サービスへのアクセスを与えている。Dokploy の
changePasswordプロシージャは、データベース コマンドを実行する前にservice: ["create"]を確認します。 - メンバーがパネルに到達できる。単一管理者のインストールでは、管理者がすでに権限を持っているため、越える境界はありません。
研究者は公式 dokploy/dokploy v0.31.0 イメージをテストし、ライブ証明を報告しています。修正は canary ブランチの pull request #5910 のコミット 1c862c9cb0 のマージで、2026 年 11 月 9 日 16:59 UTC にマージされました。リリース タグは v0.31.0 で止まっています。
| ブランチ | 影響を受けるバージョン | 修正バージョン |
|---|---|---|
| セルフホスト Dokploy | v0.29.0 から v0.31.0 | 2026 年 11 月 10 日時点でタグ付きリリースなし。修正は canary の pull request #5910 |
実行中のイメージとバージョンを確認します。
docker inspect --format '{{.Config.Image}}' dokploy
docker images dokploy/dokploy
パネルもインターフェースにバージョンを表示します。v0.29.0 から v0.31.0 のタグのイメージは影響を受けます。pull request #5910 を含む canary ビルドには修正がありますが、リリースではありません。
修正方法
修正済みリリースはまだありません。修正は canary にマージされているため、次のいずれかを選びます。
- pull request #5910 の canary コミットを含む Dokploy イメージをビルドまたは取得し、パネルを再デプロイします。データベース ルーターに
quote()呼び出しが含まれることを確認してから依存してください。 - canary ビルドを実行できない場合は、同じ変更をビルドに適用します。
docker exec <container>の後の各引数をquote()に通します。これはshell-quoteパッケージのものです。 - パネルが修正されるまで、必要としないすべてのメンバーからサービス作成権限を外します。データベースを作成できるメンバーはホストの root 相当として扱ってください。
- Dokploy パネルへのアクセスを信頼できるネットワークに限定し、インターネットに直接公開しないでください。
- 監査ログで説明できないデータベース パスワード変更を確認し、見つかった場合はデータベース資格情報をローテーションします。
- pull request #5910 またはこの修正を名指しする Dokploy のタグ付きリリースを監視し、更新後にバージョンを確認します。
研究者の論文が修正範囲の参照元です。pull request は Postgres、MySQL、MariaDB、MongoDB、Redis のパスワード経路を変更します。
根本原因は何ですか?
Dokploy のパスワード バリデータは複数のシェル文字をブロックしますが、バッククォート、セミコロン、パイプ、アンパサンド、括弧、リダイレクトは許可します。changePassword プロシージャはその後、パスワードを bash が解析する docker exec コマンドに補間し、データベースのユーザー名はバリデータなしで補間されます。
これが v0.31.0 の apps/dokploy/server/src/db/schema/utils.ts にあるバリデータです。
/** Database password: blocks shell-dangerous characters like $ ! ' " \ / and spaces. */
export const DATABASE_PASSWORD_REGEX =
/^[a-zA-Z0-9@#%^&*()_+\-=[\]{}|;:,.<>?~`]*$/;
コメントはブロックする文字を挙げています。文字クラスにはまだ `、;、|、&、(、)、>、< が含まれます。これでコマンド置換と 2 つ目のコマンドに十分です。
これが v0.31.0 の Postgres の changePassword プロシージャです。
const command = `docker exec ${container.Id} psql -U ${databaseUser} -d postgres -c "ALTER USER \\"${databaseUser}\\" WITH PASSWORD '${password}';"`;
await db.transaction(async (tx) => {
...
if (serverId) {
await execAsyncRemote(serverId, command);
} else {
await execAsync(command, { shell: "/bin/bash" });
}
});
databaseUser は保存された Postgres レコードから来て、バリデータがありません。-U の後に引用符なしで置かれます。パスワードは単一引用符の中ですが、-c 引数全体が二重引用符の中にあります。bash は二重引用符の中でバッククォートと $() を展開するため、P2`id` のようなパスワードはシェルがコマンドを構築する間に id を実行します。databaseUser のセミコロンはコマンドを終了させ、別のコマンドを開始します。
コマンドは Dokploy サーバー プロセスで execAsync 経由で /bin/bash とともに実行されます。そのプロセスはサーバー コンテナの root で、ホストの Docker ソケットを保持しています。そこでのコマンド実行は実質的にホストの root です。
同じ構築が MySQL、MariaDB、MongoDB のルーターにもあります。研究者は Postgres と MySQL の経路を発火させたと報告し、他の 2 つをソース上同一と述べています。Redis の経路はパスワードを最上位の単一引用符に置くため発火せず、これがメカニズムを証明する対照です。
どのように悪用されますか?
データベース サービスを作成できるメンバーが、シェルの引用を閉じる値にパスワードまたはユーザー名を変更します。Dokploy サーバーは注入されたコマンドを root として実行します。
- 攻撃者はサービス作成権限を持つ組織メンバーとして Dokploy にサインインするか、すでに組織を制御している場合はそのメンバーを作成します。
- 攻撃者はデータベース サービスを作成するか、アクセスできるサービスを使用します。サービスの Postgres レコードはユーザー名を保存します。
- 攻撃者は
changePasswordを、DATABASE_PASSWORD_REGEXを通過するがバッククォートを含むパスワード、たとえばP2`id>x`で呼び出します。バリデータはバッククォートを禁止していないため受け入れます。 - Dokploy は
docker execコマンドを構築し、/bin/bashに渡します。bash はバッククォートでコマンド置換を行い、idを実行して出力を攻撃者が選んだファイルにリダイレクトします。データベースのパスワード変更も完了します。 - あるいは、攻撃者はデータベースのユーザー名にセミコロンを設定します。ユーザー名にはバリデータがないため、引用符なしの
psql -U引数に到達し、2 つ目のコマンドを開始します。 - コマンドは Dokploy サーバー コンテナで root として実行されます。コンテナはホストの Docker ソケットを保持しているため、攻撃者はそれを使ってホストと他のテナントのサービスに到達できます。
研究者のライブ証明は、まず無害なパスワードを使い、次にバリデータが拒否した $(id) パスワードを使いました。その後、バッククォートのパスワードが 200 を返し、サーバー コンテナ内に uid=0(root) gid=0(root) と表示する canary ファイルを残しました。テストは localhost にバインドした環境で公式 v0.31.0 イメージに対して実行されました。研究者は MySQL 経路を 2 つ目の入口、セミコロン入りのユーザー名を 3 つ目として発火させたとも報告しています。
現実の攻撃は確認されていません。公開記録は研究者の oss-security メッセージ、そこでリンクされた論文、マージされた修正です。
攻撃の流れは?
サービス作成権限を持つメンバーがバリデータを通るパスワードを送信し、そのパスワードが docker exec 内の bash コマンドに到達します。bash は注入されたコマンドを、ホストの Docker ソケットを保持するコンテナで root として実行します。
攻撃者に何ができますか?
注入を発火させた攻撃者は、Dokploy サーバー コンテナで root としてコマンドを実行し、その Docker ソケットを通じてホストに到達できます。これはパネル、それが管理するすべてのサーバー、各テナントの秘密の制御です。
条件は影響の一部です。
- 攻撃者には、サービス作成権限とデータベース サービスへのアクセスを持つ認証済みの Dokploy メンバー アカウントが必要です。研究者は未認証ではなく、組織間の失敗でもないと述べています。
- 単一管理者のインストールでは、管理者がすでに権限を持っているため、パネル ユーザーとホストの間に境界はありません。
- コマンドはサーバー コンテナで root として実行されます。そのコンテナは設計上ホストの Docker ソケットをマウントまたは到達するため、攻撃者は特権コンテナを起動し、他のサービスの環境変数を読み、ホストのファイルシステムに到達できます。
- 注入はパスワード変更の送信時に発火します。データベースのパスワードも変更されるため、ペイロードが実行されている間も操作は成功したように見えます。
- 現実の攻撃は確認されておらず、被害者も名指しされていません。
影響はデータベースではなくホスト レベルです。データベースを作成できるメンバーはすでにそのサービスを信頼されています。この欠陥はその信頼をホストと他のテナントの制御に変えます。
修正が機能する理由
修正は quote() を shell-quote から使って各 docker exec コマンドを引数配列から構築するため、パスワードとユーザー名は単一の引数のままで、bash はその内容を構文として解析しません。
これが pull request #5910 の apps/dokploy/server/api/routers/postgres.ts の変更です。
- const command = `docker exec ${container.Id} psql -U ${databaseUser} -d postgres -c "ALTER USER \\"${databaseUser}\\" WITH PASSWORD '${password}';"`;
+ const command = `docker exec ${container.Id} ${quote([
+ "psql",
+ "-U",
+ databaseUser,
+ "-d",
+ "postgres",
+ "-c",
+ `ALTER USER "${databaseUser}" WITH PASSWORD '${password}';`,
+ ])}`;
quote() は各引数についてシェル用に引用した文字列を返すため、databaseUser や password 内のバッククォートやセミコロンはその引数内に留まります。SQL 文は 1 つの -c 引数のままで、データベースはリテラルのパスワードを受け取ります。pull request は、バリデータが単一引用符を禁止しているためパスワードは SQL 文字列内で安全なままだと述べています。
同じ書き換えが MySQL、MariaDB、MongoDB、Redis のルーターをカバーします。修正はバリデータを変更しないため、メンバーはバッククォート付きのパスワードを設定できます。違いは、バッククォートがシェルに到達しなくなったことです。
侵害されたかどうかを確認するには?
侵害の指標は公開されていません。パネルの監査ログとデータベース レコードで、エクスプロイトが必要とする入力を確認します。
- Dokploy の監査ログで、説明できないデータベース パスワード変更とデータベース サービス作成を確認します。
changePasswordプロシージャはコマンド実行後に監査エントリを書き込みます。 - 保存されたデータベースのパスワードとユーザー名に、バッククォート、セミコロン、パイプ、その他のシェル メタ文字がないか確認します。バリデータが許可するがシェル構文に見える値は手がかりです。
- Dokploy サーバー コンテナ内の予期しないファイル、特に canary ファイルやデータベース コマンドが作成したシェル スクリプトを探します。
- サーバー コンテナで予期しない root プロセス、新しい特権コンテナ、外向き接続を確認し、ホストの Docker イベントで自分が起動していないコンテナを確認します。
- 手がかりを見つけたら、ホストを再構築する前にパネルのデータベース、サーバー コンテナ、Docker イベントを保存します。パネルが保存するすべてのデータベースとサービスの資格情報をローテーションします。
失敗した注入は、パスワード変更の監査エントリ以外の痕跡を残さない場合があります。監査エントリだけでは悪用を証明しません。
年表
- 2026-11-05: Dokploy が v0.31.0 を公開します。これが現在のリリースで、研究者がテストしたバージョンです。
- 2026-11-07: pull request #5910「fix(security): database changePassword command injection (all 5 DB types)」が開かれます。
- 2026-11-09 16:59 UTC: pull request が canary ブランチにマージされます。タグ付きリリースには含まれません。
- 2026-11-10 02:11 UTC: 研究者が oss-security メーリング リストでライブ証明付きの開示を公開します。
よくある質問
Dokploy の欠陥は未認証ですか?
いいえ。攻撃者には、サービス作成権限とデータベース サービスへのアクセスを持つ認証済みの組織メンバーが必要です。研究者は前提条件を明確に述べ、組織間の失敗ではないとしています。
Dokploy v0.31.0 は修正済みですか?
いいえ。v0.31.0 は現在のリリースで、研究者がテストしたバージョンです。修正は canary ブランチの pull request #5910 にあり、2026 年 11 月 9 日にマージされましたが、2026 年 11 月 10 日時点でタグ付きリリースには含まれていません。
この問題に CVE はありますか?
2026 年 11 月 10 日時点で CVE は割り当てられていません。Dokploy は同じ前提条件クラスの別の欠陥 CVE-2026-72868 を CVSS v3.1 9.9 と採点しました。そのスコアは以前の destination.testConnection 注入のもので、この問題のものではありません。
公開されたエクスプロイトはありますか?
研究者は手法、ライブ証明、論文を公開し、証明は公式 v0.31.0 イメージに対して再現できます。公開メッセージに独立したエクスプロイト リポジトリはリンクされていません。
すべての Dokploy メンバーを root と見なすべきですか?
データベース サービスを作成できるメンバーはこの欠陥でホスト root に到達できるため、その権限についてははい。必要としないメンバーからサービス作成を外し、パネル自体を root 相当のシステムとして扱ってください。
ホストされた Dokploy サービスに影響しますか?
Dokploy はセルフホスト可能なソフトウェアです。開示と修正はセルフホストのパネルに関するものです。公開記録にホストされたサービスは名指しされていないため、この記事はそれについて主張しません。
参考資料
- 研究者の oss-security 開示「Dokploy: the validator allows the backtick : a member's database password change is host RCE, 9.9 on the vendor's own vector (v0.31.0, live-proven)」、2026 年 11 月 9 日、ライブ証明、範囲、論文リンク: https://www.openwall.com/lists/oss-security/2026/11/10/2 (2026 年 11 月 10 日確認)
- Dokploy pull request #5910「fix(security): database changePassword command injection (all 5 DB types)」、2026 年 11 月 7 日作成、2026 年 11 月 9 日マージ: https://github.com/Dokploy/dokploy/pull/5910 (2026 年 11 月 10 日確認)
- 脆弱な
DATABASE_PASSWORD_REGEX(v0.31.0 のapps/dokploy/server/src/db/schema/utils.ts): https://github.com/Dokploy/dokploy/blob/v0.31.0/apps/dokploy/server/src/db/schema/utils.ts#L50-L52 (2026 年 11 月 10 日確認) - 脆弱な Postgres
changePasswordコマンド(v0.31.0 のapps/dokploy/server/api/routers/postgres.ts): https://github.com/Dokploy/dokploy/blob/v0.31.0/apps/dokploy/server/api/routers/postgres.ts#L448 (2026 年 11 月 10 日確認) - Dokploy v0.31.0 リリース、2026 年 11 月 5 日公開: https://github.com/Dokploy/dokploy/releases/tag/v0.31.0 (2026 年 11 月 10 日確認)
- CVE-2026-72868 レコード、以前の Dokploy
destination.testConnectionrclone 注入、CVSS v3.1 9.9、同じ前提条件クラスに対するベンダーのスコアとして引用: https://www.cve.org/CVERecord?id=CVE-2026-72868 (2026 年 11 月 10 日確認) - Docker Hub リポジトリ
dokploy/dokploy、16,116,660 プル、2026 年 11 月 10 日確認: https://hub.docker.com/r/dokploy/dokploy (2026 年 11 月 10 日確認) - CISA の Known Exploited Vulnerabilities カタログ JSON フィード、2026 年 11 月 10 日確認、Dokploy のエントリなし: https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json (2026 年 11 月 10 日確認)