Sitemap

Space Explorer — Hack The Box Web Challenge Write up

10 min readNov 4, 2026

--

Platform: Hack The Box (HTB)

Challenge: Space Explorer

Category: Web

Difficulty: Very Easy

Author: J. Aazaf Ritha (ARVictor)

Introduction

Space Explorer is a very easy web challenge from Hack The Box. The challenge is about a space mission control system that has a security issue between two backend services.

The application uses Go and Python to handle user requests. The Go service checks whether the requested action is allowed, while the Python service processes the request and returns the result.

Our objective is to bypass the restriction and access the secure database to retrieve the flag.

In this challenge, I started by analyzing the source code to understand how the application works. After that, I used Burp Suite to test the HTTP requests and identify the security issue.

The main vulnerability was caused by how Go and Python interpret JSON keys differently.

Challenge Description:

A lost space mission control system suffers from flawed authentication logic between its Sender and Receiver services.

Press enter or click to view image in full size
Hack The Box Space Explorer challenge page

1. Source Code Analysis

I started by downloading the challenge files from Hack The Box and extracting them in my Kali Linux environment.

First, I extracted the ZIP file using the following command:

unzip a2423486-2962-408a-bae8-fe432db1606b-1784052327.zip -d ~/CTF/HTB/Space-Explorer/files

The unzip command extracts the files from the ZIP archive, while -d specifies the destination directory.

After extracting the files, I moved into the challenge directory and checked the available files.

cd ~/CTF/HTB/Space-Explorer/files/space_explorer
ls

The extracted files included:

space_explorer/
├── build-docker.sh
├── Dockerfile
├── entrypoint.sh
├── go-app/
│ ├── main.go
│ ├── go.mod
│ └── go.sum
└── python-service/
└── app.py

From this structure, I identified two important application files:

  • main.go — The Go service that handles incoming requests and validates actions.
  • app.py — The Python service that processes the requests and returns the response.
Press enter or click to view image in full size
Extracted challenge files in Kali Linux

Analyzing the Go Application

I started by checking the Go source code using:

cat go-app/main.go

The cat command displays the content of a file directly in the terminal.

The Go application contained the frontend HTML code and the backend logic for processing HTTP requests.

While checking the code, I found that the application supports two actions:

  • getcosmic — Retrieves a random cosmic anomaly.
  • getSecureCode — Attempts to access the secure database.

I then focused on the executeHandler() function because it handles requests sent to the /execute endpoint.

The application first reads the incoming request body.

body, err := io.ReadAll(r.Body)

After reading the request, it uses json.Unmarshal() to convert the JSON data into a Go structure.

var requestData RequestData
if err := json.Unmarshal(body, &requestData); err != nil {
http.Error(w, "Invalid JSON", http.StatusBadRequest)
return
}

The application also defines the following structure:

type RequestData struct {
Action string `json:"action"`
}

This means the application expects a JSON field named action.

After converting the JSON data, the Go service checks which action was requested.

switch requestData.Action {
case "getcosmic":
// Forward request to Python
case "getSecureCode":
w.Write([]byte("Access denied: Invalid security clearance"))
default:
http.Error(w, "Invalid command", http.StatusBadRequest)
}

From this code, I understood that getcosmic is allowed, but getSecureCode is blocked by the Go service.

I also noticed another important part of the code.

resp, err := http.Post(
"http://localhost:8081/execute",
"application/json",
bytes.NewBuffer(body),
)

Here, the Go application forwards the original JSON request body to the Python service running on port 8081.

This was interesting because Go validates the action using the parsed JSON value, but forwards the original request body instead of creating a new request from the validated data.

At this point, I decided to check how the Python service handles the same request.

Press enter or click to view image in full size
Go source code showing the JSON validation and request forwarding

Analyzing the Python Application

Next, I checked the Python source code using:

cat python-service/app.py

The Python service was developed using Flask, a Python web framework.

It contained an endpoint called /execute that accepts POST requests.

@app.route('/execute', methods=['POST'])
def execute():

The service reads JSON data using:

data = request.get_json()

After that, it checks whether the JSON request contains the action key.

if 'action' not in data:
return jsonify({"error": "No command received"}), 400

If the action is getcosmic, Python selects a random cosmic anomaly and returns its name and image URL.

if data['action'] == "getcosmic":
anomaly = random.choice(COSMIC_ANOMALIES)
return jsonify(anomaly)

However, I found another condition that handles the restricted action.

elif data['action'] == "getSecureCode":
return jsonify({
"flag": os.getenv("FLAG", "HTB{flag_not_set}"),
"name": "Captain's Log",
"src": "..."
})

Here, Python returns the flag from the FLAG environment variable when the action is getSecureCode.

The value HTB{flag_not_set} is only a fallback value used when the environment variable is missing.

From both source files, I understood that Go blocks the restricted action, but Python can process that action if the request reaches it.

The next step was to understand whether I could make the two services process the same request differently.

Press enter or click to view image in full size
Python source code showing the action checks and restricted functionality

2. Web Application Enumeration

After analyzing the source code, I started the challenge instance on Hack The Box and opened the provided IP address in my browser.

The application was named Cosmic Explorer and contained two options:

  • Scan Cosmic Anomaly
  • Access Secure Database
Press enter or click to view image in full size
Cosmic Explorer web interface

I first selected Scan Cosmic Anomaly and clicked the INITIATE SCAN button.

The application successfully returned a cosmic anomaly with its name and image.

This confirmed that the normal functionality was working.

Press enter or click to view image in full size
Successful cosmic anomaly scan

Next, I selected Access Secure Database and clicked the same button.

This time, the application displayed the following error:

Access denied: Invalid security clearance
Press enter or click to view image in full size
Access denied when trying to access the secure database

This confirmed that the restricted functionality was blocked when accessed through the normal web interface.

Since the application uses JSON requests, I decided to inspect the HTTP traffic using Burp Suite.

3. HTTP Request Analysis Using Burp Suite

I opened Burp Suite Community Edition in Kali Linux and used Burp’s browser to access the application.

After performing both actions, I checked the requests under:

Proxy → HTTP history

I found that the application sends POST requests to the /execute endpoint.

Press enter or click to view image in full size
Burp Suite HTTP history showing the /execute requests

I then sent the requests to Burp Repeater to modify them manually and compare the server responses.

Testing the Normal Request

The normal request contained the following JSON data:

{
"action": "getcosmic"
}

When I sent this request using Burp Repeater, the server returned HTTP 200 OK with a cosmic anomaly name and an image URL.

In my test, the application returned a cosmic anomaly named Quantum Singularity.

Get Aazaf Ritha’s stories in your inbox

Join Medium for free to get updates from this writer.

This confirmed that the Go service accepted the action and forwarded the request to Python.

Press enter or click to view image in full size
Normal request and response in Burp Repeater

Testing the Restricted Request

Next, I changed the JSON value to getSecureCode.

{
"action": "getSecureCode"
}

The server returned:

Access denied: Invalid security clearance

Interestingly, the HTTP status was still 200 OK, even though the application denied access.

After checking the source code, I understood that Go was writing an access-denied message without setting a different HTTP status.

This confirmed that the Go service was blocking the restricted action.

Press enter or click to view image in full size
Restricted request returning Access denied in Burp Repeater

4. Testing JSON Case Sensitivity

While analyzing the source code, I noticed an important difference between Go and Python.

The Go application uses json.Unmarshal() to read JSON data into a structure. This parser can match JSON keys to struct fields without considering letter case.

However, Python dictionaries are case-sensitive.

For example, Python treats action and Action as two different keys.

I decided to test this behavior manually using Burp Repeater.

First, I changed the JSON key from lowercase action to uppercase Action.

{
"Action": "getcosmic"
}

I kept the value getcosmic unchanged.

After sending the request, I received the following response:

{
"error": "No command received"
}
Press enter or click to view image in full size
Uppercase Action test returning No command received

This result was interesting because the request was accepted by Go but failed when Python processed it.

The reason was simple.

Go accepted Action as a match for the JSON field action. Since the value was getcosmic, the Go validation passed, and the original request was forwarded to Python.

However, Python was checking for the exact lowercase key action.

Because the request contained only uppercase Action, Python could not find the required key and returned the error.

This confirmed that both services were interpreting the same JSON request differently.

Finding: The Go and Python services do not handle JSON key names in exactly the same way.

5. Testing Multiple JSON Keys

After confirming the case-sensitivity difference, I wanted to understand what happens when both action and Action are included in the same JSON request.

I started with the following payload:

{
"action": "getcosmic",
"Action": "invalid"
}

Here, I used two similar JSON keys with different values.

After sending the request, the server returned:

HTTP/1.1 400 Bad Request
Invalid command
Press enter or click to view image in full size
Two JSON keys returning Invalid command

This happened because Go treated both keys as matching the same struct field.

First, Go read action with the value getcosmic. Then it read Action with the value invalid.

Because both keys matched the same field, the second value replaced the first one.

The final value became invalid, which was not an allowed action.

As a result, the Go service rejected the request before forwarding it to Python.

Reversing the JSON Key Order

Next, I wanted to check whether changing the order of the JSON keys would affect the result.

I reversed the previous payload:

{
"Action": "invalid",
"action": "getcosmic"
}

This time, the server returned HTTP 200 OK with a normal cosmic anomaly.

In my test, the application returned Pulsar Emission.

Press enter or click to view image in full size
Reversed JSON key order returning a successful cosmic anomaly response

The reason was that Go processed both matching keys in order.

Since getcosmic was the last matching value, the Go validation passed.

Python also found the exact lowercase key action containing getcosmic, so it returned the normal cosmic anomaly.

From these two tests, I understood that the order of JSON keys is important in this application.

Go treats action and Action as matching the same field and keeps the last value. But Python treats them as two separate keys.

This difference gave me an idea for bypassing the restriction.

6. Exploiting the Vulnerability

After testing the JSON key names and their order, I had enough information to construct the final payload.

My goal was to make Go accept the normal action while Python processed the restricted action.

I used the following JSON payload in Burp Repeater:

{
"action": "getSecureCode",
"Action": "getcosmic"
}

After sending the request, the server returned HTTP 200 OK with the restricted database response, including the flag.

Press enter or click to view image in full size
Successful authorization bypass in Burp Repeater, with the flag hidden

The payload worked because the two services interpreted the JSON differently.

Go Sender:

Go first processed action with the value getSecureCode.

Then it processed Action with the value getcosmic.

Because Go treated both keys as matching the same field, the last value replaced the first one.

The final value was getcosmic, which was allowed by the Go service.

After passing validation, Go forwarded the original JSON body to Python.

Python Receiver:

Python received the same JSON request but treated action and Action as separate keys.

The Python code checked the lowercase action key, which contained getSecureCode.

As a result, Python executed the restricted functionality and returned the flag.

Flag Captured

HTB{REDACTED}

I successfully retrieved the challenge flag through Burp Suite.

7. Understanding the Vulnerability

The main issue in this challenge is how Go and Python handle JSON keys differently.

Go validates the action using its parsed value, but it forwards the original JSON request to Python.

Python reads the same request differently because its dictionary keys are case-sensitive.

By using both action and Action in one request, I was able to make Go accept the normal action while Python processed the restricted action.

This allowed me to bypass the authorization check and access the secure database.

This vulnerability is called a JSON Parser Differential, and it leads to an Authorization Bypass.

In a real-world application, this kind of issue could allow an attacker to access restricted functions or sensitive information.

Tools Used

  • Kali Linux — Testing environment and source code analysis.
  • Firefox — Accessing and testing the website.
  • Burp Suite — Intercepting, modifying, and testing HTTP requests.
  • Go & Python — Understanding the backend logic and vulnerability.

Key Takeaways

This challenge helped me understand a few important web security concepts.

  • Source Code Analysis: Reading the source code helped me understand the application before testing it.
  • HTTP Request Testing: Burp Suite made it easier to inspect, modify, and resend requests.
  • JSON Case Sensitivity: Different programming languages can handle JSON keys differently.
  • JSON Key Order: The order of matching keys can affect how an application processes a request.
  • Authorization Bypass: Weak validation between backend services can allow restricted functionality to be accessed.
  • Manual Testing: Testing normal requests, failed requests, and modified payloads helped me understand the vulnerability instead of directly using the final exploit.

Final Thoughts

Space Explorer was an interesting web challenge from Hack The Box. Even though it was rated Very Easy, I learned something new from this challenge.

I started by checking the source code and understanding how the Go and Python services communicate. After that, I used Burp Suite to test different JSON requests and compare the responses.

The most interesting part was how a small change in the JSON key names and their order affected the application.

This helped me understand JSON parser differences and how they can lead to security vulnerabilities.

Overall, this challenge was good practice for source code analysis, HTTP request testing, and understanding authorization bypass techniques.

Written by J. Aazaf Ritha (ARVictor)

More write-ups: Medium — Aazaf Ritha

Connect: Medium | GitHub | LinkedIn

Thanks for reading!

--

--