Holiday Hack 2023: Rudolph's Rest
Geography
Getting To
Continuing East from Frosty’s Beach along the coast of Chistmas Island I’ll find Rudolph’s Rest.
Location Layout
The Goose of Christmas Island meets me at the end of the Dock with their typical “Honk!”.
In front of the giant hotel, I’ll find two elves with challenges, Noel Boetie with the Reportinator and Sparkle Redberry with Azure 101.
Inside the hotel, I’ll find the Lobby with Pepper Minstix and the Cotton Candy machine, as well as Wunorse Openslae in the Netwars room:
Pepper tells me about their cotton candy machine:
Pepper Minstix
Well hello there! I’m Pepper Minstix.
Say, do you like cotton candy by any chance?
I used to own a little cotton candy maker, but I like cotton candy so much that I decided to upgrade. Behold! The Cotton Candy Colossus 2.0.
Can I interest you in free cotton candy? What do you say! They are absolutely amazing!
Have fun on the Geese Islands! There’s still more to discover –
Like sailing your boat along the various coast lines to find new ports, catch some fish, meet new friends, or provide your expertise and assistance where needed.
After you complete all the challenges, come back here for a surprise!
I need to come back after I’ve solved all the challenges.
Wunorse has a speech kicking off a NetWars event:
Wunorse Openslae
Welcome, brave souls, to the most thrilling cyber quest of the year! Ready your wits and sharpen your skills, for the digital realm awaits!
I’m Wunorse, your helper in this festive cyber journey. Whether you’re a seasoned hacker or a budding cyber sleuth, you’re in for an epic experience!
As we embark on this adventure, remember, every challenge is a chance to shine brighter! Let’s tackle these puzzles with the joy and teamwork befitting this jolly season!
Keep your eyes peeled for clues and your spirits high. In the world of NetWars, every click can lead to wonderful discoveries!
May your codes be bug-free and your solutions creative. Let NetWars begin, and may the best cyber elf win!
Let the games begin!
Reportinator
Challenge
The first objective here is Reportinator:
Noel Boetie is next to the Reportinator. He’s been playing with AI and it’s gotten him in trouble:
Noel Boetie
Hey there, Noel Boetie speaking! I recently tried using ChatNPT to generate my penetration testing report.
It’s a pretty nifty tool, but there are a few issues in the output that I’ve noticed.
I need some guidance in finding any errors in the way it generated the content, especially those odd hallucinations in the LLM output.
I know it’s not perfect, but I’d really appreciate the extra eyes on this one.
Some of the issues might be subtle, so don’t be afraid to dig deep and ask for further clarification if you’re unsure.
I’ve heard that you folks are experts about LLM outputs and their common issues, so I trust you can help me with this.
Your input will be invaluable to me, so please feel free to share any insights or findings you may have.
I’m looking forward to working with you all and improving the quality of the ChatNPT-generated penetration testing report.
Thanks in advance for your help! I truly appreciate it! Let’s make this report the best it can be!
The terminal looks like a table with a Penetration Test report on it:
For each of nine findings, I’m asked to find if they are valid or contain any hallucinations from the AI that helped write the report. For example, the first finding is:
The green check can be toggled to a red X to mark a hallucinated finding.
Solution
There are three findings that contain hallucinations, #3, #6, and #9.
3. Remote Code Execution via Java Deserialization of Stored Database Objects
This title does represent a potentially valid finding, but many parts of the description are just off.
The report talks about ysoserial, which is a tool used to exploit Java deserialization vulnerabilities. However, it’s the tool to generate the final payload to get execution. It does not play any role in the enumeration / discovery of the vulnerability. That makes this sentence a bit awkward:
SCS evaluated this application with the ysoserial tool and Burp Suite to manually evaluate the application for typical Java vulnerabilities.
This one is flat out wrong:
Verification: NPS security teams can verify the remediation of this finding with the ysoserial tool. The tool will stress the Java application with different commands and payloads to determine if the application is still vulnerable.
The report also refers to Listing 1 as showing that the application uses Java’s native serialization and gets data from the database. But Listing 1 is just the output of a ysoserial command, generating a payload. This shows nothing about the target system.
The report also talks about intercepting HTTP traffic on TCP port 88555 to exploit this vulnerability. That is not possible. While a web server can run on any valid port, the maximum valid port is 65535. Additionally, the report doesn’t make any connection as to how this HTTP traffic is related at all to the serialized objects that are retrieved from the database. So while it is possible to think of a scenario where this may come into play, it is not obvious and should be explained much more clearly (or, more likely, it’s just a hallucination). Similarly, the NIST SP 800-53 controls SC-8 and SC-28 are real controls, but don’t make much sense for this problem of serialized data stored in the database (without additional explanation).
6. Stored Cross-Site Scripting Vulnerabilities
Another potentially valid finding with little mistakes throughout:
- There is no HTTP SEND request. Valid HTTP verbs are documented here.
- Not encoding input data is not a thing. Input data needs to be sanitized. The next sentence continues talking about “mishandling of data encoding”. This bears some resemblance to the trust, in that a way to avoid XSS is to encode risky characters and not handle them as code, but this is more commonly referred to as sanitization.
- The sentence “We found a preponderance of responses” is meaningless and doesn’t describe a problem. Is it saying those special characters caused…more responses?
9. Internal IP Address Disclosure
This finding is full of little mistakes:
For example:
- There is no such thing as an HTTP 7.4.33 request.
- It’s possible but not likely that a private IP could be used in social engineering.
- In the example screenshot, the first response doesn’t leak an IP in the Location head (though may in the X-Upstream header, but that’s never mentioned).
- In the example screenshot, the second response leaks an invalid IP with a first octet of 1192, far beyond the max of 255.
- Leaking the Windows registration key is never something you’d want to do (assuming these web servers are even running Windows).
- Content-Security-Policy and X-Content-Type-Options have nothing to do with leaking IPs via the Location header.
Hacking Solution
Overview
Instead of reading the report, I can just brute force the solution to this challenge by understanding how the attempts are sent to the server. I’ll go into details in this video:
Get Request Details
I’ll open the dev tools in my browser and go to the network tab. Then, with 1 and 3 marked with X (randomly, just want some examples), I’ll scroll down to the bottom of the report and submit. This generates a new row:
Clicking on that, I’ll find the details of the request and the response. Under “Response”, it’s a JSON response showing failure:
Under request, it shows the data sent:
The “Raw” toggle at the top right will show the raw query string:
input-1=1&input-2=0&input-3=1&input-4=0&input-5=0&input-6=0&input-7=0&input-8=0&input-9=0
I also need to be aware of the request headers, as without two things, the request will always return failure:
Typically when trying this kind of automation of some behavior that’s designed for Browser interaction, it’s safest to grab all the headers, and then reduce to just the necessary ones there’s success.
Python Script
Armed with these details, I’ll write a Python script to brute force the solution. I’m using httpx to asynchronously send HTTP requests, so it’s pretty fast! See the video for details.
#!/usr/bin/env python3
import asyncio
import httpx
from itertools import product
url = "https://hhc23-reportinator-dot-holidayhack2023.ue.r.appspot.com/check"
headers = {
"Cookie": "ReportinatorCookieYum=eyJ1c2VyaWQiOiI3MzZlNWM5Ny0xNmNjLTQxZGItODVhYi0xMmI2ZmU4MjQwYWIifQ.ZXy0bg.SQ-OclDuOdaJvSk46QId13Y-jrY",
"Content-Type": "application/x-www-form-urlencoded",
}
async def test_combination(combination, client):
post_body = "input-" + "&input-".join(
f"{i}={v}" for i, v in enumerate(combination, 1)
)
resp = await client.post(url, data=post_body, headers=headers)
return resp, combination
async def main():
async with httpx.AsyncClient() as client:
combinations = product([0, 1], repeat=9)
tasks = [test_combination(x, client) for x in combinations]
responses = await asyncio.gather(*tasks)
for resp, comb in responses:
if not "FAILURE" in resp.text:
bad_findings = [str(i) for i, v in enumerate(comb, 1) if v == 1]
print(f"Bad findings: {', '.join(bad_findings)}")
if __name__ == "__main__":
asyncio.run(main())
It runs in less than two seconds:
oxdf@hacky$ time python brute_reportinator.py
Bad findings: 3, 6, 9
real 0m1.846s
user 0m1.522s
sys 0m0.210s
Epilogue
Noel is impressed:
Noel Boetie
Great job on completing that challenge! Ever thought about how your newfound skills might come into play later on? Keep that mind sharp, and remember, today’s victories are tomorrow’s strategies!
Azure101
Challenge
The other objective solvable at Rudolph’s Rest is the Azure 101 challenge:
I’ll find Sparkle Redberry at the south west corner of Rudolph’s Rest, who presents an Azure challenge:
Sparkle Redberry
Hey, Sparkle Redberry here! So, I’ve been trying to learn about Azure and the Azure CLI and it’s driving me nuts.
Alabaster Snowball decided to use Azure to host some of his fancy new IT stuff on Geese Islands, and now us elves have to learn it too.
Anyway, I know it’s important and everyone says it’s not as difficult as it seems, but honestly it still feels like quite a challenge for me.
Alabaster sent us this Azure CLI reference as well. It’s super handy, he said. Honestly, it just confuses me even more.
If you can spare a moment, would you mind giving me a hand with this terminal? I’d be really grateful! Pretty please, with holly leaves on top!
The terminal is similar to the previous Linux 101, presenting six questions involving interaction with Azure cloud from the command line.
Solution
-
You may not know this but the Azure cli help messages are very easy to access. First, try typing:
$ az help | less
:az
is the Azure command line interface (CLI), and running thehelp
subcommand will show a very long help page. I’m piping it toless
so that I can manage that output easily to scroll up and down. -
Next, you’ve already been configured with credentials. Use ‘az’ and your ‘account’ to ‘show’ your current details and make sure to pipe to less ( | less ).
The prompt is explicit that it wants
az account show | less
, which generates the following JSON data:{ "environmentName": "AzureCloud", "id": "2b0942f3-9bca-484b-a508-abdae2db5e64", "isDefault": true, "name": "northpole-sub", "state": "Enabled", "tenantId": "90a38eda-4006-4dd5-924c-6ca55cacc14d", "user": { "name": "northpole@northpole.invalid", "type": "user" } }
-
Excellent! Now get a list of resource groups in Azure. For more information: https://learn.microsoft.com/en-us/cli/azure/group?view=azure-cli-latest
Using the help pages as a reference, I’ll find the
az group list | less
command:[ { "id": "/subscriptions/2b0942f3-9bca-484b-a508-abdae2db5e64/resourceGroups/northpole-rg1", "location": "eastus", "managedBy": null, "name": "northpole-rg1", "properties": { "provisioningState": "Succeeded" }, "tags": {} }, { "id": "/subscriptions/2b0942f3-9bca-484b-a508-abdae2db5e64/resourceGroups/northpole-rg2", "location": "westus", "managedBy": null, "name": "northpole-rg2", "properties": { "provisioningState": "Succeeded" }, "tags": {} } ]
-
Ok, now use one of the resource groups to get a list of function apps. For more information: https://learn.microsoft.com/en-us/cli/azure/functionapp?view=azure-cli-latest. Note: Some of the information returned from this command relates to other cloud assets used by Santa and his elves.
Here I’ll find the
az functionapp list
command. If I don’t give it a resource group, it errors out saying I don’t have permissions. I’ll give it each of the resource groups from the previous question. “ “northpole-rg2” returns an empty list, but “northpole-rg1” returns information about the function apps:elf@b38b9a4cfd40:~$ az functionapp list --resource-group northpole-rg2 [] elf@b38b9a4cfd40:~$ az functionapp list --resource-group northpole-rg1 [ { "appServicePlanId": "/subscriptions/2b0942f3-9bca-484b-a508-abdae2db5e64/resourceGroups/nor thpole-rg1/providers/Microsoft.Web/serverfarms/EastUSLinuxDynamicPlan", "availabilityState": "Normal", "clientAffinityEnabled": false, "clientCertEnabled": false, "clientCertExclusionPaths": null, "clientCertMode": "Required", "cloningInfo": null, "containerSize": 0, "customDomainVerificationId": "201F74B099FA881DB9368A26C8E8B8BB8B9AF75BF450AF717502AC151F59 DBEA", "dailyMemoryTimeQuota": 0, "defaultHostName": "northpole-ssh-certs-fa.azurewebsites.net", "enabled": true, "enabledHostNames": [ "northpole-ssh-certs-fa.azurewebsites.net" ], ...[snip]...
There’s a ton of data there, some of which I’ll come back to later!
-
Find a way to list the only VM in one of the resource groups you have access to. For more information: https://learn.microsoft.com/en-us/cli/azure/vm?view=azure-cli-latest
There’s a
vm
command with alist
subcommand. This time “northpole-rg1” doesn’t work, but “northpole-rg2” has a VM:elf@b38b9a4cfd40:~$ az vm list --resource-group northpole-rg1 The client 'f17559a4-d8a2-4661-ba0f-c04f8cf2926d' with object id '8deacb33-214d-4d94-9ab4-d27768410f17' does not have authorization to perform action 'Microsoft.Compute/virtualMachines/read' over scope '/subscriptions/2b0942f3-9bca-484b-a508-abdae2db5e64/resourceGroups/northpole-rg1/providers/Microsoft.Compute/virtualMachines' or the scope is invalid. If access was recently granted, please refresh your credentials. elf@b38b9a4cfd40:~$ az vm list --resource-group northpole-rg2 [ { "id": "/subscriptions/2b0942f3-9bca-484b-a508-abdae2db5e64/resourceGroups/northpole-rg2/providers/Microsoft.Compute/virtualMachines/NP-VM1", "location": "eastus", "name": "NP-VM1", "properties": { "hardwareProfile": { "vmSize": "Standard_D2s_v3" }, "provisioningState": "Succeeded", "storageProfile": { "imageReference": { "offer": "UbuntuServer", "publisher": "Canonical", "sku": "16.04-LTS", "version": "latest" }, "osDisk": { "caching": "ReadWrite", "createOption": "FromImage", "managedDisk": { "storageAccountType": "Standard_LRS" }, "name": "VM1_OsDisk_1" } }, "vmId": "e5f16214-18be-4a31-9ebb-2be3a55cfcf7" }, "resourceGroup": "northpole-rg2", "tags": {} } ]
-
Find a way to invoke a run-command against the only Virtual Machine (VM) so you can RunShellScript and get a directory listing to reveal a file on the Azure VM. For more information: https://learn.microsoft.com/en-us/cli/azure/vm/run-command?view=azure-cli-latest#az-vm-run-command-invoke
The
vm
command has arun-command invoke
subcommand. I’ll need the resource group, the name of the VM, and a command id.--script
gives the command(s) to run (I’ll do anls
to satisfy the challenge):elf@95276280d1ba:~$ az vm run-command invoke --resource-group northpole-rg2 --name NP-VM1 --command-id RunShellScript --scripts "ls" { "value": [ { "code": "ComponentStatus/StdOut/succeeded", "displayStatus": "Provisioning succeeded", "level": "Info", "message": "bin\netc\nhome\njinglebells\nlib\nlib64\nusr\n", "time": 1701814672 }, { "code": "ComponentStatus/StdErr/succeeded", "displayStatus": "Provisioning succeeded", "level": "Info", "message": "", "time": 1701814672 } ] }
The terminal tells me “Great, you did it all!”.
Epilogue
Sparkle is impressed! He recommends I find Alabaster on Pixel Island:
Sparkle Redberry
Wow, you did it!
It makes quite a bit more sense to me now. Thank you so much!
That Azure Function App URL you came across in the terminal looked interesting.
It might be part of that new project Alabaster has been working on with the help of ChatNPT.
Let me tell you, since he started using ChatNPT he’s been introducing a lot of amazing innovation across the islands.
Knowing Alabaster, he’ll be delighted to tell you all about it! I think I last saw him on Pixel island.
By the way, as part of the Azure documentation he sent the elves, Alabaster also noted that if Azure CLI tools aren’t available in an Azure VM we should use the Azure REST API instead.
I’m not really sure what that means, but I guess I know what I’ll be studying up on next.