Skip to content

SECURE_CONNECTION//PRESS[CTRL+J]FOR ROOT ACCESS

BACK TO INTEL
MiscHard

Reservation Misc

CTF writeup for Reservation Misc from nullCTF

//Reservation - CTF Challenge Writeup

Challenge Name: Reservation  

Category: MISC  

Difficulty: Easy/Medium  

Flag: nullctf{why_1s_it_r3srv3d_f3eaf9630244ed5f}

>Challenge Description

I wanted to take my inexistent girlfriend to this fancy restaurant called Windows, but they keep asking me for a key PROMPT. I don't know what to do, can you help me?

We're given a Python file reservation.py that runs a socket server.

>Initial Analysis

Let's examine the provided reservation.py file:

python

import os

import socket

from dotenv import load_dotenv

  

load_dotenv()

  

FLAG = os.getenv("FLAG", "nullctf{aergnoujiwaegnjwkoiqergwnjiokeprgwqenjoig}")

PROMPT = os.getenv("PROMPT", "bananananannaanan")

PORT = int(os.getenv("PORT", 3001))

  

# This is missing from the .env file, but it still printed something, interesting

print(os.getenv("WINDIR"))

  

def normal_function_name_1284932tgaegrasbndefgjq4trwqerg(client_socket):

    client_socket.sendall(

b"""[windows_10 | cmd.exe] Welcome good sire to our fine establishment.

Unfortunately, due to increased demand,

we have had to privatize our services.

Please enter the secret passphrase received from the environment to continue.\n""")

    response = client_socket.recv(1024).decode().strip()

  

    if response == PROMPT:

        client_socket.sendall(b"Thank you for your patience. Here is your flag: " + FLAG.encode())

    else:

        client_socket.sendall(b"...I am afraid that is not correct. Please leave our establishment.")

  

    client_socket.close()

  

def start_server(host='0.0.0.0', port=PORT):

    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    server_socket.bind((host, port))

    server_socket.listen(1024)

    print(f"[*] Listening on {host}:{port}")

  

    while True:

        client_socket, addr = server_socket.accept()

        print(f"[*] Accepted connection from {addr}")

        normal_function_name_1284932tgaegrasbndefgjq4trwqerg(client_socket)

  

if __name__ == "__main__":

    start_server()

Key Observations

  1. The server requires a PROMPT value - It loads PROMPT from environment variables with a default fallback

  2. Important comment - "This is missing from the .env file, but it still printed something, interesting"

  3. Windows hints everywhere:

   - The code prints os.getenv("WINDIR") on startup

   - The banner says [windows_10 | cmd.exe]

   - The restaurant is called "Windows"

  1. The vulnerability - The server reads from actual system environment variables, not just a .env file

>The Eureka Moment 💡

The key insight is understanding what PROMPT means in a Windows context:

On Windows systems, there's an environment variable called PROMPT that defines how the command prompt looks in CMD.exe. The default value is:

$P$G

Where:

  • $P = Current drive and path (e.g., C:\Users\Stefan)

  • $G = Greater-than sign >

This displays as the familiar C:\> prompt in Windows CMD.

Since the remote server is running on Windows (as evidenced by WINDIR and the cmd.exe banner), it will read the system's PROMPT environment variable, which defaults to $P$G!

>Solution Approach

Step 1: Local Testing Setup

First, I created a test environment to verify my theory locally using WSL.

File: run_server.sh

bash

#!/bin/bash

export PROMPT='$P$G'

python3 reservation.py

This script sets the PROMPT environment variable and starts the server.

Step 2: Simple Connection Test

I created a simple test script to verify the connection works:

File: simple_test.py

python

#!/usr/bin/env python3

import socket

  

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

sock.connect(('localhost', 3001))

  

# Receive welcome

data = sock.recv(4096).decode()

print(data)

  

# Send PROMPT value

prompt = "$P$G"

print(f"Sending: {repr(prompt)}")

sock.sendall(prompt.encode() + b'\n')

  

# Get response

response = sock.recv(4096).decode()

print(response)

  

sock.close()

Step 3: Local Testing

I started the local server:

bash

chmod +x run_server.sh

./run_server.sh

Then tested with the simple script:

bash

python3 simple_test.py

Output:

[windows_10 | cmd.exe] Welcome good sire to our fine establishment. Unfortunately, due to increased demand, we have had to privatize our services. Please enter the secret passphrase received from the environment to continue. Sending: '$P$G' Thank you for your patience. Here is your flag: nullctf{aergnoujiwaegnjwkoiqergwnjiokeprgwqenjoig}

Success! The local test confirmed that $P$G is the correct PROMPT value.

Step 4: Remote Exploitation

Now that I verified the solution locally, I created a polished exploit script for the remote server:

File: exploit_remote.py

python

#!/usr/bin/env python3

import socket

import sys

  

def exploit(host, port):

    """Exploit the remote server to get the flag"""

    print(f"[*] Connecting to {host}:{port}")

    try:

        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        sock.connect((host, port))

        # Receive welcome message

        data = sock.recv(4096).decode()

        print("[*] Received from server:")

        print(data)

        # The PROMPT environment variable on Windows CMD defaults to $P$G

        # This is what the server is expecting

        prompt = "$P$G"

        print(f"\n[*] Sending PROMPT value: {repr(prompt)}")

        sock.sendall(prompt.encode() + b'\n')

        # Receive flag

        response = sock.recv(4096).decode()

        print("\n[*] Server response:")

        print(response)

        # Extract and highlight the flag

        if "flag" in response.lower():

            import re

            flag_match = re.search(r'nullctf\{[^}]+\}', response)

            if flag_match:

                print(f"\n[+] FLAG FOUND: {flag_match.group(0)}")

        sock.close()

    except Exception as e:

        print(f"[-] Error: {e}")

        sys.exit(1)

  

if __name__ == "__main__":

    if len(sys.argv) != 3:

        print("Usage: python3 exploit_remote.py <host> <port>")

        print("\nExample: python3 exploit_remote.py 127.0.0.1 3001")

        sys.exit(1)

    host = sys.argv[1]

    port = int(sys.argv[2])

    exploit(host, port)

Step 5: Getting the Flag

Running the exploit against the remote server:

bash

python3 exploit_remote.py 34.118.61.99 10057

Output:

[*] Connecting to 34.118.61.99:10057 [*] Received from server: [windows_10 | cmd.exe] Welcome good sire to our fine establishment. Unfortunately, due to increased demand, we have had to privatize our services. Please enter the secret passphrase received from the environment to continue. [*] Sending PROMPT value: '$P$G' [*] Server response: Thank you for your patience. Here is your flag: nullctf{why_1s_it_r3srv3d_f3eaf9630244ed5f} [+] FLAG FOUND: nullctf{why_1s_it_r3srv3d_f3eaf9630244ed5f}

🎉 FLAG CAPTURED: nullctf{why_1s_it_r3srv3d_f3eaf9630244ed5f}

>Additional Helper Scripts

During the solving process, I also created these helper scripts:

File: check_env.py

python

import os

print("PROMPT:", repr(os.getenv("PROMPT")))

print("WINDIR:", repr(os.getenv("WINDIR")))

This script helps verify environment variables are set correctly.

File: test_connection.py

python

#!/usr/bin/env python3

import socket

  

def test_prompt(host, port, prompt_value):

    """Test a specific prompt value"""

    try:

        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        sock.connect((host, port))

        # Receive welcome message

        data = sock.recv(4096).decode()

        print("[*] Received:")

        print(data)

        # Send the prompt

        print(f"[*] Trying PROMPT: {repr(prompt_value)}")

        sock.sendall(prompt_value.encode() + b'\n')

        # Receive response

        response = sock.recv(4096).decode()

        print("[*] Response:")

        print(response)

        sock.close()

        if "flag" in response.lower():

            print(f"\n[+] SUCCESS! The PROMPT was: {repr(prompt_value)}")

            return True

        return False

    except Exception as e:

        print(f"[-] Error: {e}")

        return False

  

if __name__ == "__main__":

    # Test locally first

    print("[*] Testing common Windows PROMPT values locally...")

    # Common Windows CMD PROMPT values

    prompts_to_try = [

        "$P$G",           # Default: C:\>

        "$p$g",           # Lowercase version

        "$P$G ",          # With space

        "$P$G$_",         # With newline

        "$P$G$S",         # With space

    ]

    host = "localhost"

    port = 3001

    for prompt in prompts_to_try:

        if test_prompt(host, port, prompt):

            break

        print()

This script was useful for testing multiple PROMPT variations during the research phase.

>Key Takeaways

  1. Read the hints carefully - The comment about WINDIR "printing something" was crucial

  2. Context matters - The Windows/CMD.exe references weren't just flavor text

  3. Environment variables are powerful - Understanding OS-specific environment variables can be key to solving challenges

  4. Test locally first - Setting up a local test environment helped verify the solution before trying remote

  5. Windows PROMPT variable - Learning about $P$G and other Windows CMD prompt formatting codes was essential

>Windows PROMPT Format Codes Reference

For those curious, here are some common Windows CMD PROMPT format codes:

  • $A - & (Ampersand)

  • $B - | (pipe)

  • $C - ( (Left parenthesis)

  • $D - Current date

  • $E - Escape code (ASCII code 27)

  • $F - ) (Right parenthesis)

  • $G - > (greater-than sign)

  • $H - Backspace (erases previous character)

  • $L - < (less-than sign)

  • $N - Current drive

  • $P - Current drive and path

  • $Q - = (equal sign)

  • $S - (space)

  • $T - Current time

  • $V - Windows version number

  • $_ - Carriage return and linefeed

  • $$ - $ (dollar sign)

>Conclusion

This challenge was a clever play on Windows environment variables and required understanding how the Windows command prompt works. The key was recognizing that the PROMPT environment variable in Windows CMD.exe defaults to $P$G, which the server was reading from the system environment.

The challenge name "Reservation" and the restaurant theme were perfect metaphors - we needed the right "reservation" (PROMPT value) to get into the fancy "Windows" restaurant!

Final Flag: nullctf{why_1s_it_r3srv3d_f3eaf9630244ed5f}