Apoorv CTF 2025 Write ups - SEO CEO, Blog-1, Tan-je-ro (WEB)
SEO CEO (289 Solves)
Title: SEO CEO
Description: They’re optimizing SEO to show this garbage?!
This was a black box challenge. At first, I tried to check /robots.txt
, but it had a fake flag.
Based on the title and description of this challenge, I checked /sitemap.xml
. It contained XML code, and the main part is below.
1 | <url> |
I accessed /goofyahhroute
, and there was a simple black sentence on a white background.
1 | ok bro u da seo master gng frfr ngl no cap |
So, I checked the source code and found one sentence that looked like a hint.
1 | tell it to the url then blud |
I ended up getting the flag by accessing the URL below.
1 | /goofyahhroute?flag=yes |
Blog-1 (60 Solves)
Title: Blog-1
Description: In the digital realm, Blog-1 awaited brave developers. The mission? Craft a captivating blog with enchanting posts, lively comments, and secure user authentication. Create a functional and visually stunning masterpiece. Ready for the Blog-1 adventure?
This was also a black box challenge.
There were several functions interacting with the server:
- Register/login
- Create a new blog post: title, description
- Check blog rewards
To get the flag, there were two interesting points:
- You can create one blog post per day.
- If you write five posts, you will get a flag according to the blog rewards. After creating the first post and checking the blog rewards, it says that if you write four more posts, you can get a gift.
The first thing that came to my mind was to successfully create five posts almost at the same time. So, I used threading
in Python because if you use requests
and send five requests in a for loop, the second response will wait until the first response arrives.
I used an AWS server from India to reduce response time. When I checked the ping of this challenge, it was located in India.
1 | import requests |
I ran this code on the AWS server from India and ended up getting a reward! But it wasn’t the flag. To figure it out, I checked the sitemap in Burp Suite. /api/v2/gift
and /api/v1/blog/addBlog
caught my attention. So, I tried /api/v1/gift
, and then I got the flag.
Tan-je-ro (33 Solves)
Title: Tan-je-ro
Description: Bruh, Tanjiro messed up BIG TIME. 😭 He hid Goku’s summoning scroll somewhere on this cursed website, and now it’s all broken. 💀 If we don’t find it fast, Goku’s never showing up, and we’re all doomed. No cap, this might be the hardest quest yet. Think you got what it takes? 👀🔥 Can you wield your skills like Tanjiro’s blade and break through the encrypted defenses?
Hint: Dont remove the headers from the public key :)
This was a black box challenge, and I couldn’t get anything when I first tried to solve it. But it turned out that a hint came, so I was able to solve it using that hint.
After finding some endpoints, I found /login
, /Admin
, and /public
:
/login
: You can get a token to explore./Admin
: You need a token to continue./public
: You can get a public key.
To contine solving, I had to access to /Admin
with token that I could get from /login
. This shape was like below. It’s a typcial JWT token.
1 | eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhZG1pbiI6ZmFsc2UsIm5hbWUiOiJHdWVzdCIsImlhdCI6MTc0MDkyODQxM30.ZMeqC1m7Zf3UNICbBHnhqS82HK2h646HE9P_QE8pa3ZC4KVzl3og5O5RdkcFg_MkwgPpadKBmYkyQl_gGJvXkYFqA2Cfqc7IerbPWlFOVOit9I_cznLhDt497Ggge4TkRKRXVHPSITog5j3k-ULnbPQZqagqsz5XOwOPLu_T34dFGyf-lCnwryuCVE49Fh-LtgWtxxiZ2tUPa8r5Sk3dHOQHWT4RSxnwzmnYmsJGrjY7EKdwqLY55akxPBlutzo3dkSZWYQk_tZQyqJDqTAXN0gjKo3sxEQpKlCUts3XY4mGLafxnZSmoqa2qYsHhjN82dIKlQnAXk9MH6RCLz-0MA |
I decoded the header and payload.
1 | { |
At first, I tried to change token['admin']
from False to True and change token['name']
to /Admin
, but it didn’t work.
Based on the hint, I had to use the public key to solve this problem, and it was suggested not to remove the public key. So, I changed the algorithm when encoding the JWT token. However, when using the HS256
algorithm, I couldn’t use the public key as the key. I could only use plain text as the key. So, I had to modify the source code in pyjwt
.
Below was the traceback when I tried to encode the JWT token with the HS256
algorithm using the public key.
1 | Traceback (most recent call last): |
According to the traceback, I had to bypass prepare_key
in order to encode with the public key. So, I commented it out.
1 | # /jwt/algorithms.py |
And it worked! I finally got the flag! Below is the final exploit code.
1 | import jwt |