
CVE-2026-6471の概念実証エクスプロイト。PostgreSQLにおける論理デコードのdlopenを介した権限昇格を実証し、任意のコード実行とスーパーユーザーバックドアを達成します。
PostgreSQLの論理デコードでは、REPLICATION権限を保持する非スーパーユーザーロールが論理レプリケーションスロットを作成し、出力プラグインを選択できます。影響を受けるバージョンでは、その選択に対する認可チェックがないため、サーバーはプラグイン名が指すものをdlopen()します。ライブラリパスを指定すると、そのライブラリのコードがpostgresバックエンド内で、サーバーを実行するオペレーティングシステムアカウントとして実行されます。これは、データベースサーバーのOSユーザーとしての任意コード実行であり、アプリケーションデータを保持するデータベースにとっては事実上のサーバー乗っ取りとなります。
PostgreSQL 18.6、17.11、16.15、15.19、14.24で、output_plugin_libraries許可リスト(デフォルトはpgoutput, test_decoding)により修正されました。リストにないものは、dlopenの前にlibrary "X" may not be used as an output pluginというエラーになります。
両方のビルドに対して同じ手順を実行し、PostgreSQLのバージョンのみを変更します。低権限アカウント(LOGIN + REPLICATION、スーパーユーザーではない、OSアクセスなし)が通常の論理デコードサブスクライバーが行うことを実行し、その後、サーバーに任意のライブラリを出力プラグインとしてロードするよう要求します。脆弱なビルドでは、そのライブラリがpostgres OSユーザーとして実行され、永続的なスーパーユーザーバックドアロールを仕込みます。そのため、レプリケーション専用アカウントは、実行終了時に機能するスーパーユーザーログインを手に入れます。
| ステップ |
|---|
cve-2026-6471-postgres-logical-decoding-dlopen.txtはExploitmaticソリューション(.txt)です。データとアサートを含み、コードはありません。ランタイムはこれをボックスに対してリプレイします。ソリューションは実行時にpwn.soを配信し(ファイル内にbase64)、低権限レプリケーションロールとしてSQLを実行し、その後、ペイロードが仕込んだスーパーユーザーバックドアロールとしてログインします。pwn.cはペイロードライブラリのソースで、pwn.soはそのビルドです。postgres OSユーザーとして実行される単一のELFコンストラクタで、ローカルソケット経由でデータベーススーパーユーザーとして接続し(peer/trust)、永続的なロールcve6471_backdoor LOGIN SUPERUSER PASSWORD 'BackdoorPass1'を作成します。これはサーバーが実際にライブラリをロードした場合のみ実行されます。つまり、脆弱なビルドでのみ実行されます。サーバーイメージに一致するLinux libc上でgcc -Os -shared -fPIC -o pwn.so pwn.cでビルドします。前提条件: dockerへのアクセス権があること。
lab/フォルダには、このPoCの検証に使用した正確なレプリカが含まれています。2つのボックスをビルドして実行します(脆弱 = postgres 16.14、修正済み = postgres 16.15):
docker build -t pg-6471-vuln -f lab/Dockerfile.vuln lab
docker build -t pg-6471-fixed -f lab/Dockerfile.fixed lab
docker run -d --name pg-6471-vuln -p 15432:5432 -e POSTGRES_PASSWORD=lab-super-pw pg-6471-vuln
docker run -d --name pg-6471-fixed -p 15433:5432 -e POSTGRES_PASSWORD=lab-super-pw pg-6471-fixed
両方のボックスは、wal_level=logicalで標準の公式postgresイメージを実行します。初期化スクリプトlab/01-repro.shは、ソリューションが使用する低権限ロールrepro_rep LOGIN REPLICATION PASSWORD 'repropass'を作成します。これはスーパーユーザーではありません。
次にソリューションをリプレイします:
exploitmatic run cve-2026-6471-postgres-logical-decoding-dlopen.txt 127.0.0.1
変数オーバーライドで修正済みボックスを指定します。ファイル編集は不要です:
exploitmatic run cve-2026-6471-postgres-logical-decoding-dlopen.txt 127.0.0.1 \
--var ctr=pg-6471-fixed
ctrはdockerコンテナ、pwはレプリケーションロールのパスワードです。
| ターゲット | 結果 |
|---|---|
| postgres 16.14(脆弱)、wal_level=logical | 4/4検証済み、スーパーユーザーバックドアログインが機能 |
| postgres 16.15(修正済み)、wal_level=logical | 3/4未検証、バックドアなし |
許可されたテストおよび研究目的のみ、所有している、またはテスト許可を得たシステムに対して使用してください。このPoCは、認証後の権限昇格を示しています。既存の低権限データベースアカウントでREPLICATION属性を持つものと、postgres OSユーザーがロードできる場所に攻撃者制御のコードを配置する手段が必要です。これはリモートの未認証攻撃ではありません。ロードされたコードがデータベーススーパーユーザーに到達するのは、サーバーを所有するOSアカウントがローカルソケット経由でスーパーユーザーとして接続できるためです(peer/trust)。これは標準的なPostgreSQLデプロイメントの慣行です。
| 脆弱な16.14 |
|---|
| 修正済み16.15 |
|---|
| 偵察(ロールはレプリケーション、スーパーユーザーではない) | 成功 | 成功 |
| ベースライン(組み込みpgoutputによる論理スロット) | 成功 | 成功 |
| トリガー(スロットプラグイン = 攻撃者ライブラリパス) | サーバーがロード | ロード前に拒否 |
| 乗っ取り(仕込まれたスーパーユーザーバックドアとしてログイン) | スーパーユーザー | そのようなロールは存在しない |