Skip to content
KitploitKITPLOIT
StrumentiBlog
Log in
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.

FeedContattoPrivacy© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
cve-2026-22732-poc — Proof-of-concept che dimostra CVE-2026-22732, una vulnerabilità di Spring Security in cui setIntHeader("Content-Length") elimina tutti gli header di sicurezza, con build vulnerabili e corrette. | Kitploit
Strumenti/GitHubGitHub/dylan-chainguard/cve-2026-22732-poc
Strumenti DifensiviAnalisi delle VulnerabilitàExploitVirtualizzazione per la SicurezzaSicurezza WebApprendimento e Formazione
GitHubdylan-chainguard/cve-2026-22732-poc

cve-2026-22732-poc

Proof-of-concept che dimostra CVE-2026-22732, una vulnerabilità di Spring Security in cui setIntHeader("Content-Length") elimina tutti gli header di sicurezza, con build vulnerabili e corrette.

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 →
Vedi Repository
11620 giorni faNon ancora revisionato
Condividi

CVE-2026-22732 — Proof of Concept

Spring Security elimina silenziosamente gli header di sicurezza delle risposte HTTP. Solo per uso dimostrativo/educativo; eseguilo solo contro questa app locale.

CVECVE-2026-22732 (CWE-425), pubblicata il 2026-03-19
CVSS 3.19.1 CRITICAL — AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N
Dipendenza direttaspring-boot-starter-web + spring-boot-starter-security 2.7.18
Componente vulnerabilespring-security-web / -config / -core 5.7.11 — solo transitiva, mai dichiarata nel pom.xml
Componente correttaspring-security-web 5.7.14-0.cgr.2, raggiunta con un solo cambio di <version> — vedi la transizione
Verificato suTomcat 9.0.118, JDK 17.0.18, macOS arm64

Intervalli interessati: 5.7.0–5.7.21, 5.8.0–5.8.23, 6.3.0–6.3.14, 6.4.0–6.4.14, 6.5.0–6.5.8, 7.0.0–7.0.3. Spring Boot 2.7.18 fissa Spring Security 5.7.11, pienamente all'interno del primo intervallo:

$ mvn dependency:tree -Dincludes=org.springframework.security
+- org.springframework.security:spring-security-config:jar:5.7.11:compile
|  \- org.springframework.security:spring-security-core:jar:5.7.11:compile
\- org.springframework.security:spring-security-web:jar:5.7.11:compile

Esecuzione

./run.sh        # terminale 1 — compila e avvia su :8080 (fissa JDK 17)
./exploit.sh    # terminale 2 — interroga ogni endpoint, confronta gli header

run.sh fissa JAVA_HOME perché Spring Boot 2.7.x non può girare sul JDK 25 che mvn risolve per default su questa macchina. Sovrascrivi con JAVA_HOME_17=/path/to/jdk17.

Compila anche con -s settings-chainguard.xml per default, perché il parent corretto non è su Maven Central. Imposta MAVEN_SETTINGS=/path/to/your/settings.xml per puntare altrove, oppure MAVEN_SETTINGS= per compilare esclusivamente da Central — cosa che funziona solo con il 2.7.18 originale.

exploit.sh legge le versioni effettive di spring-security-web e spring-boot da target/*.jar, quindi il suo banner riporta sempre ciò che è realmente in esecuzione anziché una stringa hardcoded.

Il setup

SecurityConfig non applica nessuna personalizzazione degli header — sono in vigore i default di Spring Security, che è esattamente ciò su cui si basa un'app attenta alla sicurezza. Ogni endpoint restituisce lo stesso body sensibile:

{"account":"4111-1111-1111-1111","holder":"D. Havelock","balance":"82914.55"}

L'unica cosa che varia è come il controller scrive la risposta.

Risultati misurati

BASELINE  standard Spring MVC return value
  /safe/account                    OK        all 6 headers delivered

CONTROL   getOutputStream(), body > 8 KB buffer
  /vuln/stream/account             OK        all 6 headers delivered

CONTROL   explicit response.flushBuffer()
  /vuln/flush/account              OK        all 6 headers delivered

EXPLOIT   setIntHeader("Content-Length", n)  <-- CVE-2026-22732
  /vuln/content-length/account     BYPASSED  ALL 6 security headers dropped

BY DESIGN application sets its own Expires header (NOT this CVE)
  /vuln/cache/account              PARTIAL   Cache-Control + Pragma dropped

Solo /vuln/content-length/account cambia stato quando la CVE viene corretta, quindi è l'unico endpoint da cui exploit.sh deriva il suo verdetto. Gli altri sono controlli.

La CVE — setIntHeader("Content-Length", n) → bypass totale

Tre righe di codice del controller dall'aspetto ordinario eliminano ogni header che Spring Security aveva promesso:

response.setContentType("application/json");
response.setIntHeader("Content-Length", body.length);
response.getOutputStream().write(body);
$ curl -sD - -o /dev/null http://localhost:8080/vuln/content-length/account
HTTP/1.1 200
Content-Type: application/json
Content-Length: 77
Date: Tue, 01 Sep 2026 00:53:18 GMT

Nessun X-Frame-Options, nessun X-Content-Type-Options, nessun Cache-Control, nessun Pragma, nessun Expires, nessun X-XSS-Protection. Confronta con /safe/account, che li porta tutti e sei. La risposta è incorniciabile da qualsiasi origine, MIME-sniffable e cacheable — mentre serve un numero di carta.

Il caso by-design — header di cache impostato dall'applicazione → soppressione della cache

Corretto: una versione precedente di questo README lo chiamava "exploit 2" e sosteneva fosse la condizione documentata nell'advisory. Non fa parte di CVE-2026-22732 e nessun aggiornamento lo corregge. CacheControlHeadersWriter è identico byte per byte in 5.7.11, 5.7.14-0.cgr.2, 6.5.8 (ultima vulnerabile) e 6.5.9 (prima corretta) — verificato confrontando i sources jar. Il suo Javadoc afferma esplicitamente il comportamento: "Inserts headers to prevent caching if no cache control headers have been specified."

Vale comunque la pena dimostrarlo, perché la fuga è reale e il rischio residuo sopravvive alla patch. CacheControlHeadersWriter si ferma se Cache-Control, Expires o Pragma è già presente, quindi impostare uno qualsiasi dei tre sopprime tutte le direttive no-store di Spring Security. Una sola riga ben intenzionata lo fa:

response.setHeader("Expires", "Thu, 01 Jan 2099 00:00:00 GMT");
/safe/account                  NOT cacheable  (Cache-Control: no-cache, no-store, max-age=0, must-revalidate)
/vuln/cache/account            CACHEABLE      (Cache-Control: absent / Expires: Thu, 01 Jan 2099 00:00:00 GMT)
/vuln/content-length/account   CACHEABLE      (Cache-Control: absent / Expires absent)

Expires conta come "presente" nella tabella sopra, ma con un valore favorevole all'attaccante scelto dall'app — l'Expires: 0 di Spring Security è stato sostituito, non semplicemente eliminato. I dati del titolare della carta sono ora memorizzabili da ogni browser e proxy condiviso sul percorso fino al 2099.

Sulla build corretta /vuln/content-length/account passa a NOT cacheable, mentre /vuln/cache/account resta esattamente come sopra. Solo il codice dell'applicazione o un reverse proxy lo corregge — che è la cosa utile da dire ad alta voce in una demo: aggiornare la libreria chiude la CVE e lascia questo intatto.

Due risultati negativi, mantenuti di proposito

Diversi write-up ampiamente diffusi — incluso un repo pubblico di riproduzione — elencano response.getOutputStream() e response.flushBuffer() come trigger, spiegando che "la risposta è committed prima che Spring Security possa iniettare i suoi header". Su Spring Security 5.7.11 questo è sbagliato. Entrambi gli endpoint consegnano tutti e sei gli header.

/diag/committed mostra perché la spiegazione non regge. Dopo una scrittura di 12 KB la risposta è davvero committed all'interno del controller, eppure gli header arrivano comunque:

>>> DIAG response.isCommitted() after 12048 byte write = true
    | wrapper class = org.springframework.security.web.header.HeaderWriterFilter$HeaderWriterResponse

OnCommittedResponseWrapper sovrascrive flushBuffer() e le scritture dell'output-stream, quindi emette i suoi header prima di quei commit. Il solo ordinamento dei commit non è il bug; il percorso con Content-Length dichiarato lo è. L'advisory di Spring stesso non avalla mai la storia dell'ordinamento dei commit.

Mantenere questi due endpoint rende il PoC falsificabile: mostra ciò che non si riproduce con la stessa chiarezza di ciò che si riproduce, ed entrambi restano verdi attraverso la patch, che è ciò che rende significativo l'unico endpoint che effettivamente cambia.

La transizione vulnerabile → corretta

Una riga nel pom.xml, nient'altro. Nessuna modifica al sorgente, nessuna modifica alle proprietà, nessun bump di major di Spring Boot:

Scarica lo strumento