Contents

🌐 Exceeding Knight

A detailed write-up of the Web challenge 'Exceeding Knight' from KnightCTF - 2025

Challenge Description

/images/KnightCTF-2025/Exceeding-Knight/challenge_presentation.png
Challenge Presentation

Initial Analysis

The site appeared as follows:

/images/KnightCTF-2025/Exceeding-Knight/site_presentation.png
Site Presentation

There was nothing interesting here, so I began reading the attached files. The first thing I did was read the web.php file located in the routes folder. I found the following routes:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
Route::get('/calculator', [CalculatorController::class, 'index']);
Route::post('/calculator', [CalculatorController::class, 'calculate']); // Handle form submission

Route::get('/convert', [UnitConversionController::class, 'index']);
Route::post('/convert', [UnitConversionController::class, 'convert']);

Route::get('/character-count', [StringManipulationController::class, 'characterCountIndex']);
Route::post('/character-count', [StringManipulationController::class, 'characterCount']);

Route::get('/reverse-string', [StringManipulationController::class, 'reverseStringIndex']);
Route::post('/reverse-string', [StringManipulationController::class, 'reverseString']);

Route::post('/profile', [ProfileController::class, 'index']);
Route::get('/profile/error', [ProfileController::class, 'triggerError']); // Error-triggering route

Route::get('/', function () {
    return view('welcome');

Next, I read the .env file and found something interesting:

 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
APP_NAME=Laravel
APP_ENV=local
APP_KEY=base64:KnrD53eO60BJBvCVGNlBuOqktUCAsTuod34OelLJjPQ=
APP_DEBUG=true
APP_URL=http://localhost
MAX_CALC_LIMIT=100000000000000000


LOG_CHANNEL=stack
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=

BROADCAST_DRIVER=log
CACHE_DRIVER=file
FILESYSTEM_DISK=local
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120
FLAG=KCTF{i_am_not_flag}

Aside from the APP_KEY and FLAG, as we can see, Laravel’s debug mode is enabled. When debug mode is enabled in Laravel, any error that occurs will trigger a detailed error page. This page includes:

  • Error Message: A clear description of the error.
  • Stack Trace: A full trace of the error, showing the file paths and lines of code where the issue occurred.
  • Environment Details: Information about the environment, including variables, configurations, and request headers.
  • Sensitive Data Exposure: Potential exposure of .env values, database credentials, API keys, and other sensitive information.

So, I thought about exploiting the enabled debug mode in Laravel to capture the flag. The only thing I needed was a way to trigger any kind of error. I found this method in the /calculator route, to be more precise, in the CalculatorController.php file under the Http/Controllers folder. As we can see, by entering a number greater than MAX_CALC_LIMIT=100000000000000000 an exception is thrown:

 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
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class CalculatorController extends Controller
{
    public function index()
    {
        return view('calculator'); 
    }

    public function calculate(Request $request)
    {
        $request->validate([
            'num1' => 'required|numeric',
            'num2' => 'required|numeric',
            'operation' => 'required|in:add,sub,mul,div',
        ]);

        $num1 = $request->input('num1');
        $num2 = $request->input('num2');
        $operation = $request->input('operation');
        $limit = env('MAX_CALC_LIMIT', 100000);

        if ($num1 > $limit || $num2 > $limit) {
            throw new \Exception("You have hit the calculation limit set in the .env file.");
        }

        $result = match ($operation) {
            'add' => $num1 + $num2,
            'sub' => $num1 - $num2,
            'mul' => $num1 * $num2,
            'div' => $num2 != 0 ? $num1 / $num2 : throw new \Exception("Division by zero is not allowed."),
        };

        return view('calculator', ['result' => $result]);
    }
}

Exploit

So, all I had to do was enter 1000000000000000000 (just adding a simple zero) in the num1 parameter to trigger the exception. This caused the detailed error page to return, which contained the flag inside it:

/images/KnightCTF-2025/Exceeding-Knight/manual_flag.png
Manual Flag

Flag

Flag