++game is a web challenge that was part of the 2022 Jade CTF. In order to get the flag, we had to beat an impossible game.


After registering, the game greets us with our current score and a button to increase it. Each time we click the button, the score is increased by 1. To protect itself from automated requests, a valid reCAPTCHA token is required to increase the score.

The game interface

The backend

As part of the challenge, we were given the source code of the backend. The most interesting part is in /api/scr/update_score.php:

    include "/var/www/db/secret.php";
    if(isset($_GET["username"]) && isset($_GET["next_level"]) && isset($_GET["signature"])){

            file_put_contents('/var/www/db/database.bin', serialize($database));

The backend uses a simple signature scheme to verify that the request is valid. The signature is computed by concatenating the username, the next level and the secret and then hashing it with SHA1. The secret is stored in /var/www/db/secret.php and is not available to us.

The frontend

The frontend is responsible for signing our request and requesting the backend to increase our score:

        $recaptcha = $_POST['g-recaptcha-response'];
        $secret_key = '<<REDACTED>>';
        $url = 'https://www.google.com/recaptcha/api/siteverify?secret='.$secret_key.'&response='.$recaptcha;
        $response = file_get_contents($url);
        $response = json_decode($response);
        if ($response->success===false) {
            die('Captcha failed!');
        $head=sprintf("API: %s",$var);

Instead of making a request to the backend directly, the frontend redirects our browser to the backend. This means that we’re able to both inspect and modify any request that is sent to the backend.


If we were able to deduce the secret, we could compute valid signatures for any username and next level. However, the secret is not available to us. We might be tempted to try to brute force the secret from a given username, score and signature.

There is however a much easier way to win the game. Since the signature scheme involves directly concatenating the username and the next level, the same signature will be computed for schlingel with score 10001 and schlingel1000 with score 1.

To obtain the winning signature, we first register the user schlingel922337203685477580 and capture the signed request to the backend:


We then register the innocent user schlingel and reuse the signature from the previous request:

After that, we need to manually solve two reCAPTCHA challenges to increase our score to 9223372036854775807 and obtain the flag.

The game, showing us the flag