跳到主要内容

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_userrolsuper 结果留档,确认走的是超级用户还是角色路径。
  • 回读文件确认命令真实执行成功,而非语句报错造成的假象。
  • 注入场景注意引号闭合与注释符(-- -)是否稳定。

防御建议

  1. 应用连接一律使用最小权限账号,禁用超级用户。
  2. REVOKE pg_execute_server_program,仅运维角色按需授予。
  3. 监控日志中的 COPY TO PROGRAM 关键字并告警。
  4. 收紧数据库服务器目录权限,减少可写落盘位置。

相关知识