PostgreSQL COPY TO PROGRAM 命令执行
PostgreSQL 的 COPY ... TO PROGRAM 语句会把查询结果交给操作系统 shell 执行。当会话具备超级用户(如 postgres)或 pg_execute_server_program 角色时,它就是一条从 SQL 到系统命令执行的直通路径。
利用前先判定当前会话权限,再决定执行方式与回显手段。
仅限授权环境
该操作直接在数据库服务器上执行系统命令,仅可用于授权测试与靶场环境。
判断前提
通过 SQL 注入拿到 DB 会话时,先判定当前用户与版本:
%' UNION SELECT 1,current_user,version()-- -
随后查询角色表的 rolsuper 字段,确认当前用户是否为超级用户。
成立条件:
| 条件 | 说明 |
|---|---|
| 超级用户会话 | postgres 用户直接成立 |
| pg_execute_server_program 角色 | 非超级用户但被授予该角色同样可行 |
方法 A:COPY TO PROGRAM 执行命令
COPY (SELECT '') TO PROGRAM 'id > /tmp/pg_id 2>&1';
命令结果没有直接回显时,用 pg_read_file 回读:
SELECT pg_read_file('/tmp/pg_id');
方法 B:注入场景下的分步执行
注入点命令长度受限时,先分步写入脚本文件,再执行该脚本,避免单条语句过长。
与可写路径结合
结合服务器上的可写路径,可以把脚本落地为持久化文件,便于后续重复触发与结果回读。
复核要点
current_user与rolsuper结果留档,确认走的是超级用户还是角色路径。- 回读文件确认命令真实执行成功,而非语句报错造成的假象。
- 注入场景注意引号闭合与注释符(
-- -)是否稳定。
防御建议
- 应用连接一律使用最小权限账号,禁用超级用户。
REVOKE pg_execute_server_program,仅运维角色按需授予。- 监控日志中的
COPY TO PROGRAM关键字并告警。 - 收紧数据库服务器目录权限,减少可写落盘位置。
相关知识
- Linux 提权方法与检查清单 — 拿到数据库服务器 shell 后的下一步