SANS Holiday Hack 2018 Kringlecon


Hi All,

I thought I’d post my walkthroughs for the objectives and challenges from SANS Holiday Hack. This is a hack challenge put on by Ed Skoudis and his team. They also keep past challenges up which is pretty cool!

This years theme was that of a convention. After creating an gravitas, I had to walk around to view the various challenges. Most challenges brought me to a terminal screen where a message would give me some direction to solve the puzzle. There’s also some really good speaker talks available inside the con (or on YouTube if you prefer) that apply directly to the puzzles.

Word of warning: I wouldn’t directly copy any of the commands from this text. Please type them in manually. Editors do weird things to single and double quotes that can mess up the command. You have been warned!


Vi Escape

The first one was very simple … escape Vi. For those that don’t know, Vi is a text editor used in Unix/Linux environment. It’s renown for its powerful yet obscure command interface. If you don’t use it, it’s easy to forget how to do very basic things … like how to exit the interface.  /Steps on soapbox: I never use Vi (unless forced) because I think it’s ridiculous for such an un-user friendly interface to exist in 2018. Nano, for example, has always been able to do everything I needed while still being intuitive. The infosec community needs to demand more from their tools, not cave to the pressure of elitists jerks who thinks anyone who doesn’t use vi or vim is a noob /end soap box rant.


So to exit vi you need to type :q! and press enter. There’s actually a shell escape with Vi that will dump you to the prompt without actually exiting vi. That won’t work. They really want you to exit Vi properly.


And here’s the confirmation message.



Who wrote the poem?

This challenge was also simple in that they gave away the location of the answer right in the opening message.


So basically they tell you to read a history file to find a name. History files are usually hidden so I looked at all the files in the elf home directory to see if it might be there. It sure was.


After viewing the .viminfo file, a name stuck out right away. Notice how there was also interaction with a .secrets directory and the poem.txt? This is probably the name we’re looking for. Let’s try it!


Yep that was it! Two challenges down. The rest will most certainly be harder.



The locked door.

Ok so there’s this door. It has a 4 code combination. The previous code persists and seems to operate in a fist in first out (FIFO) kind of way. So by adding a new code block, the first is pushed off and the code block added is now the last code in the sequence. I would love to say that I knew exactly how to compromise the code, but I don’t. I literally just randomly clicked and opened the door in 10 seconds. I was clicking so fast I actually don’t know what the code was. I just received the achievement and noticed the door was open. There are 256 permutations (4^4). I started making a table but random luck proved to be much faster. UPDATE: After I solved some other challenges I learned that this can be solved by using the Bruijn Sequence.



Find the compromised account

This one was tedious for me mainly because I kept getting kicked off the server every 10 minutes. The challenge is to find the account that was compromised by a password spray. Password spraying is like brute forcing in reverse. Instead of trying 100 passwords against a single user account, the attacker tries one password against 100 user accounts. This gets around lockout attempts and is very effective since users tend to pick really bad (guessable) passwords. Don’t make your password something like Mycompany2018!

The first thing I did was list out the directory. I had no idea what did so I ran the help command on it. It seemed to take an evtx file (I didn’t know what that was either) and turn it into xml. I chose to dump it into a file so I could run searches off of it faster, but you don’t have too.


Once the file was ready, I simply looked at it to see what was there. It was a log file. With password spraying, the logs should contain multiple failed users access attempts coming from a single IP address. So if I get a list of IP addresses and find the address with lots of different users, I’ll know which address the attack was coming from. Once I have that I can look for successful accesses attempts from that IP and check the user name.


To get the address list I just grepped the file and sorted/filtered it for unique


I then went down through the list and counted how many times an IP address showed up.

grep ‘IPADDRESS’ log.txt | wc -l

Remember with password spraying there should be a lot of attempts. was one of the addresses that floated to the top of my list. I then used this command to view just the user names. The -A and -B commands just include the 20 lines before and after the line I grepped for. Without those flags, the data wouldn’t be available to pipe to other grep commands.

grep “” log.txt -A 20 -B 20 | grep TargetUserName

Looking through the list of names, it became very clear that this is the attacking IP. Notice how the names are in alphabetical order? That’s what bad looks like. I also got lucky here in that the user minty.candycane had other event data that happened to stick out in my search. I though that was worth a try.


It worked! Just as a reminder, SeasonYear! is also a bad password.



Escape from PY jail


This was really fun. When I first ran into this terminal I wasn’t sure how to go about it. Basically, the terminal is a python session but certain commands have been black listed. Commands like exec, os.system, import and compile will not work. These are the typical commands python uses to interact with the operating system. After the 100th time of getting kicked off the server, I decided to check out one of the kringlecon talks. It proved to be exactly what I needed. The talk was AWESOME. Check it out

It’s literally all about how to break out of a python jail 😊

First, I ran commands to see what exactly was allowed or not. It turns out that eval was still allowed though import was not. I then followed the advice in the talk and broke up the import command string into two parts. It ran without issue and now the os module was loaded.


os.system was still not allowed and this was a wrinkle not covered in the talk.


I decided to use the same principle and name a variable to os. It worked just fine and I was able to get command execution.


With command execution in hand, I simply ran ./i_escaped and claimed my prize.



Google Ventilation Maze

This was fun just because it brought back some map making nostalgia. Maybe there’s a better way to beat it, but I had fun just making a map. Luckily, I had some graph paper laying around which made it so much nicer. The maze was divided into two areas. An upper and a lower area. The maze starts in the lower area and the finish is in the upper area. If you didn’t want to make a map, you could also just keep turning right.

Anyway, here’s my smudgy map. S is the start in the lower left. At the top right leads UP to the next section of the maze.


In the second section, I marked the start with a D for down. The exit is at the F on the right.


At the end it dropped me into a room where Santa had captured Hans. There were some additional challenges in this room. It also seemed to bypass a badged door challenge.



Curl Master

In this challenge, the user is supposed to help restart a service by using a website call that is not acting as expected. I’m not exactly a curl master, but it turns out that I didn’t really need to be.


One of the first things I always do is look around to see what’s available. In this case, there was a bash history file.


Viewing the history shows a curl command that was recently run. I wanted to see what it did so I ran it as well and found some directions.


The website is using http2 which curl can handle. The only thing left to do was to make the command a POST request and add a parameter. I remembered how to do the POST request, but I had to google the parameter. It was about as simple as it gets.


With the two options (-X and -d) added, the challenge was complete.



Find the Name

For this challenge, I had to search for a name in a database. The only catch is that they don’t actually give you access to the database.


Looking at the options, verify the system jumped out at me as being odd. After selecting it and putting in some junk input, it became very clear that this was simply running a ping command. It also gave some SQLite version and database information.


Well since the system is running the ping command, let’s see what happens if we string commands together. The first command will ping the localhost and the second will run the ID command.


The ID command ran successfully. Now I have some command execution.


I tried running a bash command next, but it just brought me back to the initial prompt. I would learn why later. Instead, I just dropped into the sqlite prompt by appending sqlite3 to the command string. The prompt got buried by the ping replies, so I had to press enter once they stopped to get the prompt to actually appear.


SQLite uses dot commands. By pressing .help I was able to learn how to interact with the database.


Here the commands showed me some helpful things … open a file and shell commands. The shell command we’ll use later. For now, we need to open the database.


The name of the database was given to us with the ping command. Once it’s open, looking at the table schema will show what fields are available to search.


Here I’m using a simple select statement to show everything that includes chan in the last name field. The first name Scott comes right up.


Now it’s time to use the .system command and claim the reward.


Just for kicks I used the system commands to get a shell. It works with sh but not with bash. Bash apparently has been setup to run the start menu. That’s why I couldn’t get it to work chaining bash to the end of the ping command.



Find the password and upload a file.

For this challenge, I had to upload a file to a SMB share that the user had forgotten the password.


Using PS to view processes and commands was a bit confusing because the full command was getting cut off.


Once I realized this, I pipped it to a file and then viewed it. I was able to identify the password and the upload string.


Using smbclient, I was able to access the remote share.


Once connected to the share, a simple PUT command placed the file where it needed to be.


With the report uploaded, the challenge completed.


AD Privilege Discovery

For this objective, I had to search Bloodhound for a kerberoastable user that would lead to domain admin. I’ve used Bloodhound before, so this was a piece of cake. Bloodhound came pre-installed on the VM they give you and fully loaded with the search in place. Honestly, that’s the hard part of using Bloodhound.


Bloodhound comes with a lot of helpful prebuilt queries. One of them just happens to be path to domain admin via kerberoastable user.


Even with this query, it leaves several options to explore. One of the hints suggested that RDP paths should be ignored. Luckily, there is a filter we can set.


Simply remove the check box on RDP and run the query again.


Now we have a very strait path and our user sticks right out.


Objective Complete!


Dev Oops

Ok this one was painful. Somewhere in this git repository is a password. Inside the kcconfmgmt is a hidden .git folder.


I then recursively grepped for password inside the .git folder.


This lead me to two potential files. Thanks to the hints, I know that the files I’m looking for are inside the objects directory and referenced by the fist two bytes.


If you didn’t grep for password, another way would have been to write a script to brute force every directory looking for the password. I started to do that, but then wised up.

Since there were only two files that showed up in our grep, it was easy enough to show both files. The command git show 60a2ffea7520ee980a5fc60177ff4d0633f2516b will display the password.


twinkletwinkletwinkle is the password.



HR Incident Response

This was interesting. The objective was to upload a malicious CSV to gain access to a file. The hint really helped to get the syntax right. First, I tried to create the csv in Excel, but that was awful. Excel kept trying to execute the code and then would throw reference errors that overwrote the code I just put in whenever I tried to save it. I then used notepad++ and was much happier.

In order to create the code, I had to know some file paths. Luckily the challenge itself provided the directory of the file I was after, but the website also displays it after uploading a file. The second file path can be found by adding things to the end of the URL which forces an error page to display.


With those two things, I could now copy the file I needed to the public page where I could download it. I’m not sure why the pipe | string has to be there but that’s the syntax I found in the example. The cell reference at the end is also important so don’t forget to add it.

They syntax is =cmd|’ /C copy c:\candidate_evaluation.docx c:\careerportal\resources\public\FILENAME’!A0


Once uploaded, you get a nice little message. This is also where you would find the directory for the original file had it not been given.


Then just navigate to the public page with the file name you chose, and the download will start.


With the document in hand, just read through the first candidate to find the evil organization Fancy Beaver




The Badged Door

Ok this one was crazy. I still don’t really understand it. The goal is to create a QR code badge that contains a SQL injection. They give you a sample badge, but that didn’t seem to help at all. I used an online decoder, but it just returned a random string. They do give you a site to create your own QR code and a link to OWASP for SQL injection. I couldn’t get any of those to work except that I did get the door to produce an error message. I had to use BurpSuite as a proxy to capture the error message. Otherwise it just scrolled by too fast to be of use.


This was the error message I received:

{“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}

Notice the word enabled? That proved to be very important.

Since I couldn’t get anything from OWASP to work, I used a list from Netsparker. The trick, as I mentioned before, was the word enabled in the error message. I thought that might be a good substitution for a TRUE statement and tried it in place of other statements like 1=1.


‘ or enabled# is the command that ultimately worked, but I don’t know why the # needed to be in there. I’m not even sure where this fits within the error message (maybe after the uid =’ ???). The best I figured is that the # comments out the rest of the statement leaving the enabled as the defining term but I still don’t really get it.

I just put that string into the QR code generator and created a png file.


Once uploaded, the access panel turns green and the control number is displayed. I assume that if you hadn’t completed the maze challenge the door would open. Since I did the maze first, the door was already open.



Winning the lottery


In this challenge, I had to win the lottery for one of the elves. I had no idea what I was doing, but a SANS write up (one of the hints) really walked me through it well.

Looking at the directory, gdb and the lottery file can be seen. Typing nm and the lottery file shows the names of the different function calls.



Winnerwinner sticks out pretty well. That’s probably the one we need.

First, I had to set a break point in the main program and then run the program. The program breaks (pauses) right after starting.

Next, I had to call the function. Using the command jump winnerwinner was all that was needed.


Once the function call was placed, the challenge was over.



Find the secret password in a GitHub repo

This objective can be completed by following one of the featured talks. Using a program call trufflehog, I searched the provided GitHub repository to produce the password. Now I probably should have just run the Windows installer, but I like having all of my tools in Kali. Though I followed the instructions exactly, truffleHog did not run at all. It turns out that it had a problem with loading git with python3. Python2, however, worked ok. It still through some errors at the end, but I got what I needed.

The first trick is to install truffleHog. Here are the basic steps:

  1. Clone the GitHub repo for truffleHog
  2. Use pip install truffleHog to get the dependencies

Even though the talk clearly pointed out Python3, I could not get that to work. In the end I used python –regex –entropy=True PATH/TO/GIT/REPO


The password showed up several times along with some other interesting things like RSA keys.


Yet another Die Hard reference and that ended the Holiday Hack for me this year. There were a few more terminal challenges in Santa’s secret room that I didn’t complete along with 3 objectives. They were more Blue Team/forensic focused which is not as interesting to me. They were also much harder to complete based on the difficulty rating.

Anyway, I hope you enjoyed the walkthrough such that it is. The Holiday Hacks are left up all year long (including past challenges). This is incredibly generous of Ed Skoudis and his team so please take advantage of it! The YouTube talks are also really well done, interesting, and super helpful in solving the challenges. So please check them out!


2 thoughts on “SANS Holiday Hack 2018 Kringlecon”

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s