Space Explorer — Hack The Box Web Challenge Write up
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.
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/filesThe 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
lsThe extracted files included:
space_explorer/
├── build-docker.sh
├── Dockerfile
├── entrypoint.sh
├── go-app/
│ ├── main.go
│ ├── go.mod
│ └── go.sum
└── python-service/
└── app.pyFrom 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.
Analyzing the Go Application
I started by checking the Go source code using:
cat go-app/main.goThe 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 RequestDataif 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 Pythoncase "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.
Analyzing the Python Application
Next, I checked the Python source code using:
cat python-service/app.pyThe 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"}), 400If 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.
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
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.
Next, I selected Access Secure Database and clicked the same button.
This time, the application displayed the following error:
Access denied: Invalid security clearanceThis 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.
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.
Testing the Restricted Request
Next, I changed the JSON value to getSecureCode.
{
"action": "getSecureCode"
}The server returned:
Access denied: Invalid security clearanceInterestingly, 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.
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"
}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 RequestInvalid commandThis 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.
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.
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!






