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-2023-24329-lab | Kitploit
Strumenti/GitHubGitHub/jithinodattu/cve-2023-24329-lab
Analisi delle VulnerabilitàExploitSicurezza WebCTFPenetration TestingApprendimento e FormazioneLab e Pratica
GitHubjithinodattu/cve-2023-24329-lab

CVE-2023-24329-lab

Vedi Repository
4 mesi 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-2023-24329 — Laboratorio di Differenze di Parsing

Solo a scopo didattico. Questo laboratorio esiste per dimostrare una vulnerabilità reale in un ambiente sicuro e isolato. Non eseguirlo mai contro sistemi che non possiedi. Non riutilizzare mai il codice di filtro volutamente difettoso in alcun sistema di produzione.

Un laboratorio Docker autonomo che dimostra CVE-2023-24329 — una differenza di parsing in urllib.parse.urlparse() di Python che consente di aggirare i filtri su schema URL e hostname su Python < 3.11.4.

Il laboratorio mostra un'API che blocca esplicitamente gli URL file:// e gli hostname interni, che viene ingannata per leggere /etc/passwd dal proprio container e per raggiungere un servizio interno privato — poi dimostra che lo stesso exploit fallisce su Python aggiornato.


La Vulnerabilità

L'implementazione di urlparse() di Python e i relativi fetcher HTTP/file non concordano su come gestire gli URL con spazi bianchi iniziali. Nelle versioni interessate:

root@kitploit:~
from urllib.parse import urlparse

urlparse(" file:///etc/passwd").scheme   # → ""   (vuoto — il filtro passa)
urlparse(" file:///etc/passwd").hostname # → None (vuoto — il filtro passa)

Ma urllib.request.urlopen(" file:///etc/passwd") rimuove lo spazio e recupera comunque file:///etc/passwd.

Quel divario tra ciò che vede il parser e ciò che fa il fetcher — quella è la vulnerabilità.

Python 3.11.4 ha corretto il problema rimuovendo spazi bianchi e caratteri di controllo iniziali prima del parsing, chiudendo il divario.


Demo — Tre Prove


Architettura

Quattro servizi su una rete Docker bridge isolata (cve-lab-net):

internal-service non ha mapping di porte verso l'host — è raggiungibile solo dall'interno della rete Docker, simulando un vero confine di fiducia.


Prerequisiti

  • Docker Desktop (oppure Docker Engine + plugin Compose)
  • ~500 MB di spazio su disco per le immagini

Avvio Rapido

root@kitploit:~
git clone <repo-url>
cd CVE-2023-24329-lab

Prova 1 — Baseline: il filtro dovrebbe reggere

root@kitploit:~
docker compose -f docker-compose.vulnerable.yml up --build -d
docker compose -f docker-compose.vulnerable.yml exec attacker python exploit.py baseline

Prova 1 — il filtro di base regge

Prova 2 — Exploit: aggira il filtro

root@kitploit:~
docker compose -f docker-compose.vulnerable.yml exec attacker python exploit.py exploit

Prova 2 — bypass riuscito, /etc/passwd e segreto interno esposti

Prova 3 — Patch: stesso payload, Python aggiornato

root@kitploit:~
docker compose -f docker-compose.vulnerable.yml down
docker compose -f docker-compose.fixed.yml up --build -d
docker compose -f docker-compose.fixed.yml exec attacker python exploit.py verify

Prova 3 — la patch regge su Python 3.11.4

Smontaggio

root@kitploit:~
docker compose -f docker-compose.fixed.yml down

Struttura delle Directory

root@kitploit:~
CVE-2023-24329-lab/
├── docker-compose.vulnerable.yml   # Python 3.11.3 (vulnerabile)
├── docker-compose.fixed.yml        # Python 3.11.4 (aggiornato)
├── vulnerable-api/
│   ├── app.py                      # API Flask con il filtro ingenuo
│   ├── requirements.txt
│   └── Dockerfile
├── internal-service/
│   ├── app.py                      # Endpoint fittizio di metadati interni
│   ├── requirements.txt
│   └── Dockerfile
└── attacker/
    ├── exploit.py                  # Driver demo (baseline / exploit / verify)
    ├── requirements.txt
    └── Dockerfile

I servizi API vulnerabile e aggiornato condividono lo stesso codice sorgente — solo la versione di Python nell'immagine base differisce. Questa è la proprietà fondamentale di controllo scientifico del laboratorio.


Come Funziona il Bypass

Il filtro dell'API vulnerabile (semplificato):

root@kitploit:~
parsed = urllib.parse.urlparse(url)

if parsed.scheme.lower() in {"file", "gopher", "ftp", "data"}:
    return 403  # blocked

if parsed.hostname in {"localhost", "127.0.0.1", "internal-service"}:
    return 403  # blocked

urllib.request.urlopen(url)  # fetch the original, unmodified string

Il payload di bypass è un singolo spazio iniziale:

root@kitploit:~
 file:///etc/passwd
^
spazio (0x20)

Su Python ≤ 3.11.3, urlparse vede uno schema vuoto e nessun hostname → il filtro passa. urlopen rimuove lo spazio → recupera file:///etc/passwd.

Su Python ≥ 3.11.4, urlparse rimuove prima lo spazio → vede correttamente scheme=file → il filtro blocca con 403.


La Correzione (Cosa Fa Python Aggiornato)

Issue CPython issue #102153 — la correzione rimuove i caratteri di controllo C0 e gli spazi dall'inizio dell'URL prima del parsing. Dopo la patch, sia il parser sia il fetcher concordano su cosa sia l'URL, quindi il filtro non può essere aggirato in questo modo.

Il pattern difensivo corretto indipendentemente dalla versione di Python:

root@kitploit:~
# Parse → ricostruisci dalle componenti → passa l'URL ricostruito a valle.
# Sia il filtro sia il fetcher operano quindi sulla stessa stringa.
parsed = urllib.parse.urlparse(url)
safe_url = parsed.geturl()  # ricostruito dalle componenti
urllib.request.urlopen(safe_url)

Punti Didattici Chiave

  1. Le differenze di parsing sono una classe di vulnerabilità, non un bug isolato. La stessa idea è alla base dello smuggling di richieste HTTP, degli attacchi di confusione SAML e dei bypass di log4j con ${jndi:...}.
  2. Le blocklist falliscono quando il parser ti mente. Elencare input dannosi è una partita persa.
  3. Valida l'URL ricostruito, non la stringa di input grezza.
  4. Una versione minore, una piccola patch, conseguenza enorme. La correzione in CPython è di poche righe.

Riferimenti

  • NVD: CVE-2023-24329
  • Issue CPython: github.com/python/cpython/issues/102153
  • Divulgazione originale: Yebo Cao — cerca "CVE-2023-24329 Yebo Cao"
  • Classe più ampia: PortSwigger — tecniche di bypass dei filtri SSRF
  • Classe più ampia: James Kettle — HTTP Desync Attacks

Limitazioni di Sicurezza

  • Non esporre mai le porte di internal-service verso l'host.
  • Non eseguire mai questo laboratorio su una macchina connessa a una rete di produzione.
  • Il codice di filtro in vulnerable-api/app.py è volutamente difettoso per scopi didattici — non copiarlo in alcun sistema reale.

Licenza

MIT — libero di usare, condividere e adattare per scopi educativi con attribuzione.

Scarica lo strumento
ProvaCosa vediCosa insegna
1 — Baselinefile:///etc/passwd → 403 blocked schemeIl filtro sembra ragionevole
2 — ExploitStesso URL con uno spazio iniziale → 200 + contenuto di /etc/passwd e segreto internoUn singolo spazio sconfigge l'intero filtro
3 — PatchStesso payload contro Python 3.11.4 → 403 blockedurlparse aggiornato rimuove gli spazi prima; il filtro lo intercetta correttamente
ServizioVersione PythonRuoloPorta host
vulnerable-api3.11.3API di destinazione con filtro URL ingenuo8000
fixed-api3.11.4Stesso codice, interprete aggiornato8000
internal-service3.12Endpoint fittizio di metadati interninessuna
attacker3.12Driver dell'exploitnessuna