🌐 Knight Connect
A detailed write-up of the Web challenge 'Knight Connect' from KnightCTF - 2025
📊 Challenge Overview
Category Details Additional Info 🏆 Event KnightCTF - 2025 Event Link 🔰 Category Web 🌐 💎 Points 260 Out of 500 total ⭐ Difficulty 🟢 Easy Personal Rating: 3/10 👤 Author NomanProdhan Profile 🎮 Solves (At the time of flag submission) 49 XX% solve rate 📅 Date 20-01-2025 KnightCTF - 2025 Day X 🦾 Solved By Bebo07 Team: QnQSec
📝 Challenge Information
In a realm where ancient knights and modern technology collide, a mysterious portal emerges—known as “Knight Connect.” Only the wisest and most cunning warriors can decipher its secrets. Legends whisper of a forgotten system, guarded by layers of encryption and vulnerabilities, waiting for a brave soul to breach its defenses. Do you possess the skills to uncover the truth? Enter the domain of Knight Connect and etch your name into the annals of digital knighthood. The challenge awaits.
🎯 Challenge Files & Infrastructure
Provided Files
Files:
🔍 Initial Analysis
First Steps
The site initially appeared as follows:
with a login screen. After completing the registration and login, I was redirected to the following page:
I couldn’t find anything else on the site, so I started reading the attached files. At first, I was overwhelmed and didn’t know where to look due to the number of files present. The first thing that came to mind was to forge some session cookies since the
APP_KEY
of Laravel was in the.env
file. Also, because it required the session to be set tois_admin
in order to display the flag. We can see this from the following lines of code in theindex.blade.php
file under theresources/views/users
folder:
1 2 3
@if (isset($flag) && session()->has('is_admin') && session('is_admin')) <div class="flag">Flag: {{ $flag->flag }}</div> @endif
but then I discovered that it wasn’t the right path. However, I realized that I needed to get an administrator account to be able to read the flag. In the
web.php
file under theresources/routes
folder, I found all the routes of the site, including one that seemed a bit suspicious:/contact
. Visiting it redirected me to the following page:where the administrator accounts and their respective emails were displayed. Spoiler: only one of these was valid, which was
nomanprodhan@knightconnect.com
(the username of the challenge creator). I then continued looking at other files, but I was interested in how authentication was being handled, so I searched for the authentication file, which was namedAuthController.php
under theHttp/Controllers
folder. Here I found the vulnerability—there were two functions that allowed you to request a login link for an account, which created a token formed by combining the email and a timestamp at that moment, all encrypted using the bcrypt function. The other function allowed you to log in using that generated link by passing the token as a parameter:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
public function requestLoginUrl(Request $request) { $request->validate([ 'email' => 'required|email', ]); $user = User::where('email', $request->email)->first(); if (!$user) { return back()->withErrors(['email' => 'Email not found']); } $time = time(); $data = $user->email . '|' . $time; $token = bcrypt($data); $loginUrl = url('/login-link?token=' . urlencode($token) . '&time=' . $time . '&email=' . urlencode($user->email)); return back()->with('success', 'Login link generated, but email sending is disabled.'); } public function loginUsingLink(Request $request) { $token = $request->query('token'); $time = $request->query('time'); $email = $request->query('email'); if (!$token || !$time || !$email) { return response('Invalid token or missing parameters', 400); } if (time() - $time > 3600) { return response('Token expired', 401); } $data = $email . '|' . $time; if (!Hash::check($data, $token)) { return response('Token validation failed', 401); } $user = User::where('email', $email)->first(); if (!$user) { return response('User not found', 404); } session(['user_id' => $user->id]); session(['is_admin' => $user->is_admin]); return redirect()->route('users'); }
the first function doesn’t really have any vulnerabilities, since it only shows how the token is created to request the “instant” login URL. In contrast, the second function has a significant vulnerability, as the only check it does is ensure the timestamp of the generated token is at most one hour old (3600 seconds), otherwise, it becomes invalid. However, we can manipulate the timestamp ourselves by passing a fake value as a parameter. In fact, to make it secure, the generated token with the timestamp should have been saved in the database, and if it wasn’t the exact timestamp, it wouldn’t allow access (although a brute-force attack could be used to try all possible timestamps). So, I realized that it’s possible to forge a token—one just needs to know the email of the account they want to access, and as we saw earlier in the
/contact
route, there were quite a few admin emails… Now that we’ve figured it all out, let’s proceed with the exploit.
🔬 Vulnerability Analysis
Potential Vulnerabilities
- Insecure Authentication
🎯 Solution Path
Exploitation Steps
Initial setup
Initially, to generate the URL, I used https://onlinephp.io/. I also found this website useful for generating “passwords” with Laravel’s bcrypt (https://fbutube.com/laravel-password-generator). However, in the end, I decided to write it in PHP and run it locally, as this way I could fully automate the process.
Exploitation
After obtaining the admin’s email
nomanprodhan@knightconnect.com
, it was quite simple to forge a token, since it was made up of “email|timestamp”. I then wrote a PHP script that did exactly what the first function did, using bcrypt on the string formed by the admin’s email + timestamp, and then generating a link similar to the one in the function with the parameterstoken
,time
, andis_admin
flag on the account, I was able to retrieve the flag.
Flag capture
🛠️ Exploitation Process
Approach
I wrote the exploit in PHP because I had issues with token composition using bcrypt in Python. This exploit takes the admin’s email, which has the flag in their profile, and then creates a valid token with a timestamp less than one hour old. It then generates a URL with a valid token to access the admin profile, and through a cURL function in PHP, it makes a request to the page, extracting the flag via a regex. I used the following commands for the requirements and the run:
1 2 3
sudo apt install php sudo apt-get install php-curl php exploit.php
🚩 Flag Capture
Flag
Proof of Execution
🔧 Tools Used
Primary Tools
Tool Purpose PHP Exploit
💡 Key Learnings
Skills Improved
- Binary Exploitation
- Reverse Engineering
- Web Exploitation
- Cryptography
- Forensics
- OSINT
- Miscellaneous
📚 References & Resources
Learning Resources
📊 Final Statistics
Metric | Value | Notes |
---|---|---|
Time to Solve | 00:30 | From start to flag |
Global Ranking (At the time of flag submission) | 10/451 | Challenge ranking |
Points Earned | 260 | Team contribution |
Created: 20-01-2025 • Last Modified: 20-01-2025 Author: mH4ck3r0n3 • Team: QnQSec