GEMASTIK Final 2024
Buffer overflow leads to account takeover / information disclosure
FJB
Web - Pwn
Story Time
Last year, i got into GEMASTIK 2024 Final stage with Abdiery, and Haalloobim and i did not solve anything at the time. This was an attempt to upsolve the problem FJB.
Say it a year long overdue writeup :)
There are actually two bugs in this challenge, an integer overflow and a buffer overflow, but i will only write the buffer overflow part π
Initial Analysis
We are given files:
βββ(miraiγΏkali)-[~/CTFs/Gemastik2024/FJB]
ββ$ tree .
.
βββ docker-compose.yml
βββ Dockerfile
βββ fjb.db
βββ frontend
β βββ components.json
β βββ eslint.config.js
β βββ index.html
β βββ jsconfig.json
β βββ package.json
β βββ pnpm-lock.yaml
β βββ postcss.config.js
β βββ public
β β βββ favicon.svg
β βββ README.md
β βββ src
β β βββ components
β β β βββ navigation.jsx
β β β βββ ui
β β β βββ badge.jsx
β β β βββ button.jsx
β β β βββ card.jsx
β β β βββ dialog.jsx
β β β βββ input.jsx
β β β βββ label.jsx
β β β βββ table.jsx
β β β βββ tabs.jsx
β β β βββ textarea.jsx
β β β βββ tooltip.jsx
β β βββ constants.js
β β βββ hooks
β β β βββ useAuth.js
β β βββ index.css
β β βββ lib
β β β βββ httpClient.js
β β β βββ router.js
β β β βββ utils.js
β β βββ main.jsx
β β βββ pages
β β β βββ cart-checkout.jsx
β β β βββ login-register.jsx
β β β βββ marketplace-lisiting.jsx
β β βββ routes
β β β βββ cart.jsx
β β β βββ index.lazy.jsx
β β β βββ login.lazy.jsx
β β β βββ __root.jsx
β β βββ routeTree.gen.ts
β βββ tailwind.config.js
β βββ vite.config.js
βββ httpd.conf
βββ httpd-foreground
βββ kauth
β βββ kauth-1.0-1.rockspec
β βββ kauth.c
β βββ kauth.h
β βββ Makefile
βββ src
βββ database.lua
βββ handler
β βββ api.lua
β βββ cart.lua
β βββ catalog.lua
β βββ checkout.lua
β βββ login.lua
β βββ register.lua
β βββ user.lua
βββ lib
β βββ utils.lua
βββ middleware.lua
βββ secret.lua
14 directories, 58 filesGoing into the website:

To do anything, we need to be authenticated first, we see that there is api.lua file, taking a look at it:
There are features like catalog, cart and checkout.
We can't register from the frontend since the button at the register page have no handler to hit to the /api/register endpoint so we need to hit the APIs directly.
We will use the below script as a base for our exploit.

For debugging purposes, i will modify the docker-compose.yml file to make fjb.db uses shared volume from local to the docker:
Interacting with the Website
We can login to the website and "Add Item" to it:

We can try to add an item:

There is a suspicious Valuable field that is using type password.
Locating the Flag
Looking around the files, it looks like there is no file or logic that is being used to generate the flag.


So we assume that the flag is in the database file. This assumption is basically confirmed based on yqroo's writeup (Great player btw) on this same challenge (pls don't call me out, not copying the writeup kok π₯Ί).
We see that when we create a catalog:

When we try to access api/catalog/me we can see the value field.

But when we access it with the public api /api/catalog:

We cannot see the value field. Meaning that the flag must be in the catalog of the admin user.
Vulnerability analysis
Looking around the files, we can see that this website is using an external C code to do it's authentication (which in on itself is very suspicious) in kauth/kauth.c file.

We see that this kauth.c file have 2 main functions, decode and encode:
Did you see the bug?
Let me highlight it.
YES. It is a buffer overflow bug that can overwrite adjacent variables. I would say, this code is so conveniently coded so that we can exploit it. Didn't believe me? Let's analyze it further.
Analyzing the code further
Proof #1
We see the definition of kauth_user struct in kauth/kauth.h:
We will try to see the layout of memory of this struct in a temporary file for easier debugging:

We see that the ID field is below the name field. With long enough name (in this case 128 characters), we can control the ID field by overwriting it.
Proof #2
The order of the variable assignment.
See that the program assigns the claim.id first, then claim.name and lastly the claim.exp . Since we control the name field. We can overwrite the id field without worrying that the id will be reassigned later.
Proof #3
You may think, "maybe in the register.lua or login.lua file, there is a limiter on how many characters can be send". Let's analyze register.lua and login.lua files.
Nope. there is no check on how long the input can be inputted.
Exploit
Now onto the exploit. First we need to register a user that is:
128 bytes long username
Then append a byte on the back of the username
Figuring out how to append a binary data to JSON.
Well i tried to naively do it like this:
We are greeted with an error:

We need another way to append a binary data to the username.
When googling about appending binary data to a lua string, we found a StackOverflow answer:

We can append binary data by using C escape sequences.
We modify our script like this:

Looks promising. Let us check in the db to cross-check the real id for our newly created user.

We successfully logged in as id 1 even though in the database, we are user id 3!
Now we can get the flag!

Final Exploit

Final words
It seems crazy to me that the exploit is this short. Since no one solved it during the competitions. I dunno maybe i am just having skill issues at the times. Sadge we didn't solve any challenge that day.
Until next time β€οΈ

Last updated