In the following write up of the Holiday Hack Challenge 2018, you’ll find an enthralling take on a story we all know. Sure there is the mystery of , but there’s also the intrigue of , the thrill of unknown , and the allure of a 0day. You’ll also find an , the truth behind , and some of our own. Show
You’ll feel like you won a Golden Ticket with how easy it is to follow along. The sections along the side expand in an everlasting way, not unlike a Gobstopper, and what presents itself like a piece of gum; small and easily chewed through, but actually fills you up like a three course meal. We lay out the answers off the bat so you can chew into the Wonka Bar-like sweetness right away. We then move into the pre hack we went through, as if we were watching Nakatomi Plaza before attacking the hack. had us waiting for our chance to arrive at the Holiday Party and make our presence known. From there, we work our way through the story like Samantha Coleman before we drop into the juicy part of the challenge. You’ll see the come up next, with a detailed overview. Each one will give the goal and any necessary background needed to begin tackling it (including relevant hints and videos). Feel free to skip right to the Solution (including asciinema videos, that allow you to copy and paste) if you just want to know the answer. If you feel like learning more, we’ll then step you through our thought process in solving the problems, how the challenge was made, and sometimes, an alternate solution. The Summary for each challenge is also a good spot to skip to if you’re short on time as you’ll get a nice, brief idea of what we did. The following section works almost exactly the same, though leans more on pictures than gifs. After that is the . We managed to escalate privileges on the Snort system, which allowed us to pivot to snortsensor1. There we discovered a 0day in rssh, and exploited a race condition which allowed us to read arbitrary files as root. We also thought it might be useful to show our entire process, how we worked efficiently as a small , maybe our ideas will help others. You might also have better ideas and can share your techniques with us, we love to learn and improve! Some artifacts will be left on our Github as they fit better there and we don’t want to overwhelm you any more than required. See how many easter eggs you can find between this site and the Github! Happy reading, The ESnet Security Team –Dop, Sam and Vlad Answers
ReconnaisanceAny penetration test starts with reconnaisance on your target. In a typical Capture the Flag (CTF) or other hacking challenge, you're given all this information up-front. However, this step shouldn't be skipped, as it can make the challenge easier. GoalIdentify domain names, hostnames, IP addresses, etc. Reverse WhoisFirst, we'll try to identify the domain names being used. Last year, the domain was northpolechristmastown.com. Every domain name has some ownership information associated with it. We can query this information via a ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 96 lookup: $ whois northpolechristmastown.com ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... northpolechristmastown.com was registered in October 2017, and the organization is listed as Counter Hack. Using this information, we can also do a "reverse whois" search, where we can see all domains that a given organization is listed as the registrant for: Figure 1: A reverse whois search for Counter Hack kringlecon.com was registered in May, and in July it was opened up for participants to begin signing up, and poking around (more on that below, in "LineCon"). erohetfanu.com and kringlecastle.com were registered in October. LineCon gave us a hint about the castle. erohetfanu.com seems obfuscated. Domain Name System (DNS)Armed with the 3 domain names, we'll see what additional information we can glean. DNS attempts to convert between hostnames and IP addresses. dig +noall +answer ANY kringlecon.com kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" There's a lot of information returned, but we can learn thatkringlecon.com resolves to the IP address 104.196.14.143, that DNS services are provided by domaincontrol.com, and that e-mail services are provided through Google Mail. These are "indicators," and can be used to track how a certain actor likes to operate. Domains and IP addresses can change, but tactics often stay the same. Whois also works on IP addresses, so we can see the ownership of the IP address returned: ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... The IP address is owned by Google, and the name of the network implies that it's part of Google's Cloud offerings. Some more digging reveals that northpolechristmastown.com was set up the same way. We can perform similar queries on the other two domains, and we find out the following information: Domain Purpose Domain Registration Date Domain Registry DNS Provider Mail Provider IP Address IP Owner northpolechristmastown.com Last Year's Domain October 19th, 2017 GoDaddy.com domaincontrol.com Google n/a Hosts hosted on Google Cloud kringlecon.com The Kringle Conference May 25th, 2018 GoDaddy.com domaincontrol.com Google 104.196.14.143 Google Cloud kringlecastle.com Unknown: Kringle's Castle? October 12th, 2018 GoDaddy.com domaincontrol.com Google n/a Unknown erohetfanu.com Unknown: Something hidden? October 16th, 2018 GoDaddy.com domaincontrol.com Google 104.196.126.19 Google Cloud Certificate Transparency LogsAfter determining the domains for this year's Holiday Hack, we'd like to figure out what systems there are in those domains. A good way of doing this is via Certificate Transparency logs – public logs which serve as an audit mechanism for SSL certificates which are issued, in order to detect mistaken or malicious certificates. There are several free services which allow you to query these logs. I like using VirusTotal.com: Figure 2: Certificates for kringlecastle.com Figure 3: Certificates for kringlecon.com MonitoringSince we found several hosts that use SSL certificates, it's a pretty safe bet that they'll be web servers. We can set up monitoring to poll some of these systems, so that we'll know as soon as the contest goes live. Figure 4: Let the games begin… SummaryIP Address Hostname 35.185.2.206 scanomatic.kringlecastle.com hohohodaddy.kringlecastle.com 35.185.76.157 docker2018-qa.kringlecon.com 35.185.89.85 git.kringlecastle.com 35.185.103.210 pianolockn.kringlecastle.com 35.185.104.53 docker.kringlecon.com 35.190.187.47 packalyzer.kringlecastle.com 35.196.29.176 doorpasscode.kringlecastle.com cfp.kringlecastle.com pianolock.kringlecastle.com 35.196.162.157 narrative.kringlecon.com 35.229.118.54 careers.kringlecastle.com 35.237.171.66 vents.kringlecastle.com 35.243.215.176 status.kringlecon.com 104.196.14.143 www.kringlecon.com kringlecon.com api.kringlecon.com rsvp.kringlecon.com 104.196.66.61 snortsensor1.kringlecastle.com LineConGoalRegister for the conference, and look for any secrets Finding a hidden pathWhile zooming out the browser window, something appeared off to the right: Figure 5: A secret snow path Upon visiting the secret path, we could see a castle in the distance. Figure 6: Kringle Castle? Client-side tricks to make secrets stand outTo make it easier to see hidden paths, we can use this JavaScript snippet in our browser's Javascript console. To access the console, visit ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 97 → ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 98 → ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 99 in Firefox, and dig +noall +answer ANY kringlecon.com 00 → dig +noall +answer ANY kringlecon.com 01 → dig +noall +answer ANY kringlecon.com 02 in Chrome. var i; var lava = document.getElementsByClassName('lava'); for ( i = 0; i < lava.length; i++ )
The game uses a special HTML class called "lava" for any element which is "walkable." Our snippet finds all elements which have that class, and then sets their background color to pink.Figure 7: Making everything pink in the Console Figure 8: Pink paths! Game Internals: WebSocket MessagesUsing the same Developer Tools, we can start reverse engineering how the game works. As we'll discover, the game relies on WebSocket messages. Firefox currently lacks the ability to view these messages, so it's recommended to use Chrome for this portion. This time, we'll use the dig +noall +answer ANY kringlecon.com 03 tab in the Developer Tools. Network traffic from your browser will be listed here. If this tab wasn't open when the traffic was initiated, nothing will show up, so it's best to have this tab open and then refresh the page, to ensure we see everything. Once we login go the game, we can filter on WebSocket connections by clicking on the dig +noall +answer ANY kringlecon.com 04 filter, and then view the dig +noall +answer ANY kringlecon.com 05 tab to see the individual messages: Figure 9: WebSocket messages Messages in green are messages that we sent to the server, and the other messages are the replies. By interacting with the game and observing which messages are sent/received, we can slowly learn how to interact with the game without a browser. Using the new-found knowledge about WebSocket messages, we can create a simple client for the game: #!/usr/bin/env python3 import asyncio import simplejson as json import time import websockets async def hello(): asyncio.get_event_loop().run_until_complete(hello())Game Internals: Avatar DNAAs we explored LineCon, one feature that drew our attention was that the appearance of each avatar was encoded as DNA. Using the standard DNA sequence letters (A, T, C, G), pairs of letters would encode the numbers 0-3: dig +noall +answer ANY kringlecon.com 06. A neat detail is the fact that these pairs match DNA nucleic-acid pairs (i.e. in the double-helix, A is complementary to T, and C with G). The avatar is encoded as a 120 character sequence, such as dig +noall +answer ANY kringlecon.com 07. Once we convert the pairs back to numbers, we get a 60 digit sequence: dig +noall +answer ANY kringlecon.com 08. Inspecting the Javascript code, we can see how this sequence gets translated back to an avatar: C = [ { name: "size", size: 4 }, { name: "legs", size: 8 }, { name: "hue", size: 8 }, { name: "torso", size: 8 }, { name: "head", size: 8 }, { name: "saturation", size: 4 }, { name: "mouth", size: 8 }, { name: "eyes", size: 8 }, { name: "brightness", size: 4 }]; Returning to our example, we can convert the sequence to these fields. A quick way to convert the numerical sequences is using Python's dig +noall +answer ANY kringlecon.com 09 function with a base of 4: dig +noall +answer ANY kringlecon.com 10. Offset Size Sequence Name Value 0 4 0001 size 1 4 8 00000001 legs 1 12 8 00003123 hue 219 20 8 00000011 torso 5 28 8 00000012 head 6 36 4 0001 saturation 1 40 8 00000020 mouth 8 48 8 00000012 eyes 6 56 4 0003 brightness 3 We can verify our decoding by searching for the names of the color schemes in the Javascript. In the example sequence above, the avatar selection modal used "Flimsy Cappuccino," which we can find defined as: dig +noall +answer ANY kringlecon.com 11. An exact match! Another cool mini-feature is that if you open up the dig +noall +answer ANY kringlecon.com 12 tab of your Developer Tools, you can see representations of the DNA sequence: Figure 10: DNA Sequences in the Console tab The color scheme is: dig +noall +answer ANY kringlecon.com 13. So, in the example above, the top line starts dig +noall +answer ANY kringlecon.com 14, and the bottom line is the complementary sequence dig +noall +answer ANY kringlecon.com 15. First Finding: Avatar vulnerabilityIn the dig +noall +answer ANY kringlecon.com 03 tab of the Developer Tools, we can see other resources that are being loaded by the game. One of these is an image, called dig +noall +answer ANY kringlecon.com 17: Figure 11: egg.png It seems like the game uses this when it can't load an image: render() { const {dna: e, version: t} = this.props; if (au.a.validateSequence(e))
While investigating this mysterious image, it was discovered that we could use our WebSocket client to set an invalid avatar for ourselves.Doing this caused an exception which would render our game completely black and inoperable. Worse yet, our avatar was being loaded by other players in the game, and it would cause their screens to go black as well. We quickly set our avatar back to its original state, and reported this issue to the SANS Counter Hack team. They quickly issued a fix for it. SummaryLineCon was a great preview! We prepped some in-browser tricks for making paths or other interesting elements stand out. We wrote a simple Python script which allowed us to interact directly with the game. And we discovered and reported our first vulnerability. KringleConMapFirst, we walk around, familiarizing ourselves with the surroundings: StoryAs you walk through the gates, a familiar red-suited holiday figure warmly welcomes all of his special visitors to KringleCon. Your narrative begins when you stop to chat with Santa and he shares the preceding. Continuing into the castle, you begin to poke around. Once you complete the door passcode challenge and receive the dig +noall +answer ANY kringlecon.com 18 token, you start to notice some suspicious behavior: Suddenly, all elves in the castle start looking very nervous. You can overhear some of them talking with worry in their voices. The toy soldiers, who were always gruff, now seem especially determined as they lock all the exterior entrances to the building and barricade all the doors. No one can get out! And the toy soldiers' grunts take on an increasingly sinister tone. You carry on and help out by finding some secrets in a git repository. This unlocks the dig +noall +answer ANY kringlecon.com 19 token. While receiving that, you begin to see something disturbing, the toy soldiers act even more aggressively. They are searching for something – something very special inside of Santa’s castle – and they will stop at NOTHING until they find it. Hans seems to be directing their activities. What could they be after? In the main lobby on the bottom floor of Santa's castle, Hans calls everyone around to deliver a speech. Make sure you visit Hans to hear his speech." What could he have to say? Ladies and Gentlemen… All of a sudden, all of the toy soldiers are similarly taken by Die Hard references: Grunt! As you keep digging for secrets trying to figure out just what’s going on here, you break into the domain and get the dig +noall +answer ANY kringlecon.com 20 token. This reveals another, even more sinister sight: The toy soldiers continue behaving very rudely, grunting orders to the guests and to each other in vaguely Germanic phrases. Suddenly, one of the toy soldiers appears wearing a grey sweatshirt that has written on it in red pen, "NOW I HAVE A ZERO-DAY. HO-HO-HO." The elves are panicking: Oh my! Santa’s castle… it’s under siege! That is worrisome, but even more so when you start to hear, "A rumor spreads among the elves that Alabaster has lost his badge. Several elves say, 'What do you think someone could do with that?'" Quickly trying to help out and save the castle from attack, you find an example badge used to beat the qrcode Scan-O-Matic objective. Finding a way to trick your way through this badge reader to earn your dig +noall +answer ANY kringlecon.com 21 token, you hear, "Congratulations! You have gained access to Santa's secret room." This is great, but then you quickly learn that, "Hans has started monologuing again. Please visit him in Santa's lobby for a status update." Our captor tells us: So, you’ve figured out my plan – it’s not about freeing those prisoners. As you go listen to Hans, you notice a vent cover that seems… not quite right. As you wonder where this maze of a vent system could take you, you eventually find your way out. This unlocks the dig +noall +answer ANY kringlecon.com 22 token and you find yourself in a new room. "Great work! You have blocked access to Santa's treasure… for now. Please visit Hans in Santa's Secret Room for an update." As you approach Hans, "…suddenly, Hans slips and falls into a snowbank [editor’s note: that is strangely located inside this secret, third story room hidden in a castle]. His nefarious plan thwarted, he's now just cold and wet." Things are starting to look up, "But Santa still has more questions for you to solve!" You need to find Santa to see if you can answer his questions. Your eye lands on a door you couldn’t have seen before. It won’t open and has some strange musical lock on it. After struggling with it, you finally defeat the lock and collect the dig +noall +answer ANY kringlecon.com 23 token. With this, you are able to enter this final hidden room and talk to Santa. Congrats! You have solved the hardest challenge! Please visit Santa and Hans inside Santa's Secret Room for an update on your amazing accomplishment! The elves say "YAY! You won!", and Hans and the now hat-less toy soldiers join in on congratulating us. Santa explains: 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! Walking back out of these once secret rooms, as you leave the castle and hear Jason the plant's lament of psmitty, you realize that instead of snaking through the arduous, confusing maze of vents, you could have won the dig +noall +answer ANY kringlecon.com 24 token and gotten the same access, and heard the same information. Oh well, you saved the day, and what action hero are you really if you don’t come out looking bloodied and dirtied like this at the end? Bonus: Crawling through the VentsNow I know what a TV dinner feels like. —John McClane Solution 1: Manually Crafted Vent MazeOn the left side of the lobby in Santa's Castle is a large air vent that's large enough to crawl through, upon entering it's soon clear that this is a maze. This can be solved manually by carefully crafting a map during an hour long meeting (not that anyone would do that). Solution 2: Recover Map from Git RepositoryIn , we manage to recover a map from the GitLab server. Solution 3: Automated Maze SolverPerhaps the most fun way to solve the maze is programmatically. To move, your browser sends a request like: https://vents.kringlecastle.com/move?heading=w&mazex=23&mazey=19&mazef=1&playeraction=forward&locationkey=ba49a09644aa8fa7fb0082e935f46521&resourceid=inigomontoya Breaking that out to be more clear: Field Value Meaning dig +noall +answer ANY kringlecon.com 25 dig +noall +answer ANY kringlecon.com 26 Current heading: n=north, w=west, s=south, e=east dig +noall +answer ANY kringlecon.com 27 dig +noall +answer ANY kringlecon.com 28 Current X coordinate dig +noall +answer ANY kringlecon.com 29 dig +noall +answer ANY kringlecon.com 30 Current Y coordinate dig +noall +answer ANY kringlecon.com 31 dig +noall +answer ANY kringlecon.com 32 Current maze floor dig +noall +answer ANY kringlecon.com 33 dig +noall +answer ANY kringlecon.com 34 Potentially valid options: forward, backward, up, down dig +noall +answer ANY kringlecon.com 35 dig +noall +answer ANY kringlecon.com 36 The unique location id key for where you currently are dig +noall +answer ANY kringlecon.com 37 dig +noall +answer ANY kringlecon.com 38 Never changes, clearly a reference to The Princess Bride It's important to note that every location on the vent map has a unique locationkey. So we can't just sent a request for every possible x,y,f position without traversing the maze and learning the location keys. Assuming you send an action that moves you to a valid location, the server response will include a number of variables outlining your current state: window.onload = function() { document.getElementById("top").style.visibility="hidden"; document.getElementById("bottom").style.visibility="hidden"; document.getElementById("arrow-up").style.visibility="hidden"; document.getElementById("arrow-down").style.visibility="hidden"; //next section depends on player state document.getElementById("mazeform").elements.namedItem("heading").value = "w"; document.getElementById("mazeform").elements.namedItem("mazex").value = "22"; document.getElementById("mazeform").elements.namedItem("mazey").value = "19"; document.getElementById("mazeform").elements.namedItem("mazef").value = "1"; document.getElementById("mazeform").elements.namedItem("locationkey").value = "07edf09b26a307b9fe4f40bedffe76ed"; document.getElementById("mazeform").elements.namedItem("resourceid").value = "inigomontoya"; document.getElementById("wallform").elements.namedItem("northwall").value = "True"; document.getElementById("wallform").elements.namedItem("southwall").value = "True"; document.getElementById("wallform").elements.namedItem("eastwall").value = "False"; document.getElementById("wallform").elements.namedItem("westwall").value = "False"; wallcheck(); //render correct walls once state is known }; The important parts here are the True/False value of the four walls, which gives us valid headings, and the locationkey for our new coordinates. The size of the response is generally within a few bytes (3509-3514) which can be used to help find locations that aren't like the others, like the shaft to the second floor and the exit. In these cases the response size changes as well as the arrow-up/arrow-down elements may be visible instead of hidden. A Python script was written to automatically solve the maze by always going right. It generates a map with the following final output. 'S' is the starting location, 'U' and 'D' represent up and down possibilities, and 'X' marks the current location: the exit. ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 0 ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 1 Exiting the vent maze you end up in Santa's Secret Room. The other way to get there is through the . Cranberry Pi TerminalsEssential EditorGoalBackground
I'm glad you're here, I'm the target of a terrible trick. Pepper says his editor is the best, but I don't understand why. He's forcing me to learn vi. He gave me a link, I'm supposed to learn the basics. Can you assist me with one of the simple cases? Badge HintOnce Bushy tells us the above, we get the following hint: Indiana University Vi Tutorials Relevant KringleCon Videos NoneIntroWhen we login, we're presented with the following screen: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 2 SolutionThis can be easily solved with the hint from Bushy Evergreen. As the page says, to exit, hit dig +noall +answer ANY kringlecon.com 39, then type dig +noall +answer ANY kringlecon.com 40. Escape ensures that dig +noall +answer ANY kringlecon.com 41 is in command mode, dig +noall +answer ANY kringlecon.com 42 is the command for quit, and the exclamation point instructs it to not warn us about any unsaved changes. Game Internals: How it was madeThe Docker terminals drop us into a terminal with our Bash shell running. Normally when Bash is running, it will read some configuration files on startup, including dig +noall +answer ANY kringlecon.com 43 in the user's home directory. Inspecting our dig +noall +answer ANY kringlecon.com 43, we see the following two lines at the bottom: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 3 When Bash starts, it runs dig +noall +answer ANY kringlecon.com 45, opening the file dig +noall +answer ANY kringlecon.com 46. Whenever dig +noall +answer ANY kringlecon.com 45 exits, it runs dig +noall +answer ANY kringlecon.com 48. Using to reverse engineer binaries, we can recover this script. The main logic of the script is: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 4 The dig +noall +answer ANY kringlecon.com 49 function will actually make sure that no process named dig +noall +answer ANY kringlecon.com 41 is running. So, even if you had called dig +noall +answer ANY kringlecon.com 51 from within dig +noall +answer ANY kringlecon.com 45, you would not receive credit. ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 5 The final noteworthy portion of this script is calculating the HMAC which is sent to the game server to receive credit for completion of this challenge. The HMAC algorithm is discussed in detail in However, the source code does reveal the HMAC key: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 6 SummaryWe escaped dig +noall +answer ANY kringlecon.com 45 by giving the quit command. We then showed how dig +noall +answer ANY kringlecon.com 45 was being started upon login, and how we received credit for completing it. We successfully reverse-engineered the dig +noall +answer ANY kringlecon.com 51 binary, and recoved the HMAC key, so now we can receive credit without ever solving the challenge at all. GoalTo solve this challenge, determine the new worker's first name and submit to runtoanswer. Background
I need to make a nametag for an employee, but I can't remember his first name. Maybe you can figure it out using this Cranberry Pi terminal? The Santa's Castle Onboarding System? I think it's written in PowerShell, if I'm not mistaken. PowerShell itself can be tricky when handling user input. Special characters such as & and ; can be used to inject commands. I think that system is one of Alabaster's creations. He's a little … obsessed with SQLite database storage. I don't know much about SQLite, just the .dump command. Badge Hint Relevant KringleCon Videos NoneIntroWhen we launch the Cranberry Pi, we see: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 7 SolutionGiven the hints, it sounds like our penultimate step is to dump the data from SQLite, and look for someone named Chan. The Powershell menu presents us with three options: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 8 Maybe we're on a quitting streak after the first terminal, but we start by trying to get to a command prompt directly, and hit dig +noall +answer ANY kringlecon.com 42 to quit. Unfortunately, that hangs the terminal, and we can't type anything else. Reloading, and trying again, we do the onboard process. Minty mentioned trying to give Powershell tricky characters, like dig +noall +answer ANY kringlecon.com 57 and dig +noall +answer ANY kringlecon.com 58: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 9 No luck. Once we hit enter, we're back in the main menu. We'll move on to the last unexplored option, verifying the system. dig +noall +answer ANY kringlecon.com 0 So, the verification pings the server you give it, and then checks the dig +noall +answer ANY kringlecon.com 59 file. Once again, let's try giving it some potentially troublesome characters: dig +noall +answer ANY kringlecon.com 1 Submitting dig +noall +answer ANY kringlecon.com 58 and dig +noall +answer ANY kringlecon.com 57 behave the same – we see the usage information for ping. It's the same output we would see if we called ping without any arguments. One of the pages that Minty linked us to said that we can use the dig +noall +answer ANY kringlecon.com 58 operator in Powershell to call other commands. Let's try it: dig +noall +answer ANY kringlecon.com 2 It's a bit hard to see in the output, but we have a different line from the time before: dig +noall +answer ANY kringlecon.com 63. This would be the output from our dig +noall +answer ANY kringlecon.com 64 command. At this point, we can exit the Powershell menu and run our own commands. Now we can dump the SQLite database, using the tips in the second link that Minty provided: dig +noall +answer ANY kringlecon.com 3 Success! But it's hard to find Chan in all of that. Let's see if we can pass our output to the dig +noall +answer ANY kringlecon.com 65 command, returning only lines that contain "Chan." dig +noall +answer ANY kringlecon.com 4 Great. We now have one final hurdle – we need to call dig +noall +answer ANY kringlecon.com 66 and answer the question. The same technique works there too: dig +noall +answer ANY kringlecon.com 5 Answer: Scott This was classic command injection. There were a few other techniques that could've worked here, including using a semicolon instead of the ampersand (e.g. dig +noall +answer ANY kringlecon.com 67). We also discovered that the dig +noall +answer ANY kringlecon.com 68 script had an unlisted option: dig +noall +answer ANY kringlecon.com 6 Hitting option 9 drops us into a Powershell shell: dig +noall +answer ANY kringlecon.com 7 SummaryThe onboarding Powershell script was vulnerable to command injection. By running a command to dump the database, we found our guy, and were able to successfully call dig +noall +answer ANY kringlecon.com 66. Furthermore, by inspecting the Powershell source code, we discovered a hidden backdoor in the menu. Vim ForensicELFificationGoalFind the first name of the elf of whom a love poem was written. Background
Any chance you can help me with an investigation? Elf Resources assigned me to look into a case, but it seems to require digital forensic skills. Do you know anything about Linux terminal editors and digital traces they leave behind? Apparently editors can leave traces of data behind, but where and how escapes me! Badge HintTangle also suggests the following site: Forensic Relevance of Vim Artifacts Relevant KringleCon Videos NoneIntroWhen we open the terminal, we see: dig +noall +answer ANY kringlecon.com 8 SolutionThis one seems pretty straightforward. We have a single hint, and the hint only discusses the importance of the dig +noall +answer ANY kringlecon.com 70 file. Let's take a look at that, but before we do anything, we want to do two things: Look at the metadata, and copy the file so that we don't accidentally modify it (by opening vim, say): dig +noall +answer ANY kringlecon.com 9 To start, we need to figure out what love poem was written. The "Forensic Relevance of Vim Artifacts" web page has this to say: File marks are among the last items in most .viminfo files and essentially consist of a list of files that have been opened with Vim. A ‘mark’ allows a user to record their location in a file they were editing, like a bookmark of sorts, which they can jump back to. On Linux systems, the “History of marks within files” section of .viminfo records the last 20 files that were opened using the Vim editor, along with their file path (relative to the user) and epoch timestamp. As we view the dig +noall +answer ANY kringlecon.com 71 file, it's fairly obvious that only one file was recently opened: kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 0 Opening up dig +noall +answer ANY kringlecon.com 72: Once upon a sleigh so weary, Morcel scrubbed the grime so dreary, Shining many a beautiful sleighbell bearing cheer and sound so pure– There he cleaned them, nearly napping, suddenly there came a tapping, As of someone gently rapping, rapping at the sleigh house door. "'Tis some caroler," he muttered, "tapping at my sleigh house door– Only this and nothing more." Then, continued with more vigor, came the sound he didn't figure, Could belong to one so lovely, walking 'bout the North Pole grounds. But the truth is, she WAS knocking, 'cause with him she would be talking, Off with fingers interlocking, strolling out with love newfound? Gazing into eyes so deeply, caring not who sees their rounds. Oh, 'twould make his heart resound! Hurried, he, to greet the maiden, dropping rag and brush - unlaiden. Floating over, more than walking, moving toward the sound still knocking, Pausing at the elf-length mirror, checked himself to study clearer, Fixing hair and looking nearer, what a hunky elf - not shocking! Peering through the peephole smiling, reaching forward and unlocking: NEVERMORE in tinsel stocking! Greeting her with smile dashing, pearly-white incisors flashing, Telling jokes to keep her laughing, soaring high upon the tidings, Of good fortune fates had borne him. Offered her his dexter forelimb, Never was his future less dim! Should he now consider gliding– No - they shouldn't but consider taking flight in sleigh and riding Up above the Pole abiding? Smile, she did, when he suggested that their future surely rested, Up in flight above their cohort flying high like ne'er before! So he harnessed two young reindeer, bold and fresh and bearing no fear. In they jumped and seated so near, off they flew - broke through the door! Up and up climbed team and humor, Morcel being so adored, By his lovely NEVERMORE! -Morcel Nougat dig +noall +answer ANY kringlecon.com 73 seems like an odd name for an elf, and submitting this to dig +noall +answer ANY kringlecon.com 66 yields: kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 1 Returning to our dig +noall +answer ANY kringlecon.com 70 file, we see: kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 2 It seems like our elf did a find-and-replace on "Elinore," replacing all instances with "NEVERMORE." kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 3 Answer: Elinore We actually see a bit more history in the dig +noall +answer ANY kringlecon.com 70 file: kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 4 We can use dig +noall +answer ANY kringlecon.com 77 to reverse some of these changes. Though, if we replace "tenor" with "sound," to undo the earliest change, we have no way of knowing which instances of "tenor" were there originally: dig +noall +answer ANY kringlecon.com 78 And we recover the following poem: Once upon a sleigh so weary, Morcel scrubbed the grime so dreary, Shining many a beautiful sleighbell bearing cheer and sound so pure– There he cleaned them, nearly napping, suddenly there came a tapping, As of someone gently rapping, rapping at the sleigh house door. "'Tis some caroler," he muttered, "tapping at my sleigh house door– Only this and nothing more." Then, continued with more vigor, came the sound he didn't figure, Could belong to one so lovely, walking 'bout the North Pole grounds. But the truth is, she WAS knocking, 'cause with him she would be talking, Off with fingers interlocking, strolling out with love newfound? Gazing into eyes so deeply, caring not who sees their rounds. Oh, 'twould make his heart resound! Hurried, he, to greet the maiden, dropping rag and brush - unlaiden. Floating over, more than walking, moving toward the sound still knocking, Pausing at the elf-length mirror, checked himself to study clearer, Fixing hair and studied nearer, what a hunky elf - not shocking! Peering through the peephole smiling, reaching forward and unlocking: Elinore in tinsel stocking! Greeting her with smile dashing, pearly-white incisors flashing, Telling jokes to keep her laughing, soaring high upon the tidings, Of good fortune God had borne him. Offered her his dexter forelimb, Never was his future less dim! Should he now consider gliding– No - they shouldn't but consider taking flight in sleigh and riding Up above the Pole abiding? Smile, she did, when he suggested that their future surely rested, Up in flight above their cohort flying high like ne'er before! So he harnessed two young reindeer, bold and fresh and bearing no fear. In they jumped and seated so near, off they flew - broke through the door! Up and up climbed team and humor, Morcel being so adored, By his lovely Elinore! -Morcel Nougat SummaryFor this terminal, the hint was a big help. By looking at the dig +noall +answer ANY kringlecon.com 70 file, we could reconstruct the changes made to the file, and learned that someone had replaced Elinore's name with NEVERMORE. Samba Mucking ReportGoalComplete this challenge by uploading the elf's report.txt file to the samba share at dig +noall +answer ANY kringlecon.com 80. Background
Golly, passwords may be the end of all of us. Good guys can't remember them, and bad guess can guess them! I've got to upload my chore report to my manager's inbox, but I can't remember my password. Still, with all the automated tasks we use, I'll bet there's a way to find it in memory… Badge HintTalking to Wunorse unlocks the following hint in our badge: Keeping Command Line Passwords Out of PS Relevant KringleCon Videos NoneIntroOpening the terminal, we're greeted with: kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 5 SolutionThe hint links us to a page that discusses risks when passwords are passed on the command line, such as being able to view it with the process status command dig +noall +answer ANY kringlecon.com 81. Let's try it: kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 6 Not a whole lot of information. By default, dig +noall +answer ANY kringlecon.com 81 only shows us a couple of fields, and only for processes we own (and our associated with our current terminal). We can read dig +noall +answer ANY kringlecon.com 81's manual page with dig +noall +answer ANY kringlecon.com 84, which has the following snippet: kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 7 Let's try it: kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 8 That looks better. We can see there's a dig +noall +answer ANY kringlecon.com 85 process, and a dig +noall +answer ANY kringlecon.com 86 process. The dig +noall +answer ANY kringlecon.com 87 process is particularly interesting, as it seems to have a bunch of command-line arguments. However, by default, dig +noall +answer ANY kringlecon.com 81 truncates them to the width of our terminal. Simple solution: zoom out our browser window. kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 9 The end of the command is dig +noall +answer ANY kringlecon.com 89. A less hacky solution is to use more dig +noall +answer ANY kringlecon.com 81 arguments to see the entire command: OUTPUT MODIFIERS … –cols n Set screen width. ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 0 At this point, we suspect that "directreindeerflatterystable" is our password. Now we need to figure out how to copy it to the dig +noall +answer ANY kringlecon.com 80 SMB share. Some Googling points us to the dig +noall +answer ANY kringlecon.com 92 command: ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 1 dig +noall +answer ANY kringlecon.com 92 has a lot of options, but as we parse the usage information, it seems like the snippet recoverd from the end of dig +noall +answer ANY kringlecon.com 85 should just work: ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 2 Uploading the report is as simple as: ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 3 Once we do so, the following happens: ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 4 SummaryWe ran dig +noall +answer ANY kringlecon.com 81, with some extra arguments to see all of the command-line arguments, and recovered the username and password for the SMB share. We then copied the report to the share with dig +noall +answer ANY kringlecon.com 92. HTTP2 CURLing MasterGoalComplete this challenge by submitting the right HTTP request to the server at http://localhost:8080/ to get the candy striper started again. Background
Sorry to vent, but that brother of mine did something strange. The trigger to restart the Candy Striper is apparently an arcane HTTP call or 2. I sometimes wonder if all IT folk do strange things with their home networks… Badge HintHolly links us to: HTTP/2.0 Basics Relevant KringleCon VideosIntroOnce we open the terminal, we see a curling stone and the following message: ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 5 SolutionThe terminal tells us to check out dig +noall +answer ANY kringlecon.com 97, so we do that. The following comment catches our attention: ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 6 The web server has HTTP2 enabled. We read the page that Holly linked us to, but what we're really looking for is how to use the dig +noall +answer ANY kringlecon.com 98 command with HTTP2. Chris Elgee's video gives us the following command, which we've adapted for our server running on localhost, port 8080: ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 7 Well, that didn't work. Let's try to find out more about the dig +noall +answer ANY kringlecon.com 99 flag. We can run kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 00, and see: ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 8 Let's try doing it without the HTTP/1.1 upgrade: ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 9 Ok! Now, instead of sending an empty GET, we need to send a POST with the right paramter. Once again, we'll return to the help output: var i; var lava = document.getElementsByClassName('lava'); for ( i = 0; i < lava.length; i++ )
0Easy enough: var i; var lava = document.getElementsByClassName('lava'); for ( i = 0; i < lava.length; i++ )
1Alternative solutionThis system had some interesting commands in the bash history: var i; var lava = document.getElementsByClassName('lava'); for ( i = 0; i < lava.length; i++ )
2SummaryWe found a comment from Bushy in the kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 01 config, which told us that HTTP2 was enabled on this system. Using a combination of Chris Elgee's talk and the curl help output, we figured out the correct parameters to have curl be able to send the request as HTTP2 (without trying to HTTP/1.1 and doing an upgrade to HTTP2 first). Then, the output from the page told us that we needed to submit a POST request, with kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 02. Windows Yule Log AnalysisGoalSubmit the compromised webmail username to runtoanswer to complete this challenge. Background
We fear that they were successful in accessing one of our Elf Web Access accounts, but we don't know which one. Parsing through .evtx files can be tricky, but there's a Python script that can help you convert it into XML for easier grep'ing. Badge HintPepper promptly points password penetration people to Password Spraying. Relevant KringleCon VideosIntroWhen we start the Cranberry Pi, we get the following message: var i; var lava = document.getElementsByClassName('lava'); for ( i = 0; i < lava.length; i++ )
3Checking our home directory, we see: var i; var lava = document.getElementsByClassName('lava'); for ( i = 0; i < lava.length; i++ )
4kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 03 must be the Python script Pepper was referring to, for converting kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 04 to XML. SolutionFirst, we figure out how to run kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 03: var i; var lava = document.getElementsByClassName('lava'); for ( i = 0; i < lava.length; i++ )
5Next, we'll save the XML version to a file, so we're not waiting on the Python script to re-parse the events each time. var i; var lava = document.getElementsByClassName('lava'); for ( i = 0; i < lava.length; i++ )
6At this point, we follow along in Beau's video. We learn that password spraying involves trying a single password across a large number of accounts. That way, account lockout polices don't trigger. He also mentions that a good way to try this is via e-mail servers like OWA, using his tool, MailSniper. Given that Pepper's hint is about MailSniper, we suspect that this is likely the vector being used. Taking a closer look at our logs, we see events such as: var i; var lava = document.getElementsByClassName('lava'); for ( i = 0; i < lava.length; i++ )
7Let's start by seeing which systems we have log data from. To do this, we'll use the dig +noall +answer ANY kringlecon.com 65 command, to only return lines from the file which match our search term, and then we'll use the pipe ( kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all"
kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 08. Finally, we'll pass the sorted lines to the kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 09 ("unique") command, which will only print a line if it's different from the line above it. kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 08 and kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 09 are often used together in this way, since kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 09 only compares the line to the line above it when deciding whether or not to print it. var i; var lava = document.getElementsByClassName('lava'); for ( i = 0; i < lava.length; i++ )
8We only have logs from a single system, which we suspect to be an Exchange Server 2016 from its hostname. Let's see what events we have: var i; var lava = document.getElementsByClassName('lava'); for ( i = 0; i < lava.length; i++ )
9A bit of research gives us names to go with these EventIDs: Event ID Event Name 4608 Windows is starting up 4624 An account was successfully logged on 4625 An account failed to log on 4647 User initiated logoff 4688 A new process has been created 4724 An attempt was made to reset an accounts password 4738 A user account was changed 4768 A Kerberos authentication ticket (TGT) was requested 4769 A Kerberos service ticket was requested 4776 The domain controller attempted to validate the credentials for an account 4799 A security-enabled local group membership was enumerated 4826 Boot Configuration Data loaded 4902 The Per-user audit policy table was created 4904 An attempt was made to register a security event source 5024 The Windows Firewall Service has started successfully 5033 The Windows Firewall Driver has started successfully 5059 Key migration operation 4624 and 4625 seem interesting. Let's update our previous command to include the number of occurences of each event by using kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 13: #!/usr/bin/env python3 import asyncio import simplejson as json import time import websockets async def hello(): asyncio.get_event_loop().run_until_complete(hello())0 So, we've had 756 accounts successful logon attempts, and 212 failed ones. #!/usr/bin/env python3 import asyncio import simplejson as json import time import websockets async def hello(): asyncio.get_event_loop().run_until_complete(hello())1 At this point, there's a few ways we can proceed to analyze the logs. However, parsing XML data becomes tricky with the standard *NIX text-processing tools ( dig +noall +answer ANY kringlecon.com 65, dig +noall +answer ANY kringlecon.com 77, kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 16, etc.). Instead, we'll write up a Python script: #!/usr/bin/env python3 import asyncio import simplejson as json import time import websockets async def hello(): asyncio.get_event_loop().run_until_complete(hello())2 When we run the script, we get the authentication result, and the username. The last lines printed are along the lines of: #!/usr/bin/env python3 import asyncio import simplejson as json import time import websockets async def hello(): asyncio.get_event_loop().run_until_complete(hello())3 We can use dig +noall +answer ANY kringlecon.com 65 to ignore the mailbox. This time, we'll use the kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 18 flag: kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 19 #!/usr/bin/env python3 import asyncio import simplejson as json import time import websockets async def hello(): asyncio.get_event_loop().run_until_complete(hello())4 This does look like a password spraying attack. We see a large number of failures, going alphabetically. Interestingly, it seems like SugarPlum Mary's account name is misspelled, leading more credence to the theory that the attacker is going off of a list of usernames. After the failures, we see successful logins for Minty and Wunorse. To get a better sense of what's going on, we'll update our script to add the timestamp and IP address as well: #!/usr/bin/env python3 import asyncio import simplejson as json import time import websockets async def hello(): asyncio.get_event_loop().run_until_complete(hello())5 It looks like the attack started at 12:54, with "test.user," then proceeded alphabetically, ending about 10 minutes later, at 13:05. All of those attempts came from the same IP address, 172.31.254.101. As the attacker was trying passwords, they were able to successfully login as minty.candycane. After the attack ended, they logged in as minty.candycane again. Her account is the only account from that IP address that had a successful login. #!/usr/bin/env python3 import asyncio import simplejson as json import time import websockets async def hello(): asyncio.get_event_loop().run_until_complete(hello())6 Silly Minty, indeed. If only she had listened to Beau's talk… Answer: minty.candycane SummaryUsing the provided script, we converted the event logs to XML. Using basic \*NIX text-processing tools, we got an overview of the logs, then wrote a Python script to print out the relevant details. The password spraying attack was easy to spot, and all the attempts came from a single IP address. Only one user, minty.candycane, had a successful login from that IP. Git Dev Ops FailGoalFind Sparkle's password, then run the runtoanswer tool. Background
I mean, I may have uploaded something sensitive earlier, but it's no big deal. I overwrote it! Care to check my Cranberry Pi terminal and prove me right? Badge HintTo help us, Sparkle provides two links: Finding Passwords in Git and Git Cheat Sheet. Relevant KringleCon Videos Brian Hostetler, Buried Secrets: Digging Deep Through Cloud Repositories seems relevant, but it relies on using tools to search for secrets; something we can't easily do on the terminal.IntroOnce we connect: #!/usr/bin/env python3 import asyncio import simplejson as json import time import websockets async def hello(): asyncio.get_event_loop().run_until_complete(hello())7 SolutionFirst, we see what we're working with: #!/usr/bin/env python3 import asyncio import simplejson as json import time import websockets async def hello(): asyncio.get_event_loop().run_until_complete(hello())8 kcconfmgmt is a git repo, and we need to find some credentials in the history. The Git Cheat Sheet gives us the following command to search commits: kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 20 #!/usr/bin/env python3 import asyncio import simplejson as json import time import websockets async def hello(): asyncio.get_event_loop().run_until_complete(hello())9 To view the changes, the cheat sheet suggests the following command: C = [ { name: "size", size: 4 }, { name: "legs", size: 8 }, { name: "hue", size: 8 }, { name: "torso", size: 8 }, { name: "head", size: 8 }, { name: "saturation", size: 4 }, { name: "mouth", size: 8 }, { name: "eyes", size: 8 }, { name: "brightness", size: 4 }]; 0 We see that in kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 21, the credentials were sredberry and "twinkletwinkletwinkle": C = [ { name: "size", size: 4 }, { name: "legs", size: 8 }, { name: "hue", size: 8 }, { name: "torso", size: 8 }, { name: "head", size: 8 }, { name: "saturation", size: 4 }, { name: "mouth", size: 8 }, { name: "eyes", size: 8 }, { name: "brightness", size: 4 }]; 1 Answer: twinkletwinkletwinkle SummaryWe got fairly lucky on this one. We searched commits for "password," and then viewed the details of an interesting commit. Python Escape from LAGoalTo complete this challenge, escape Python and run ./i_escaped Background
Can you please help me by escaping from the Python interpreter? Badge HintSugarPlum's advice is to check out Mark Baggett's talk upstairs. Relevant KringleCon VideosIntroLaunching this terminal, we see something a bit different: C = [ { name: "size", size: 4 }, { name: "legs", size: 8 }, { name: "hue", size: 8 }, { name: "torso", size: 8 }, { name: "head", size: 8 }, { name: "saturation", size: 4 }, { name: "mouth", size: 8 }, { name: "eyes", size: 8 }, { name: "brightness", size: 4 }]; 2 SolutionWe need to run kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 22, either from Python, or after we've escaped. A simple way to exit Python is to call kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 23: C = [ { name: "size", size: 4 }, { name: "legs", size: 8 }, { name: "hue", size: 8 }, { name: "torso", size: 8 }, { name: "head", size: 8 }, { name: "saturation", size: 4 }, { name: "mouth", size: 8 }, { name: "eyes", size: 8 }, { name: "brightness", size: 4 }]; 3 Foiled. Watching Mark's talk, we see similarities with using kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 24 to filter prohibited words. Mark suggests checking to see if kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 25 is available: C = [ { name: "size", size: 4 }, { name: "legs", size: 8 }, { name: "hue", size: 8 }, { name: "torso", size: 8 }, { name: "head", size: 8 }, { name: "saturation", size: 4 }, { name: "mouth", size: 8 }, { name: "eyes", size: 8 }, { name: "brightness", size: 4 }]; 4 Next, let's try kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 26: C = [ { name: "size", size: 4 }, { name: "legs", size: 8 }, { name: "hue", size: 8 }, { name: "torso", size: 8 }, { name: "head", size: 8 }, { name: "saturation", size: 4 }, { name: "mouth", size: 8 }, { name: "eyes", size: 8 }, { name: "brightness", size: 4 }]; 5 That's promising. We try what Mark suggests using kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 27: C = [ { name: "size", size: 4 }, { name: "legs", size: 8 }, { name: "hue", size: 8 }, { name: "torso", size: 8 }, { name: "head", size: 8 }, { name: "saturation", size: 4 }, { name: "mouth", size: 8 }, { name: "eyes", size: 8 }, { name: "brightness", size: 4 }]; 6 Once we've escaped, we can see how this challenge was setup: C = [ { name: "size", size: 4 }, { name: "legs", size: 8 }, { name: "hue", size: 8 }, { name: "torso", size: 8 }, { name: "head", size: 8 }, { name: "saturation", size: 4 }, { name: "mouth", size: 8 }, { name: "eyes", size: 8 }, { name: "brightness", size: 4 }]; 7 SummaryWe basically followed Mark's talk directly. kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 28 and kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 29 was blocked, but kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 27 was available. We called kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 22 directly from Python, without ever actually escaping. The GDB Sleighbell LotteryGoalComplete this challenge by winning the sleighbell lottery for Shinny Upatree. Background
As long as no one else wins first, I can just keep trying to win the Sleigh Bell Lotto, but this could take forever! I'll bet the GNU Debugger can help us. With the PEDA modules installed, it can be prettier. I mean easier. Badge HintShinny recommends the SANS blog post Using gdb to Call Random Functions! Relevant KringleCon Videos NoneIntroThe terminal greets us with: C = [ { name: "size", size: 4 }, { name: "legs", size: 8 }, { name: "hue", size: 8 }, { name: "torso", size: 8 }, { name: "head", size: 8 }, { name: "saturation", size: 4 }, { name: "mouth", size: 8 }, { name: "eyes", size: 8 }, { name: "brightness", size: 4 }]; 8 SolutionWe start by investigating our surroundings: C = [ { name: "size", size: 4 }, { name: "legs", size: 8 }, { name: "hue", size: 8 }, { name: "torso", size: 8 }, { name: "head", size: 8 }, { name: "saturation", size: 4 }, { name: "mouth", size: 8 }, { name: "eyes", size: 8 }, { name: "brightness", size: 4 }]; 9 We start following along with the blog post. We'll start with kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 32 (display name list), and as the post tells us to focus on symbol types 'T' (text section symbols): render() { const {dna: e, version: t} = this.props; if (au.a.validateSequence(e))
0kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 33 looks promising. Let's see if we can use kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 34 to call that: render() { const {dna: e, version: t} = this.props; if (au.a.validateSequence(e))
1SummaryFor this one, we followed the SANS blog post from our badge hint almost verbatim, and were able to directly call the kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 33 function. ObjectivesOrientation ChallengeGoalWhat phrase is revealed when you answer all of the questions at the KringleCon Holiday Hack History kiosk inside the castle? Background
Solution
Directory BrowsingGoalBackground
SolutionAs we interact with the website, we're told that we missed the Call for Papers for the conference! We also see that there are two webpages we can access: https://cfp.kringlecastle.com/ https://cfp.kringlecastle.com/cfp/cfp.html The hints tell us to remove some characters from the end of the URL, as to view a directory listing. We discover that https://cfp.kringlecastle.com/cfp/ has directory listings enabled, and we see another file in that directory: Figure 17: Directory Listing At this point, we just need to find the line with the talk we're looking for: Figure 18: A Path in the Darkness? John McClane de Bruijn SequencesGoalWhen you break into the speaker unpreparedness room, what does Morcel Nougat say? Background
Solution
\(\triangle \square \bigcirc \triangle \) Data Repo AnalysisBackground
SolutionWhen we pull up the Git repository, we find a project called "santas_castle_automation." Our first hurdle is retrieving the encrypted ZIP file. The GitLab site has a "Find File" button on the right side of the page. Searching for kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 39 yields: Figure 21: zip paths in santas_castle_automation GitLab kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 40 catches our attention, so we download that from the website. Is this the encrypted ZIP file which we seek? Trying to open it prompts us for a password, so it seems likely that we've found it. Viewing the history and the commit where this file was added also reveals the following comment: Figure 22: Shinny's comment on ventilation_diagram.zip As we skim over the README that's displayed as we scroll down, we see the following message from Shinny: We all get what we git, then we git what we've got. When we're full of old pulls, then we're holding a lot. Do you wonder what happens to things that we thought, Were too private then trampled with things that were not? I assume that our secrets are gone from the cloud. They still sit here in local reposit'ries' shroud, But I heard that old Redberry was rather wowed, When she found out her keys were exposed - wasn't proud. So when I found that I had thown creds with a push, Pretty sure I did stomp them with clean files - smoosh! If you find an old password 'neath folder or bush, Would you kindly play nice and say nothing - just shush?" This, combined with the hint, strongly suggest that there are some secrets hidden in this repository. We've never tried Trufflehog before. Following along in Brian's video, we can try the command from the . render() { const {dna: e, version: t} = this.props; if (au.a.validateSequence(e))
6Interesting… some private SSH keys. The top commit catches our eye, as the message is "cleaning files." Could this be what Shinny was talking about, when he said "So when I found that I had thown creds with a push, Pretty sure I did stomp them with clean files - smoosh!?" No passwords, though. The video continues to mention the second command from the README, so let's try that. The README states that the first command we ran cuts down on the noise, but as we haven't found the password yet, we'll expand the search: render() { const {dna: e, version: t} = this.props; if (au.a.validateSequence(e))
7This finds a lot of hits, but the second from the last commit catches our eye. The filepath is kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 41, and there's a line: render() { const {dna: e, version: t} = this.props; if (au.a.validateSequence(e))
8Trying to open the ZIP file again, we enter that password and discover maps of the ventilation system! Yippee-ki-yay AD Privilege DiscoveryGoalUsing 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. Background
SolutionTo start, we download and run the VM. On the social medias, we read reports of people having issue opening this VM. Some people suggested changing the architecture to 64-bit, or using VMware instead. When the VM launches, we're in a Slingshot Linux instance. We notice a shortcut to Bloodhound on the desktop: Figure 23: VM Launch Screen When we launch Bloodhound, we open up a dataset for kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 42. Because Bloodhound is already installed, and the data is pre-imported for us, we can skip ahead in the video that Holly linked us to (around the 4:27 mark). We learn that the quickest way to get started is to explore the Queries tab. Our task is to find a path from a Kerberoastable user to the Domain Admins group. As we scroll down the Pre-Built Analytics Queries list, we see that there's a query for almost exactly that: Figure 24: Shortest Paths to Domain Admins from Kerberoastable Users We see a few options, and a few paths. Our objective tells us one further thing: "Remember to avoid RDP as a control path as it depends on separate local privilege escalation flaws." As we explore Bloodhound's interface, we find an Edge Filter option, and we can disable "CanRDP." Figure 25: Edge Filtering in Bloodhound This provides us with the following graph: Figure 26: Bloodhound Result It looks like our answer is Leanne Dubej's user: But what does this graph mean?
Administrators have unfettered access to a system. One of their superpowers is to be able to steal access tokens from other users on that system, and impersonate them. Because Jena has an active session on a system that Leanne is an admin on, Leanne could steal Jena's token, and use it to perform actions as a domain admin. The other remaining question is what exactly is meant by a "Kerberoastable" user? Kerberoast is "a series of tools for attacking MS Kerberos implementations." If an account has a Service Principal Name (SPN) associated with it, it's vulnerable to offline cracking attacks. Kerberoastable users are simply users that have SPNs associated with their accounts. In our case, Leanne has an SPN, and if we use Kerberoast to access her account, Bloodhound has found a path for us to elevate all the way to Domain Admin. Badge ManipulationGoalBypass 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? Background
Unfortunately, the badge-scan-o-matic said my account was disabled when I tried scanning my badge. I really needed access so I tried scanning several QR codes I made from my phone but the scanner kept saying "User Not Found". I researched a SQL database error from scanning a QR code with special characters in it and found it may contain an injection vulnerability. I was going to try some variations I found on but decided to stop so I don't tick-off Alabaster.
SolutionClicking on the Scan-O-Matic brings up the following interface: Figure 27: Scan-O-Matic in action As we interact with the scanner, we see there are two things we can do: scan our fingerprint, or plug in a USB 3.0 drive. Scanning our fingerprint processes the still from the video camera, while the USB drive brings up a file selection window for a file upload. The objective also gave us a sample employee badge: Figure 28: If found, please return to Alabaster First thing we try is uploading the badge via the file upload functionality. No dice: Figure 29: Error 1: PNG files only That's fine. We can do some file conversion, either by "Save As…" or from the command line: kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 43. Now we're uploading the right format: Figure 30: Error 2: Authorized User Account Has Been Disabled! Perhaps Alabaster's access was revoked when he reported his badge as stolen. These elves are really on top of security… Pepper's hints are pointing us towards SQL injection via the QR code, so let's start by taking a closer look at the QR code on Alabaster's badge. The Creating QR barcodes website she provided also has a scan function (as do many cellphone camera apps). We ended up using a different site, as we can just link to Alabaster's badge URL, and we don't have to use our webcam. The results are fairly cryptic, but they do seem to be plain text: render() { const {dna: e, version: t} = this.props; if (au.a.validateSequence(e))
9As we turn our attention to the link she mentioned, we see this interesting looking snippet: Figure 31: Auth Bypass We can use the Creating QR barcodes website to create a new QR code, with the snippet provided kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 44, and then save it (making sure to save it as a PNG). Now we can upload our new code to the Scan-O-Matic: Figure 32: Error 2a: Authorized User Account Has Been Disabled! Same error. But, this wasn't a total failure. We've confirmed that we can send arbitrary text as a QR code. Let's take a step back, and simplify our injection attempt. The OWASP webpage has several good examples, but let's just send the simplest case: kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 45. Figure 33: Error 3: Exception at line 96 window.onload = function() { document.getElementById("top").style.visibility="hidden"; document.getElementById("bottom").style.visibility="hidden"; document.getElementById("arrow-up").style.visibility="hidden"; document.getElementById("arrow-down").style.visibility="hidden"; //next section depends on player state document.getElementById("mazeform").elements.namedItem("heading").value = "w"; document.getElementById("mazeform").elements.namedItem("mazex").value = "22"; document.getElementById("mazeform").elements.namedItem("mazey").value = "19"; document.getElementById("mazeform").elements.namedItem("mazef").value = "1"; document.getElementById("mazeform").elements.namedItem("locationkey").value = "07edf09b26a307b9fe4f40bedffe76ed"; document.getElementById("mazeform").elements.namedItem("resourceid").value = "inigomontoya"; document.getElementById("wallform").elements.namedItem("northwall").value = "True"; document.getElementById("wallform").elements.namedItem("southwall").value = "True"; document.getElementById("wallform").elements.namedItem("eastwall").value = "False"; document.getElementById("wallform").elements.namedItem("westwall").value = "False"; wallcheck(); //render correct walls once state is known }; 0 The error is hard to read as it scrolls across, but we can use the dig +noall +answer ANY kringlecon.com 03 Developer Tools tab to view the whole thing. Still, it's hard to parse, so we'll take a closer look. It's an error from the MariaDB (née MySQL) database server. We also see a code snippet from Scan-O-Matic: window.onload = function() { document.getElementById("top").style.visibility="hidden"; document.getElementById("bottom").style.visibility="hidden"; document.getElementById("arrow-up").style.visibility="hidden"; document.getElementById("arrow-down").style.visibility="hidden"; //next section depends on player state document.getElementById("mazeform").elements.namedItem("heading").value = "w"; document.getElementById("mazeform").elements.namedItem("mazex").value = "22"; document.getElementById("mazeform").elements.namedItem("mazey").value = "19"; document.getElementById("mazeform").elements.namedItem("mazef").value = "1"; document.getElementById("mazeform").elements.namedItem("locationkey").value = "07edf09b26a307b9fe4f40bedffe76ed"; document.getElementById("mazeform").elements.namedItem("resourceid").value = "inigomontoya"; document.getElementById("wallform").elements.namedItem("northwall").value = "True"; document.getElementById("wallform").elements.namedItem("southwall").value = "True"; document.getElementById("wallform").elements.namedItem("eastwall").value = "False"; document.getElementById("wallform").elements.namedItem("westwall").value = "False"; wallcheck(); //render correct walls once state is known }; 1 From this, we can figure out the database query was something like: window.onload = function() { document.getElementById("top").style.visibility="hidden"; document.getElementById("bottom").style.visibility="hidden"; document.getElementById("arrow-up").style.visibility="hidden"; document.getElementById("arrow-down").style.visibility="hidden"; //next section depends on player state document.getElementById("mazeform").elements.namedItem("heading").value = "w"; document.getElementById("mazeform").elements.namedItem("mazex").value = "22"; document.getElementById("mazeform").elements.namedItem("mazey").value = "19"; document.getElementById("mazeform").elements.namedItem("mazef").value = "1"; document.getElementById("mazeform").elements.namedItem("locationkey").value = "07edf09b26a307b9fe4f40bedffe76ed"; document.getElementById("mazeform").elements.namedItem("resourceid").value = "inigomontoya"; document.getElementById("wallform").elements.namedItem("northwall").value = "True"; document.getElementById("wallform").elements.namedItem("southwall").value = "True"; document.getElementById("wallform").elements.namedItem("eastwall").value = "False"; document.getElementById("wallform").elements.namedItem("westwall").value = "False"; wallcheck(); //render correct walls once state is known }; 2 The QR code seems to supply the kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 47 parameter (this is the only variable on that line; everything else is hard-coded). When we submitted a kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 47 of just a single-quote, the SQL database server complained of a syntax error. Let's play around with this a little bit, to better understand what's going on. A good tool for this is sqltest.net. From the query, we know that we're searching the kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 49 table. The query is requesting the fields kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 50, kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 51, kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 52 be returned, and it's filtering on the fields kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 53 and kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 47. So we can mock up a simple example (in fact the example when we load sqltest.net already is pretty close, as it has kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 55, kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 50, and kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 51). window.onload = function() { document.getElementById("top").style.visibility="hidden"; document.getElementById("bottom").style.visibility="hidden"; document.getElementById("arrow-up").style.visibility="hidden"; document.getElementById("arrow-down").style.visibility="hidden"; //next section depends on player state document.getElementById("mazeform").elements.namedItem("heading").value = "w"; document.getElementById("mazeform").elements.namedItem("mazex").value = "22"; document.getElementById("mazeform").elements.namedItem("mazey").value = "19"; document.getElementById("mazeform").elements.namedItem("mazef").value = "1"; document.getElementById("mazeform").elements.namedItem("locationkey").value = "07edf09b26a307b9fe4f40bedffe76ed"; document.getElementById("mazeform").elements.namedItem("resourceid").value = "inigomontoya"; document.getElementById("wallform").elements.namedItem("northwall").value = "True"; document.getElementById("wallform").elements.namedItem("southwall").value = "True"; document.getElementById("wallform").elements.namedItem("eastwall").value = "False"; document.getElementById("wallform").elements.namedItem("westwall").value = "False"; wallcheck(); //render correct walls once state is known }; 3 We decided to make the kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 53 and kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 52 fields integers because the query has kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 60. The lack of quotes tells us it's not a string. We'll start by trying our query with the UID from Alabaster's badge: kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 61: Figure 34: Sending Alabaster's badge to sqltest.net We got our expected result, but Alabaster's not enabled. Now let's try sending a single quote, and see if we can duplicate the error message: Figure 35: Sending a single quote to sqltest.net We get the following error message, which matches almost exactly the error message we got from Scan-O-Matic: =You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '''' LIMIT 1' at line 2=. The cause of the error is that we've created a query with a string that doesn't close (there's no closing single-quote). We've discovered a SQL injection! Now we need to exploit it to gain access to the door. We start by trying the following query: window.onload = function() { document.getElementById("top").style.visibility="hidden"; document.getElementById("bottom").style.visibility="hidden"; document.getElementById("arrow-up").style.visibility="hidden"; document.getElementById("arrow-down").style.visibility="hidden"; //next section depends on player state document.getElementById("mazeform").elements.namedItem("heading").value = "w"; document.getElementById("mazeform").elements.namedItem("mazex").value = "22"; document.getElementById("mazeform").elements.namedItem("mazey").value = "19"; document.getElementById("mazeform").elements.namedItem("mazef").value = "1"; document.getElementById("mazeform").elements.namedItem("locationkey").value = "07edf09b26a307b9fe4f40bedffe76ed"; document.getElementById("mazeform").elements.namedItem("resourceid").value = "inigomontoya"; document.getElementById("wallform").elements.namedItem("northwall").value = "True"; document.getElementById("wallform").elements.namedItem("southwall").value = "True"; document.getElementById("wallform").elements.namedItem("eastwall").value = "False"; document.getElementById("wallform").elements.namedItem("westwall").value = "False"; wallcheck(); //render correct walls once state is known }; 4 We're looking for an authorized user, whose uid is either empty or not empty. In other words, this should match everyone. Figure 36: Matching anyone on sqltest.net Well, no more error, but we still only get Alabaster's user. Even though our search should match everyone, the kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 62 clause will only return one result, and just our luck, that one result is not enabled. No problem – we can just also require that the user be enabled: window.onload = function() { document.getElementById("top").style.visibility="hidden"; document.getElementById("bottom").style.visibility="hidden"; document.getElementById("arrow-up").style.visibility="hidden"; document.getElementById("arrow-down").style.visibility="hidden"; //next section depends on player state document.getElementById("mazeform").elements.namedItem("heading").value = "w"; document.getElementById("mazeform").elements.namedItem("mazex").value = "22"; document.getElementById("mazeform").elements.namedItem("mazey").value = "19"; document.getElementById("mazeform").elements.namedItem("mazef").value = "1"; document.getElementById("mazeform").elements.namedItem("locationkey").value = "07edf09b26a307b9fe4f40bedffe76ed"; document.getElementById("mazeform").elements.namedItem("resourceid").value = "inigomontoya"; document.getElementById("wallform").elements.namedItem("northwall").value = "True"; document.getElementById("wallform").elements.namedItem("southwall").value = "True"; document.getElementById("wallform").elements.namedItem("eastwall").value = "False"; document.getElementById("wallform").elements.namedItem("westwall").value = "False"; wallcheck(); //render correct walls once state is known }; 5 This query seems a bit repetitive, and it is, because we're limited in what queries we can build. What we're searching on is that a user must have an empty kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 47 OR be enabled OR have an empty kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 47. We're not sure if anyone has an empty kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 47, but the user that's returned matches the other criteria: their account is enabled. Figure 37: Requiring an enabled user on sqltest.net We found a query which works in our little sandbox, but how do we make it work on Scan-O-Matic? We start by comparing the queries: window.onload = function() { document.getElementById("top").style.visibility="hidden"; document.getElementById("bottom").style.visibility="hidden"; document.getElementById("arrow-up").style.visibility="hidden"; document.getElementById("arrow-down").style.visibility="hidden"; //next section depends on player state document.getElementById("mazeform").elements.namedItem("heading").value = "w"; document.getElementById("mazeform").elements.namedItem("mazex").value = "22"; document.getElementById("mazeform").elements.namedItem("mazey").value = "19"; document.getElementById("mazeform").elements.namedItem("mazef").value = "1"; document.getElementById("mazeform").elements.namedItem("locationkey").value = "07edf09b26a307b9fe4f40bedffe76ed"; document.getElementById("mazeform").elements.namedItem("resourceid").value = "inigomontoya"; document.getElementById("wallform").elements.namedItem("northwall").value = "True"; document.getElementById("wallform").elements.namedItem("southwall").value = "True"; document.getElementById("wallform").elements.namedItem("eastwall").value = "False"; document.getElementById("wallform").elements.namedItem("westwall").value = "False"; wallcheck(); //render correct walls once state is known }; 6 The UID from the QR code gets put in between single quotes, which is why our query was rather odd. We needed to construct it in such a way so that it would both start and end with a string. So, if we just set the kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 47 parameter to kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 67, we should be able to run this query on Scan-O-Matic: Figure 38: Access Granted! User Access Granted - Control number 19880715 CareersGoalSanta uses an Elf Resources website to look for talented information security professionals. Gain access to the website and fetch the document kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 68. Which terrorist organization is secretly supported by the job applicant whose name begins with "K." Background
It takes CSV files as imports. That certainly can expedite a process, but there's danger to be had. I'll bet, with the right malicious input, some naughty actor could exploit a vulnerability there. I'm sure the danger can be mitigated. OWASP has guidance on what not to allow with such uploads. Badge HintSparkle also points us to the OWASP CSV Injection Page, and tells us: Somehow Brian Hostetler is giving a talk on CSV injection WHILE he's giving a talk on Trufflehog. Whatta' guy! Relevant KringleCon VideosSolutionBringing up the webpage, we're presented with a simple form: Figure 39: Elf Resources website home Filling in the form, the page forces us to attach a file before submitting. If we do that, we receive the following message: Figure 40: Elf Resources submission message Both the objective and the submission message told us the file we need to retrieve, kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 68. We next simply tried https://careers.kringlecastle.com/candidate_evaluation.docx, and got the following: Figure 41: Elf Resources 404 What a helpful error message! Unfortunately, trying https://careers.kringlecastle.com/public/candidate_evaluation.docx similarly doesn't work. But now, we know two critical pieces of information:
Time to turn our attention to the hints, and see how we can get our target file into the public directory. Brian's talk gives some guidance on how to build a CSV to execute an arbitrary command. We choose a name designed to not conflict with other KringleCon attendees. window.onload = function() { document.getElementById("top").style.visibility="hidden"; document.getElementById("bottom").style.visibility="hidden"; document.getElementById("arrow-up").style.visibility="hidden"; document.getElementById("arrow-down").style.visibility="hidden"; //next section depends on player state document.getElementById("mazeform").elements.namedItem("heading").value = "w"; document.getElementById("mazeform").elements.namedItem("mazex").value = "22"; document.getElementById("mazeform").elements.namedItem("mazey").value = "19"; document.getElementById("mazeform").elements.namedItem("mazef").value = "1"; document.getElementById("mazeform").elements.namedItem("locationkey").value = "07edf09b26a307b9fe4f40bedffe76ed"; document.getElementById("mazeform").elements.namedItem("resourceid").value = "inigomontoya"; document.getElementById("wallform").elements.namedItem("northwall").value = "True"; document.getElementById("wallform").elements.namedItem("southwall").value = "True"; document.getElementById("wallform").elements.namedItem("eastwall").value = "False"; document.getElementById("wallform").elements.namedItem("westwall").value = "False"; wallcheck(); //render correct walls once state is known }; 7 Uploading this file, we then try to access https://careers.kringlecastle.com/public/ZXNuZXRfc2VjdXJpdHkK.docx. After ~10-15 seconds, we download a Word Doc. The download evaluates 4 elves, including Krampus: Figure 42: Krampus Evaluation The document reveals that Krampus is connected to cyber terrorist organization Fancy Beaver (a play on the Fancy Bear APT group). Answer: Fancy Beaver PCAPalyzerGoalSanta 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? Background
As a token of my gratitude, I would like to share a rumor I had heard about Santa's new web-based packet analyzer - Packalyzer. 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. On a tooootally unrelated note, have you seen the HTTP2 talk at at KringleCon by the Chrises? I never knew HTTP2 was so different!
Solution Part 1: Downloading the SSL Key LogfileA lot of hints on this one. We start by loading up Packalyzer, and trying to find the HTML comments. We have access to two pages initially, the home page, and the new user registration page. We can't find any hidden comments in either one, so we go ahead and register a new user, and then sign in with our new account. At this point, the Packalyzer allows us to sniff 20 seconds of traffic, and then download the PCAP. Once we're authenticated, we can find the following comment in the page source: window.onload = function() { document.getElementById("top").style.visibility="hidden"; document.getElementById("bottom").style.visibility="hidden"; document.getElementById("arrow-up").style.visibility="hidden"; document.getElementById("arrow-down").style.visibility="hidden"; //next section depends on player state document.getElementById("mazeform").elements.namedItem("heading").value = "w"; document.getElementById("mazeform").elements.namedItem("mazex").value = "22"; document.getElementById("mazeform").elements.namedItem("mazey").value = "19"; document.getElementById("mazeform").elements.namedItem("mazef").value = "1"; document.getElementById("mazeform").elements.namedItem("locationkey").value = "07edf09b26a307b9fe4f40bedffe76ed"; document.getElementById("mazeform").elements.namedItem("resourceid").value = "inigomontoya"; document.getElementById("wallform").elements.namedItem("northwall").value = "True"; document.getElementById("wallform").elements.namedItem("southwall").value = "True"; document.getElementById("wallform").elements.namedItem("eastwall").value = "False"; document.getElementById("wallform").elements.namedItem("westwall").value = "False"; wallcheck(); //render correct walls once state is known }; 8 https://packalyzer.kringlecastle.com/app.js doesn't work, but we also noticed some resources being loaded from https://packalyzer.kringlecastle.com/pub/, and we can recover the server-side source code of kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 72 from https://packalyzer.kringlecastle.com/pub/app.js Folllowing SugarPlum's hints, we found the comment, and grabbed the server-side source code sitting in the web root. Now we need to identify the environment variables used to store SSL keys: window.onload = function() { document.getElementById("top").style.visibility="hidden"; document.getElementById("bottom").style.visibility="hidden"; document.getElementById("arrow-up").style.visibility="hidden"; document.getElementById("arrow-down").style.visibility="hidden"; //next section depends on player state document.getElementById("mazeform").elements.namedItem("heading").value = "w"; document.getElementById("mazeform").elements.namedItem("mazex").value = "22"; document.getElementById("mazeform").elements.namedItem("mazey").value = "19"; document.getElementById("mazeform").elements.namedItem("mazef").value = "1"; document.getElementById("mazeform").elements.namedItem("locationkey").value = "07edf09b26a307b9fe4f40bedffe76ed"; document.getElementById("mazeform").elements.namedItem("resourceid").value = "inigomontoya"; document.getElementById("wallform").elements.namedItem("northwall").value = "True"; document.getElementById("wallform").elements.namedItem("southwall").value = "True"; document.getElementById("wallform").elements.namedItem("eastwall").value = "False"; document.getElementById("wallform").elements.namedItem("westwall").value = "False"; wallcheck(); //render correct walls once state is known }; 9 Let's take this line by line. In the development copy we have, kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 73 is set to true. kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 74 uses some short-hand syntax, which could also be written as: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 00 Finally, once kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 74 is set, the comment tells us that it's used to view traffic. Our hints seem to point us to recovering this file, and then using it to decrypt the traffic. Perhaps the file was left over from development. We need to figure out what the environment variables kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 76 and kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 77 were set to. The main logic of the file is the kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 78 function. An annotated version is: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 01 Going through this, especially with an example, we can understand the logic. Sometimes it's useful to try running a command, and seeing what the output is. In cases like this, we pull up the Javascript console of our browser's developer tools again: Figure 43: Testing JS code in our console Our attention is drawn to how the code builds the filename: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 02 Again, we'll expand this logic out a bit: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 03 So, the first part of our path is upper-cased, and if an environment variable exists with that name, it attempts to use that as part of the path to our file. Let's try it. Searching for kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 79 pulls up some Node.js documentation: Figure 44: process.env documentation Let's try accessing the kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 80 environment variable: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 04 We received an error message, but one which discloses some information. Let's try to unpack this, given that we have the source for how the filename was built. First, let's identify exactly which part is our kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 80. We can check this on a Cranberry Pi terminal, as a point of comparison: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 05 Reading our error message carefully, we can identify all three variables that combined to form the filename: Value Variable kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 82 kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 83 kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 84 kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 85 kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 86 kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 87 At this point, we need to recover the environment variables kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 76 and kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 77, which are referenced in kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 90: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 06 From this, we can deduce that kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 76 is kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 92 and kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 77 is kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 94. We've already figured out kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 83, so our kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 74 would've been kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 97. We just need to figure out how to access that via the webserver. We've already noted that we can access files from https://packalyzer.kringlecastle.com/pub/, so let's get the full path of that by generating an error message for a non-existant file: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 07 Great! The files we're accessing are from kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 98, so kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 99 should be just as easy to access: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 08 Great! We've successfully downloaded the file. Solution Part 2: Decrypting the TrafficWe've run through most of SugarPlum's hints in order to recover the SSL Key Logfile. As a reminder, she also told us: I'm hoping these errors can't be used to compromise SSL on the website and steal logins. On a tooootally unrelated note, have you seen the HTTP2 talk at at KringleCon by the Chrises? I never knew HTTP2 was so different! We already used Chris Elgee's video for the CURLing Master terminal, and it made no mention of using HTTP2 to compromise SSL. The other video is Chris Davis, HTTP/2: Decryption and Analysis in Wireshark, which sounds perfect. The first part of the talk discusses how to create the SSL Key Logfile using curl and Chrome. This seems like what we just recovered from the system, only that it was generated server-side instead of client-side. The talk also mentions how we can use this file to decrypt the SSL traffic in Wireshark. In order to do that, we need a PCAP, though. Perhaps a new PCAP from the Packalyzer web interface? The comment in the server-side source code warned us that the key log only stores a few minutes worth at a time. The server can't log keys ahead of time, so our workflow should be:
For step 4, we just continue following along with Chris's video. First, we configure the Wireshark SSL protocol analyzer to use our freshly downloaded key logfile: Figure 45: Configuring Wireshark SSL protocol analyzer It worked! We can now see some HTTP2 traffic: Figure 46: Wireshark HTTP2 overview As a reminder, our goal is to steal logins, and ultimately access a document sent from Holly to Alabaster. To start, we'll filter out just HTTP2 traffic, using the ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 00 display filter: Figure 47: Wireshark with http2 filter We immediately see a HTTP ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 01 request to ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 02, which seems promising. Chris's video has a very similar request, and he points out that to get the actual username and password, we need to look at a different frame in the packet capture. We'll combine two of Chris's example filters into ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 03, and then we can find some credentials: Figure 48: Wireshark with http2 POST filter We've found Pepper's credentials. Can we find anyone else's? To speed up this analysis a bit, we're going to add some custom fields to the Wireshark display. Either by right-clicking on the column headers and going to ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 04 or by going to ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 05 → ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 06 → ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 07. We'll add two custom columns for JSON keys and values: Figure 49: Wireshark custom columns Finally, we'll filter our PCAP to display frames which have a JSON key of "password": Figure 50: Wireshark with json filter Bingo! Username Password pepper Shiz-Bamer_wabl182 alabaster Packer-p@re-turntable192 We've followed all the hints, but ultimately, we're looking for a document. The HTTP2 traffic we're seeing in this PCAP looks like the Packalyzer website itself, so we're presuming the credentials are for that. Since we know the document was sent to Alabaster, let's start with his credentials, and try logging into Packalyzer: Figure 51: Successful login as Alabaster Opening up the captures associated with Alabaster's account, we find the tantalizingly named ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 08. We'll grab it and open it up in Wireshark again. A good way to get a quick overview of a PCAP in Wireshark is to use ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 09 → ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 10: Figure 52: Super secret protocol hierarchy It looks like the only thing Wireshark found in this PCAP is SMTP (e-mail) traffic. Note that it's not listed as 100%, since some packets are simply TCP control packets. We'll filter on ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 11: Figure 53: Super secret SMTP We immediately see an e-mail from Holly to Alabaster. Looks like we're on the right track… Now we just need to find and extract the document. To get a better look at the data, we can right click on one of the frames, and select ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 12 → ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 13. A new window pops up: Figure 54: Super secret e-mail Holly says: Hey alabaster, Santa said you needed help understanding musical notes for accessing the vault. He said your favorite key was D. Anyways, the following attachment should give you all the information you need about transposing music. What follows is the attachment: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 09 We can see that the attachment is encoded as base64, so we can copy and paste the data, and then decode it with: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 10 The attachment is a PDF, so we'll rename it accordingly. Opening the document gives us our answer: Figure 55: Super secret song Answer: Mary Had a Little Lamb We also note that this document walks us through how to transcribe a song from one key to another. Ransomware RecoveryGoalAlabaster 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. Background
Phase 1: Catch the Malware
I came here to help but got locked in 'cause I dropped my "Alabaster Snowball" badge in a rush. I started analyzing the ransomware on my host operating system, ran it by accident, and now my files are encrypted! Unfortunately, the password database I keep on my computer was encrypted, so now I don't have access to any of our systems. If only there were some way I could create some kind of traffic filter that could alert anytime ransomware was found! We launch the Snort Challenge terminal. Opening it up, we see the following message: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 11 Looking at ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 14, we see: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 12 To summarize, we need to edit ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 15 and add a rule to detect the malware, but not alert on legitimate traffic. To test our rule, we can run ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 16. SolutionLet's start by taking a look at ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 17: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 13 No rules in there yet. Let's check out the DNS traffic and determine what we need to alert on. We're told that we also have a PCAP file with 30 seconds of traffic. For digging into the PCAP, we can get some hints from Mike Poor's KringleCon talk. One of the tools mentioned is ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 18, which we're told is on this system. The Snort system doesn't have manual pages installed, but if we run ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 19, we see some useful help output: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 14 Let's just try reading the PCAP, and see what we're working with: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 15 The output of the command is rather verbose, and looks like an intimidating wall of text. We see a number of DNS TXT queries ( ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ...
Our rule works, but is not a great rule. Any UDP content that has that string anywhere in the packet will trigger the rule. DNS uses a special method to encode the query name on the wire. Each portion of the DNS name (the "labels"), are prefixed with the length of that label, with an empty label at the end. So, "www.es.net" would be encoded as ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ...
Phase 2: Identify the Domain
Hey, you're pretty good at this security stuff. Could you help me further with what I suspect is a malicious Word document? All the elves were emailed a cookie recipe right before all the infections. Take this document with a password of elves and find the domain it communicates with. Also, Shinny tells us: Have you heard that Kringle Castle was hit by a new ransomware called Wannacookie? Several elves reported receiving a cookie recipe Word doc. When opened, a PowerShell screen flashed by and their files were encrypted. Many elves were affected, so Alabaster went to go see if he could help out. I hope Alabaster watched the PowerShell Malware talk at KringleCon before he tried analyzing Wannacookie on his computer. Badge HintWe have the following hints from Shinny and Alabaster: Whoa, Chris Davis' talk on PowerShell malware is crazy pants! You should check it out! Word docm macros can be extracted using olevba. Perhaps we can use this to grab the ransomware source. Relevant KringleCon Videos
Phase 3: Stop the Malware
I remember another ransomware in recent history had a killswitch domain that, when registered, would prevent any further infections. Perhaps there is a mechanism like that in this ransomware? Do some more analysis and see if you can find a fatal flaw and activate it! Badge HintWe have a couple of hints from Alabaster: I think I remember reading an article recently about Ransomware Kill Switchs. Wouldn't it be nice if our ransomware had one! wannacookie.min.ps1? I wonder if there is a non-minified version? If so, it may be easier to read and give us more information and maybe source comments? The article tells us: By relying on a static, discoverable address, whoever found it—in this case MalwareTech—could just register the domain and trigger WannaCry's shutdown defense. SolutionAt the end of Phase 2, we recovered a snippet that does something over DNS: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 30 We see that the first DNS query is actually in the ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 46 line itself: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 31 We expect this to return a number, as it's being convert to a 32-bit integer, as base 10. We recognize ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 47 from the PCAPs on the Snort system, and we already found that it's a hex-encoded "wannacookie.min.ps1". Let's see what's being sent over DNS: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 32 As expected, the first top-level query returned a number. Next, the script would start to loop over queries for ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 48, ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 49, up to the ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 50. Let's see what those look like: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 33 Looks like more encoded content. We notice that the script was passing this output to a function, ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 51: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 34 It would stand to reason that this is once again hex-encoded, and ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 51 is short for "hex to ASCII." ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 35 We decoded it, and recovered Powershell code. This was expected, as ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 53 ( ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ...
Phase 4: Recover Alabaster's Password
Now that we don't have to worry about new infections, I could sure use your L337 security skills for one last thing. As I mentioned, I made the mistake of analyzing the malware on my host computer and the ransomware encrypted my password database. Take this zip with a memory dump and my encrypted password database, and see if you can recover my passwords. One of the passwords will unlock our access to the vault so we can get in before the hackers. We also have the following hints from Shinny: He also said that Wannacookie transfers files over DNS and that it looks like it grabs a public key this way. Another recent ransomware made it possible to retrieve crypto keys from memory. Hopefully the same is true for Wannacookie! Of course, this all depends how the key was encrypted and managed in memory. Proper public key encryption requires a private key to decrypt. Perhaps there is a flaw in the wannacookie author's DNS server that we can manipulate to retrieve what we need. If so, we can retrieve our keys from memory, decrypt the key, and then decrypt our ransomed files. Badge HintWe have a hint that we haven't used yet: Pulling strings from a memory dump using the linux strings command requires you specify the -e option with the specific format required by the OS and processor. Of course, you could also use powerdump. SolutionOpening the zip reveals two files: ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 59 and ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 60. To solve this, we really need to understand the Powershell script better. After some analysis, we can trace the main code flow:
Who Is Behind It All?GoalUse what you have learned from previous challenges to open the door to Santa's vault. What message do you get when you unlock the door? Background
How could I forget that I used Rachmaninoff as my musical password?
SolutionWe take the notes recovered from Alabaster's decrypted password vault, and try it on the piano lock. The document we recovered from Packalyzer helpfully shows us the notes on the piano keys. Figure 58: Wrong key The hint tells us that it should be in the key of D, not E. The Packalyzer document also told us how to transcribe music from one key to another. Let's try: Note in key of E Note in key of D E D D# C# E D D# C# E D E D D# C# E D F# E G# F# F# E G# F# A G B A A# G# B A A# G# B A Trying that sequence ( ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ...
Figure 59: Right key! Once we enter the vault, Alabaster tells us: Of course I transposed it it before I entered it into my database for extra security. Hans offers us a congratulations, and Santa explains the whole thing, finishing: 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. So, who was behind it all? Answer: Santa de Bruijn Piano Lock?After learning about sequences, we were curious if that would work here. The lock seemed to operate in the same way, as it would try unlocking after each note was pressed. We noticed that the tune in question had a similar note pattern at the end ( ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ...
... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 74). We whipped up a quick Python program that verified that in fact we could generate a de Bruijn sequence. ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 51 The result was: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 52 What's even cooler is that the sequence goes through all of the keys before it repeats! Figure 60: de Bruijn key sequence for Marriage of Figaro Rachmaninoff?As we walk around the castle, everyone congratulates us on winning. However, we don't feel complete, as we're left with the nagging question of what in the world Alabaster was talking about with his Rachmaninoff-no-really-Mozart song. We have the notes, but not the tune. Can we figure out the song? This one we solved two ways: Musipedia.org allows you to search by melodic contour (Parsons code). By simply saying if each note progression goes up, down, or repeats, it can find the closest matches: Figure 61: Musipedia Parsons search The Wedding of Figaro seems to match perfectly: Figure 62: Wedding of Figaro, by Mozart But still… why Rachmaninoff, then? The answer is found in the second method we used to figure this out: Figure 63: Asking on Facebook… Your browser does not support the video tag. And with that, Santa's parting words make a lot more sense too: Your browser does not support the video tag. Going Further: Escalations and 0daysAt this point, we've solved it all! However, our curiousity is unabated, and we'd like to know what else we can find… NoteWe managed to escalate to root on the snort terminal, pivot to snortsensor1, where we got command execution and were able to read files with root privileges. Finally, we got a shell on careers. Scan-O-MaticWe managed to get through the , but we were curious to see who had access. We wrote which allowed us to use ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 75 to enumerate the rest of the data in the table: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 53 We note that only has access. Escalating to root on snortWe've solved the Snort challenge, but what else can we do on that system? Checking dig +noall +answer ANY kringlecon.com 81, we see: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 54 So, root is running a number of processes. Let's see if we can figure out what's happening behind the scenes to test our rule. It seems as if something happens whenever we modify the local.rules file, so we can simulate that with ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 77: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 55 Here we see that root actually runs ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 78 to check our rules. Perhaps we can modify the Snort configuration in such a way to run some commands as root? We can't modify ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 79, but let's see how the ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 17 file is being loaded: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 56 Ah! It seems as if it's being included into the config. A generic ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 81 statement would imply that we could modify arbitrary configuration settings, and we're not simply limited to adding rules. Looking over the Snort documentation, we found a very intriguing option: ... Time to create a malicious shared library: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 57 The above command uses Metasploit's ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 83 to create a shared library which will execute a command when it's loaded. Because Snort's running as root, the command will run as root as well. The command grants our ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 84 user the ability to run any command with superuser privileges, without prompting for a password. The Snort system is the only Docker container which has networking enabled. We can transfer our new shared library by simply using ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 85. Then, we add it to the ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 17 file: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 58 Pivoting to snortsensor1Now that we have root access on the Snort docker container, we can extract the HMAC key from the script. We also see the following interesting snippet from the ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 87 script (snort spelled backwards): ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 59 Sure enough, using the private key, we can also login to snortsensor1 as elf. However, we run into an issue: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 60 Command execution on snortsensor1We need to figure out a way past ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 88. We can copy files off of the system, and we can copy ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 89, which mainly has: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 61 To start, let's see what actually happens when we run ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 90. We'll run it with the ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 91 ( kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all"
... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 62 So, ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 90 is simply calling ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 94 with a fixed command. We can run this ourselves to verify: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 63 So, the program hangs, and once we type some input, we get some text back. So, it certainly seems as if ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 88 allowed us to run our ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 90 command. Can we run other commands this way? ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 64 That's a negative. ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 88 must be filtering the commands we can run. Time to dive into the ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 90 and ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 94 documentation, and see if there's a way we can craft an ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 90 invocation that will cause it to execute commands. Quickly, we identify a promising candidate: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 65 ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 66 They're on to us… Reading further, we see that we can also pass ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 94 options to ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 90: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 67 Reading through the var i; var lava = document.getElementsByClassName('lava'); for ( i = 0; i < lava.length; i++ )
03 man page, we find another intriguing option:... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 68 From the snort system, we already know the fun we can have with a shared library. First, we'll build a library which executes a command when it's loaded: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 69 Now, will ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 90 load this? We test on our system first: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 70 No, the same behavior. Of course! The man page said that this option is passed to the ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 94 call, and by just listening for data, ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 90 is never calling ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 94. To make it do this, we'll try using ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 90 to send a file from our system to another: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 71 Success! Now the question is, will ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 88 allow this new ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 90 command? First, we'll copy our shared library over to the system. We'll add another ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 94 option to ignore the "New host key, Are you sure you want to continue?" prompt: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 72 Success! We reported this issue to the ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 88 author, who replied saying that: RSSH is no longer maintained. We've applied for a CVE and will update our report when that's assigned. So… we discovered a 0day! And perhaps it's time for people to switch off of ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 88. At this point, it's trivial to escalate this to a meterpreter shell: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 73 Bingo! Privilege Escalation on snortsensor1Now that we have a comfortable foothold, we can see how the holiday magic of snortsensor1 was created. Looking at processes running, we identify var i; var lava = document.getElementsByClassName('lava'); for ( i = 0; i < lava.length; i++ )
14, and we notice that it's running as root. The main logic of that script is:... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 74 This script has a vulnerability in this section: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 75 Let's assume that an attacker wants to access a file on the system that the elf user isn't authorized to read. Because var i; var lava = document.getElementsByClassName('lava'); for ( i = 0; i < lava.length; i++ )
15 is running as root, the attacker knows that the script can read that file. Furthermore, the script is placing files in the publicly accessible web server root.Linux uses symbolic links (symlinks), almost as a pointer from one location to another on the filesystem. If an attacker times their attack just right, they can do something like: Figure 64: packet_generator race condition An interesting note is that this attack was possible without the ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 88 vulnerability, as var i; var lava = document.getElementsByClassName('lava'); for ( i = 0; i < lava.length; i++ )
17 was allowed, and var i; var lava = document.getElementsByClassName('lava'); for ( i = 0; i < lava.length; i++ )
17 can create symlinks.However, this race is very hard to win. And, if we don't time it right, the following happens: Figure 65: packet_generator oops condition Let's see if we can't improve our odds. Another special Linux file is a FIFO, or named pipe. These are designed so that one side will write to it, and another will read to it. All data is passed internally, without being written to the filesystem. One side-effect of using a FIFO is that, when you write to it, your program will hang until something reads from it. We can use this to cause var i; var lava = document.getElementsByClassName('lava'); for ( i = 0; i < lava.length; i++ )
19 to pause at the right time, giving us a much better chance to win the race.Figure 66: packet_generator FIFO We've successfully moved the race up a step, where now we need to get var i; var lava = document.getElementsByClassName('lava'); for ( i = 0; i < lava.length; i++ )
19 writing to our FIFO just after it deletesvar i; var lava = document.getElementsByClassName('lava'); for ( i = 0; i < lava.length; i++ )
21, but before it starts writing to it. However, this approach has two advantages: the var i; var lava = document.getElementsByClassName('lava'); for ( i = 0; i < lava.length; i++ )
22 function takes a bit of time to run, and the risk of accidentally overwriting our target file is greatly reduced.We weaponized this as a bash script, which has the following logic: Figure 67: race.sh logic ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 76 When running, this looks like: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 77 We see that there's a new file, with the same size as our target. Now we can download it, and we've got some hashes! ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 78 At this point, if we can crack root's password, we have completely compromised this system. Popping a shell on careersThe final system we turned our attention to was careers.kringlecastle.com. We already got our file off of this system, but we'd like to see what else we can do. We first tried to get a meterpreter session running, but quickly found that Windows Defender was blocking it. We were able to bypass Defender with this method: https://rastamouse.me/2018/12/amsiscanbuffer-bypass-part-4/ ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 79 To create our actual payload, we use ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 83 once again. For the reasons listed in the article above, we're careful to use a 64-bit payload, so as to not spawn a non-bypassed 32-bit Powershell instance. ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 80 We fire up meterpreter ( var i; var lava = document.getElementsByClassName('lava'); for ( i = 0; i < lava.length; i++ )
24), and soon see:... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 81 Unfortunately, our shell will get killed off after about 30 seconds. So, we'll migrate to another process. We see that Sparkle is running the Non-Sucking Service Manager, so we'll try to migrate to that process: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 82 At this point, we tried a few things (and were able to recover Sparkle's password hash through an SMB relay attack), but the escalation paths we saw risked the stability of the game, and we didn't pursue the matter. Working as a TeamWhile working on this challenge, we used three main techniques to get things done and stay organized. We were mostly working in the same room that happened to have a couple of big whiteboards. Those came in handy as we slowly drew out the map of the game and location of all things in it. We also originally tracked our progress using this. The whiteboards also came in handy as a way to quickly iterate through ideas on specific challenges we faced. Figure 68: Map Whiteboard The use of a private Slack channel was also very helpful. It existed as a place to both dump answers, clues, and interesting artifacts, as well as a good place for discussion for when we weren’t in the same room. Figure 69: Progress Whiteboard Our final method for working was using a private GitHub repo. We didn’t want to have a public one because we didn’t want to spoil things for others, nor did we want to give away any advantage we had or secrets we found. GitHub was very useful for a place for more well defined to do list. We used GitHub issues to track what we still needed to do and chat about who was doing what. Labelling issues helped us to prioritize this to do list so we could make sure to finish up the challenge with the most impactful parts done. All in all, using these collaboration techniques allowed us to be as comprehensive as we could with both the challenge and the end report. Easter EggsA quick list of easter eggs that we found as we were going through the game. Egg Location Reference Notes OHHIMARK LineCon/KringleCon The Room WebSocket Message "Wake up, we're at Grandma's" LineCon/KringleCon MST3k WebSocket Message egg.png LineCon/KringleCon Twitter Egg Logo a-wild-missingno-appears LineCon/KringleCon Pokemon Lethal ForensicELFification Terminal Lethal Forensicator Lethal ForensicELFification Terminal The Raven var i; var lava = document.getElementsByClassName('lava'); for ( i = 0; i < lava.length; i++ )
25 Stall Mucking Argument Hitchhiker's Guide smbwrapper command argumentvar i; var lava = document.getElementsByClassName('lava'); for ( i = 0; i < lava.length; i++ )
26 Stall Mucking Argument Star Wars Holiday Special & 2016 HHC smbwrapper command argument directreindeerflatterystable Stall Mucking Password XKCD KONAMI CODE Yule Log Analysis Konami Code and 2015 HHC In reverse-engineered code Escape from LA Python Terminal Escape from LA movie ("Snake is Back!") Candy Striper CURLing Terminal 2017 HHC EE2 (CranPi Logo) GitLab Old HHCs, Raspberry Pi EE3 (Drawing of Hans) GitLab Die Hard Theo Authorized User Scan-O-Matic Database Die Hard (he was the hacker) Only authorized and enabled user Bill Clay Wannacookie HTML Source Die Hard (Hans' alias) InigoMontoya Vents Code Princess Bride Happy Trails Answer 1 Die Hard John McClane Answer 2 Die Hard Yippee-ki-yay Answer 4 Die Hard 19880715 Answer 5 Die Hard Movie release date Fancy Beaver Answer 7 Fancy Bear APT Group erohetfanu.com Answer 10 Die Hard hansgruber ROT-13 and backwards yippeekiyaa.aaay Answer 11 Die Hard Piano Lock & Rachmaninoff Answer 12 Willy Wonka Many Hans quotes KringleCon Die Hard Toy Soldier quotes KringleCon Die Hard From Hans' German-speaking associates Dungeon for Errant Reindeer Hans Quote 2016 HHC ATNAS Corporation, Miss Cindy Lou Who Hans Quote 2015 HHC Glinda the Good Witch Hans Quote 2017 HHC The Plant Front Door Previous HHCs, psmitty First person to get all challenge coins! Thank YousAs proud as we are to have completed this Holiday Hack Challenge, we would be remiss to not publicly acknowledge a few people outside of this team who helped us during the challenge. Justin Azoff (Corelight): Helped greatly on the as well as some other thoughts and ideas throughout Michael Sinatra (ESnet): Helped us figure out why we were unable to query from Linux/macOS at first (search for noedns for more info) Nick Buraglio (ESnet): Thanks to his time pretending to be Randall from the movie “Clerks” he immediately thought of the musical lock in Charlie and the Chocolate Factory when we were first stuck on that We're also very grateful to SANS for this event, recognizing all the hard work that went into it. But, most of all, we also need to thank our significant others for putting up with our efforts leading to some late nights and busy weekends. We all may need to stop at the florist on the way home today. Appendix 1: Reverse Engineering PyInstaller BinariesOn some of the terminals, we would need to invoke a command, such as dig +noall +answer ANY kringlecon.com 66 and provide the correct answer in order to receive credit for that terminal. Other terminals would automatically invoke a command once a certain condition has been met. Inspecting these files, we discovered that they were standalone Linux ELF binaries, which had been packaged by PyInstaller from a standalone Python script. We wanted to recover the original Python script, and were able to do just that.
Appendix 2: Game Internals: HMACs and Hidden Terminal MessagesIn order to receive credit for successfully completing a game objective, such as a Cranberry Pi terminal challenge, or an objective, HMACs are used. In this section, we'll discuss how they're used, and how we were able to forge these after stealing the keys for some of the challenges. Recovering the HMAC keysAfter one of the dig +noall +answer ANY kringlecon.com 66 binaries on a Cranberry Pi system, we can see how the scripts generate the HMAC: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 89 Each in-game element (terminal, objective, etc.) has a unique resource ID, and each user receives different resource IDs. These IDs are passed to the terminal via a GET parameter. The terminals print a special message, which is hidden by the JavaScript TTY terminal. We can create a bash one-liner to just give ourselves credit for this challenge, without actually solving it: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 90 This duplicates the logic in the Python script. It uses OpenSSL to calculate the HMAC, and then it prints the hidden message, which causes the game to give us credit. Challenge KeysTerminal Direct URL HMAC Key Essential Editor Skills viescape 2bb6b9c702834095a9c3284e053da124 The Name Game pwshmenu 78871929eec84c94806623a086b376f0 Lethal ForensicELFification viminfo 48e41d5cc5e041c0869395bb8cab791e Stall Mucking Report plaintext-creds CURLing Master http2 Yule Log Analysis spray-detect 81013803273d4c58b0e2e5ed869c3677 Dev Ops Fail gitpasshist 32f7f08dbb014bb3a288ecc9ecce1486 Python Escape from LA python_docker_challenge 09f90c21d59845a7b0c972b8e871e8fe The Sleighbell Lottery unlinked-function a6ec0e49731b4c29907422c23794b9a6 Snort snort 4069e612c5d44c69b9ba302ce63968d7 The Sleighbell Lottery key was recovered with kringlecon.com. 599 IN A 104.196.14.143 kringlecon.com. 3599 IN NS ns45.domaincontrol.com. kringlecon.com. 3599 IN NS ns46.domaincontrol.com. kringlecon.com. 3599 IN SOA ns45.domaincontrol.com. dns.jomax.net. 2018121800 28800 7200 604800 600 kringlecon.com. 3599 IN MX 10 aspmx.l.google.com. kringlecon.com. 3599 IN MX 20 alt1.aspmx.l.google.com. kringlecon.com. 3599 IN MX 30 alt2.aspmx.l.google.com. kringlecon.com. 3599 IN MX 40 aspmx2.googlemail.com. kringlecon.com. 3599 IN MX 50 aspmx3.googlemail.com. kringlecon.com. 3599 IN TXT "v=spf1 include:_spf.google.com ~all" 34. As part of this report, we're releasing our scripts and tools at: https://github.com/esnet/sans-holiday-hack-2018 Some select tools, which were mentioned in this report are listed below: Scan-O-MaticWe wrote this simple script to create and upload a QR code: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 91 We wanted to used tools that can automatically map SQL databases, such as ... NetRange: 104.196.0.0 - 104.199.255.255 CIDR: 104.196.0.0/14 NetName: GOOGLE-CLOUD ... 75, but they all use URLs, and not QR codes. So we hacked together this script, which calls the badge shell script, and just acts as a go-between: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 92 CareersUploading a CSV file by hand became old fast, so we wrote this: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 93 It takes a command as an argument, will upload it, and then poll the server to get the result. MalwareWe used the following script to search for other files the malware author may have left on the system: ... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 94 Maze Solver... Domain Name: northpolechristmastown.com Registry Domain ID: 2176618950_DOMAIN_COM-VRSN Registrar WHOIS Server: whois.godaddy.com Registrar URL: http://www.godaddy.com Updated Date: 2017-10-19T19:29:00Z Creation Date: 2017-10-19T19:29:00Z ... Registrant Organization: Counter Hack ... 95 Postscript: Police ReportCase No: 951-262-3062 (Note to filing clerk: make sure to put this in the case number line, NOT the phone number line, this is also Santa Claus’ phone number and it’s easy to confuse) Figure 70: Hans Gruber, person of interest 1988: Kidnapping, Murder, Attempted Grand Larceny - Took hostages at Nakatomi Plaza in an attempt to steal $640 million dollars in bearer bonds Figure 71: Santa Claus, interesting person ~280 AD - 2018: Breaking and entering into homes around the world every winter. Estimates suggest 640 million per year (coincidentally the same amount Hans attempted to steal) |