Preamble
There are alot of reasons to look forward to the holiday season and the annual SANS Holiday Hacking Challenge is no exception. This year they went with a conference theme, where you sign into a virtual world and attend Kringlecon
– a mythical conference hosted by santa and his crack team of information security elves. SANS makes things very approachable by giving you smaller terminal challenges to solve in exchange for hints regarding the bigger objectives. This is my writeup on 2018 SANSHHC, aka Kringlecon.
On a personal note, this year was my favorite SANSHHC yet, the variety of challenges and exposure to unfamiliar (to me) technologies was phenomenal. The ASCII art was also a great treat, I was always excited to solve the terminal challenges and see what came out. Hopefully you’re able to take something away from this and use it in your next CTF.
Table of Challenges
We got a little bit of everything with this years SANS Holiday Hacking Challenge, so heres an overview incase there is anything in particular you want to check out.
Title | Gist | (Objective) Difficulty |
---|---|---|
1. Essential Editor Skills / Orientation Challenge | Vim/HTML | 1/5 |
2. The Name Game / Directory Browsing | CMD Injection/ Dir traversal | 1/5 |
3. Lethal ForenseicELFication / De Brujin Sequences | Trufflehog / de Brujin Sequence | 1/5 |
4. Stall Mucking Report / Data Repo analysis | SMB / Trufflehog | 2/5 |
5. CURLing Master / AD Privelege Discovery | cURL / Bloodhound | 3/5 |
6. Yule Log Analysis / Badge Manipulation | Windows evtx / SQL injection | 3/5 |
7. Dev Ops Fail / HR Incident Response | git / CSV Injection | 4/5 |
8. Python Escape from LA / Network Traffic Forensics | Python / Wireshark | 4/5 |
9. Sleighbell Lottery / Ransomware Recovery | gdb / Snort / Malware analysis | 5/5 |
10. Santas Vault / Who did it? | Music / Story | 1/5 |
Challenge 1
Terminal Challenge 1 : Essential Editor Skills
The first elf we come across, Bushy Evergreen, is next to a terminal that is stuck in VIM and needs our help to get out.
It feels every other time I bring up VIM… someone says they can never figure out how to exit it.
This is an age old debate, so I’ll just say I love VIM, and I’d definitely recommend learning it.
Being able to use a terminal editor effectively is great when you’re dealing with remote Nix systems.
Escape ->
:q!
Objective 1 : Orientation Challenge
The first objective was a quiz with some SANSHHC history, having done the past two, this wasn’t too bad at all.
Challenge 2
Terminal Challenge 2 : The Name Game
To solve this challenge, determine the new worker’s first name and submit to runtoanswer.
The elf dropped a hint relating to command injection and SQLite, from there the path was clear.
In this case the ampersand allowed us to append an additional command spilling the DB and info we wneeded for the solve.
Objective 2 : Directory Browsing
Who submitted (First Last) the rejected talk titled Data Loss for Rainbow Teams: A Path in the Darkness ?
This objective has you go to a Call For Papers site, with the name of the challenge being Directory Browsing I had all I needed upfront.
Immediately going to the website it was sparse and attention was immediately drawn to the URL.
Alright so what if we try to strip the end off?
That rejected_talks.c1_solve
is looking like our target, lets pop it open and use the find function real quick.
Challenge 3
Terminal Challenge 3 : Lethal ForenseicELFication
Find the first name of the elf of whom a love poem was written. Complete this challenge by submitting that name to runtoanswer.
Alright so to get started I always like to look around the directory and see if anything catches my eye. In this case we’re immediately draw to .viminfo
lets spill its contents and see what that’s all about.
We can see Elinore is a name prominently featured here, as if someone removed it from their poem, thus that is our answer.
Objective 3: de brujin sequences
The room is protected by a door passcode. Upon entering the correct passcode, what message is presented to the speaker?
We’re presented with a door sporting a pin made up of a combination containing 4 shapes.
I was fortunate, while clicking around I luckily guessed it, but how do we do this proper?
Well, opening Chromes developer tools -> network tab
we can see where the request is being made to validate the pin, from there we can just use some quick
pythons to automate some brute forcing action. To be incredibly precise you could read about de brujin sequences and adjust your script accordingly.
|
|
Challenge 4
Terminal Challenge 4 : Stall Mucking Report
Complete this challenge by uploading the elf’s report.txt file to the samba share at //localhost/report-upload/
Alright so this challenge references samba, and the only thing on the directory is report.txt.
We can use ps aux
to check for running processes, looking for something samba.
From there we can see a line with the name manager, and that looks to be of interest, lets use grep
to narrow our results.
We can see the password used and then craft our own command to upload the report using the same.
Objective 4 : Data Repo Analysis
Retrieve the encrypted ZIP file from the North Pole Git repository. What is the password to open this file?
Did you say git repository? Well git tends to retain everything through versioning, which is great… unless you accidentally committed some sort of secret.
Then we can use a tool called Trufflehog
to find it. I thoroughly recommend implementing Trufflehog as part of your CI/CD process to help spot accidental secret commits early.
So all we need to do is pull the repository and point Trufflehog
at it.
Challenge 5
Terminal Challenge 5: CURLing Master
Complete this challenge by submitting the right HTTP request to the server at http://localhost:8080/ to get the candy striper started again.
Alright, following that statement they say to checkout /etc/nginx/nginx.conf
, if we cat it and take a look… we see a comment helping us narrow down whats important here.
HTTP2 is different, so a quick consult to our CURL documentation gives us a flag to throw in.
After that the output tells us to add a POST and have status=on
, no problem just throw it on the end of our CURL
command and voila.
Objective 5 : AD Privelege Discovery
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?
Alright, so if we throw the image into virtualbox and fire up bloodhound the data is already preloaded.
From there I was able to spot a filter that would give us our desired result.
This was pretty sweet, I’d never seen Bloodhound before but being able to visualize all these AD relations was great. Then being able to create attack paths off it sounds even more awesome.
Challenge 6
Terminal Challenge 6 : Yule Log Analysis
Submit the compromised webmail username to runtoanswer to complete this challenge.
This challenge has a .evtx logfile
and a Python
script to convert it to something you can grep
.
Windows event logs are pretty straight forward and well documented, you can see the standard structure below.
I used targetusername
as a filter to narrow results down, then looked at various users until I could identify which was compromised via the log.
Coming back to do this writeup I noticed I didnt take a picture of the exact event that tipped me off. Whoops.
Objective 6 : Badge Manipulation
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?
Immediately two things become clear.
- This is going to be a SQL Injection Challenge
- Based on that badge I’m going to have to load it into a QR code.
I’m by no means a SQLi ninja, I just know enough to be dangerous. So lets stick an apostrophe in a QR code and see what happens.
{"data":"EXCEPTION AT (LINE 96 \"user_info = query(\"SELECT first_name,last_name,enabled FROM employees WHERE authorized = 1 AND uid = '{}' LIMIT 1\".format(uid))\"): (1064, u\"You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '''' LIMIT 1' at line 1\")","request":false}
From this I understand that we’re injecting our payload into uid
, and the DB flavor is MariaDB
.
After trying many payloads and trying to think through the backend logic, I felt like I was at an impasse.
I reached out to a DBA friend of mine, JB for some SQL
knowledge and he helped me understand what I was missing here.
Before I go ahead show the final payload lets talk about something else I missed here, the added relevance of the employee badge.
If we give the door our employee badge, we get this message {"data":"Authorized User Account Has Been Disabled!","request":false}
They keyword here being disabled. Now proceeding onward, what does our SQLi payload look like?
I really wanted to understand why this was the answer as opposed to something like or '1='1';--
.
The logic:
- Assuming our SQL roughly evaluates to
SELECT first_name,last_name,enabled FROM employees WHERE authorized = 1 AND uid = 'a' or enabled = 1 and ''=' LIMIT 1
- dont worry about uid, if we were supposed to manipulate that, then Alabaster Snowball’s QR code would’ve had a UID to look at
- so we add the subquery in to bypass the logic, SQLs ordering will execute that first which will cause the conditional to evaluate as true
- this allows us to get results back from the query
- the
limit
1 on the end however means that we only get the first result, and the first results account is disabled - adding
enabled=1
allows us to return a result with a passing account
Challenge 7
Terminal Challenge 7 : Dev Ops Fail
This one is succinct, and similar to the Trufflehog challenge being git is the culprit. Except this time we get no Trufflehog
, what do we do??
We use Git. git help
-> git log
(Identify commit to examine) -> git diff _commit_
Objective 7 : HR Incident Response
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”?
Web challenges are always fun and the hints all point to this one being a csv injection. Looking at the site we see a nice form with a file upload.
At this point Im not sure what my csv injection should be, so I try my favorite approach – poking around the site and seeing what I find
Oh alright, armed with this fresh knowledge lets make a super simple payload.csv
Submitting this triggers a file download of the aforementioned candidate_evaluation.docx.
Challenge 8
Terminal Challenge 8 : Python Escape from LA
To complete this challenge, escape Python and run ../../images/posts/kringlecon/i_escaped
This one has an accompanying talk so I watched that to learn how to get this one done.
In the talk he was implementing a black list on the python shell and demonstrating creative ways to circumvent it.
I like Python so I thought Id try some other creative ways to get around it.
The first thing that came to mind was base64 encoding for a filter bypass
Next someone had mentioned I should look up the globals function in the Python standard library.
If its not blacklisted then we can use it to overwrite the global variable containing the blacklisted function names.
Looks line restricted terms is what we want to overwrite, lets give it a go.
Objective 8 : Network Traffic Forensics
Santa has introduced a web-based packet capture and analysis tool 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?
Armed with my new found knowledge of HTTP/2 from the CURL master challenge, and the hints from the Python Escape I was feeling ready to tackle this one.
I also don’t do alot with Wireshark so I’m excited to get some more time in using it.
Well heres the site. When you sign in and poke around it has a nice UI, but that’s not what we’re here for. It gives us our PCAP file but its encrypted.
So what do we do? Directory traversal is easy, lets start there. The app is snappy so we’ll look for something associated with those kinds of web frameworks.
Boy do I love a good error message. A quick Google and it looks like we’re working with NPM/Node.
A comment line in the HTML of the site mentions rushing into production and accidentally including dev code…
Look at that, the source code! Not to mention, if our goal is to decrypt then seeing server.key
is looking promising.
…But its not, its a red herring. They’re trying to draw our eyes away. If we look above the variables dev_mode
and key_log_path
start to look interested. Dev mode is set to true (Because its dev code remember? How fortunate.), so that means we can reach it. Lets throw SSLKEYLOGFILE
onto the end of our URL.
Another error message… but at least we can clearly see the next breadcrumb. Some more mild fiddling around with the URL and we finally get.
Sweet, the key! Now we can download it, and feed it to Wireshark
to decrypt our HTTP/2
traffic. The SANS videos accompanying Kringlecon helped me understand more about Wireshark and its filters, making this much easier.
Well I don’t see any indication of an attachment in this PCAP, but finding some credentials gives me a new direction. What if we try to log into Alabaster Snowballs account using them?
I was wondering why have us login, and I thought some of the text on that login screen was phrased interestingly.
Moving on, from here we can download the PCAP, open it, and see it’s not encrypted. Not only that, but it’s easy to scroll through and see where the email begins as a Follow TCP Stream
. So if we just right click Follow Stream
we’re rewarded with this.
Look, Base64! We can wrangle that with a few lines of Python
to dump it out into a file. Opening the file I see the word PDF, so I immediately close it, save it as .pdf
and reopen it.
Seeing the PDF open with nothing wrong was pretty awesome, I’d never pulled an attachment out of Wireshark
like this before.
Challenge 9
Terminal Challenge 9 : Sleigh Bell Lottery
Complete this challenge by winning the sleighbell lottery for Shinny Upatree.
Descriptive right? Theres a little lottery binary, objdump, and GDB in the directory, chances are we need to call a function.
Most of the terminal challenge have been simple so far, so lets treat this one the same way.
First we’ll use objdump to look at the functions in the binary and see if any jump out at us.
It does get much more apparent than that, so how do we call it?
Since we were provided with GDB we can just place a breakpoint at main then jump to the winwinwin function.
Pretty straight forward, a great introductary challenge for GDB if you’re not familiar with it already.
Sadly this is the last piece of ASCII art, I thoroughly enjoyed them all and could’ve easily spent a whole post admiring the art they put into this.
Obective 9
For me Challenge 9 was a doozy, both for introducing me to new concepts, and challenging my understanding of existing ones.
Obective 9.1 : Catch the Malware
Assist Alabaster by building a Snort filter to identify the malware plaguing Santa’s Castle.
They provide us a snort terminal to input our answer onto, and some PCAPs with traffic to analyze. More Wireshark action!
Immediately we notice quite a few things going on here.
- They DNS queries with malicious traffic all have hex strings at the start
- The DNS names are dynamic
- The content size of the packets containing the malicious code is apparent
- Decoding the malicious packets TXT segment shows us the malware transmitting its source
Neat but we cant block based on the hex body, or the packet size, or the DNS names because then we may shun legit traffic.
So what does that leave? Upon closer inspection you’ll notice that all the DNS names begin with that same hex string, we can use that!
I’ve not done anything with Snort outside of studying for cert exams so writing a rule was new to me. After reading a few sites it became
apparent that we would need to use Content
as our blocker, and a kind person recommended I convert the hex string to bytes for this.
After doing that we windup with the following rule.
I’ve been alternating between turning the answers ingame, and on that static site you see, when we give it the terminal output from the above it gives us the Word document for the next challenge.
Obective 9.2 : Identify the Domain
Using the Word docm file, identify the domain name that the malware communicates with.
Using the awesome Kringlecon talk on Powershell Malware analysis we have our base of knowledge to work through this.
Lets get started, first thing we need to do is extract the Macro from the Doc that is calling the powershell code that has the virus.
There’s our Macro alright but its heavily obfuscated, if we just drop the iex() function from the code we can pipe the deobfuscated string to standard output.
Well that URL certainly looks like it could be the domain the malware communicates with, lets try that out.
Obective 9.3 : Stop the Malware
Identify a way to stop the malware in its tracks!
Wannacookie is a clear name play on that nasty wannacry malware, so we know theres a killswitch involved!
If we slightly modify the dropper code by removing things like iex()
and then execute it, it’ll reward us with the source.
Sweet we have source code now! Sadly its a single line, so from here I had to drop it into Powershell ISE and prettify it back into something human readable.
After we do that, we have alot of type conversion functions, some encryption functions, and a main function called wanc
.
The first line of wanc
has an interesting string that it attempts to resolve on the next line in a conditional, a prime suspect for our killswitch domain.
What we’ll wanna do is set a breakpoint on the following line then manually run that string through its decoder functions so we can examine the output.
They provide us a fun little ‘Ho-Ho Daddy’ domain registrar, so lets go try our string there.
Slightly different from the Powershell reversing video, but obvious enough to get us moving forward.
Objective 9.4 : Recover Alabaster’s Password
Recover Alabaster’s password as found in the the encrypted password vault.
This challenge was ranked the hardest and rightfully so, you need a firm grasp on the concepts of encryption to tackle this one.
We can see by analyzing the functions in the Malware that they are implementing asymmetric encrpytion.
What is asymmetric encryption?
The two actions we want to hone in on are:
- Create a private key for just that user, this would be the unique one the malware authors give upon payment.
- Encrypt the private key using the private key from their C&C server
We’ll want to do the opposite. We already have our source code from 9.3, what does 9.4 give us?
This challenge supplies us with a memory dump of the program and an encrypted DB – alabasters-passwords.elfdb.wannacookie
.
The memory dump is relevant becuse the private key is generated with random bytes, so we’ll need to fish the exact key used out of the dump using Power dump
In order to narrow the search critera out of all the 11000 variables, I put a break point in the malware and just grabbed the length of p_k_e_k
, the encrypted private key that was used to encrypt the elfdb.
Sweet, now lets run a length match in Power dump
against the powershell memory dump.
We’re lucky to have gotten one result back, this makes things much easier for us.
Alright, so now we have the solution, but its unusable since it’s encrypted. We’ll need to get the asymmetric encryption pieces in order to decrypt it.
Immediately one thing stands out, we have to change our computers WORKGROUP
to KringleCastle or the program wont continue to execute.
Moving past that, I noticed another hex string a function called g_o_dns() containing a hex string. Decoded the string evaluates to server.crt.
A quick breakpoint, a function call…. and we’re rewarded with our server.crt, the first half of the asymmetric pair.
Awesome, now all we need is a private key. Maybe the attackers didn’t secure their infrastructure and we can leak the private key the same way, just with a hex encoded string containing a value of server.key.
With both pieces of the puzzle, now comes the hard part. We need to combine them together into a certificate, and then import the certificate and use it to decrypt the p_k_e_k
to then decrypt the database.
Fortunately a fellow with kringlecon attendee with the handle marlas linked me these two pages which helped me get everything assembled together. I’ve worked with certificates on Linux systems but on Windows in Powershell this is new territory.
How to create a PFX Certificate
Using a PFX Certificate in powershell
I lined out what I felt was a good decryption function. I made a slight mistake when I copy pasted the script, so for a while I was spinning in circles. I didn’t notice a syntax error I made earlier since the function e_d_file
hadn’t been called until now.
|
|
The extension is .elfdb
and not knowing any elves, I opted to open it in N++ because I am not sure what else to use..
Oh, thats what else Im going to open it with, SQLite.
Fortunately they didnt fill this with alot of data and we have our answer immediately.
Challenge 10 : Santa’s Vault
That password looks alot like musical notes… and there’s a piano on the wall.
Not only that, but the PDF we got from the TCP Stream earlier mentioned the key of D.
Lets throw this all together in an online music transposer, and I’m not sure what key to start with so we’ll use the default of E.
E was the right key to start with! With that, we’ve completed all the challenges we need to finish Kringlecon.
Objective 10 : Who did it?
Who was the mastermind behind the whole KringleCon plan?
Santa reveals he did this all for us.
I actually answered this one before I found got through the piano door, I gave it a guess. Trying “Santa” as a guess kind of felt like trying “password” but it worked! My second lucky guess in this writeup.
Prologue
This was the first SANS Holiday Hacking Challenge I’ve completed. It felt really great for so many technical concepts to come together in accomplihing these objectives. I learned an immense amount and had the opportunity to hone some existing skills with practice. Not to mention, that ASCII art was pretty sweet.
I get asked regularly by people how to learn or get better at InfoSec type skills.
CTFs like this SANSHHC
are the place to do just that. Especially with the Holiday Hack challenge; SANS provides you so much information, challenges to pit it against, and an environment to mingle with other like minded people. Thats a solid environment to learn in as opposed to trudging through youtube videos and documentation, if you say you want to learn but don’t take advantage of these opportunities then you’re missing out. Don’t worry if you aren’t sure where to start, just jump into the CTF and see what it asks of you.
In the end it’s all just learning and practice, which was Kringlecons
gift to us all along this holiday season.