2021 Way West Hackin’ Fest was a great conference in that it did have something for all attendees (remote or in-person) including its numerous CTFs, labs, workshops, and high-quality talks. As this was my first time attending the conference, I had a great time messing about with the various sponsors and seeing their contributions to the conference. Before the event truly started, I noticed several Red Siege coins invading the various Discord channels, I assumed that it was a indicator that a CTF would be held that the victor would be the proud recipient of a coin themselves.
Now, under normal circumstances I am not a competitive person, but when it comes to receiving a coin forged by the Red Siege team themselves. At that point, I knew I had to win.
Challenge 1: UFO – Metadata
>> Metadata
Metadata is a type of hidden data that describes historical features of a file. This data retains properties that help to answer questions like: how was a file created, who modified a file, when did a user last modify a file, what program created a file? The depth of information varies both by file extension, and the application used to create the file.
This information can be retrieved from a single file with the tool ExifTool. Alternatively, this information can be retrieved from all exposed document files from a single domain with a tool like PowerMeta. PowerMeta does this by scraping multiple search engines to identify a list of Document Files (.docx, .xlsx, .pdf) hosted on a specific domain.
The type of data varies by file type. For example, images can contain an insanely verbose amount of information including the potential for data specifying the camera aperture, original image dimensions, and oftentimes GPS-coordinates.
>> Offensive Methodologies
This data can also be abused by an attacker, as it may reveal usernames, the application that created it, file path disclosures, and other sensitive information. Therefore, it is recommended to automatically purge all files of meta information, (via data sanitization polices, prior to uploading these files to any website or other publicly accessible service to prohibit inadvertent data disclosure.
>> How do we access this information?
payton@OpenSecurity:~$ wget https://redsiege.metacorp.us/problems/ufo.jpg
payton@OpenSecurity:~$ exiftool ufo.png
ExifTool Version Number : 12.05
File Name : ufo.jpg
Directory : .
File Size : 536 kB
File Modification Date/Time : 2021:06:17 01:50:54+00:00
File Access Date/Time : 2021:06:18 02:35:44+00:00
File Inode Change Date/Time : 2021:06:18 02:35:44+00:00
File Permissions : rw-rw-r--
File Type : JPEG
File Type Extension : jpg
MIME Type : image/jpeg
JFIF Version : 1.01
X Resolution : 72
Y Resolution : 72
Exif Byte Order : Big-endian (Motorola, MM)
Image Description : Part1{a740b63}
Resolution Unit : inches
Y Cb Cr Positioning : Centered
GPS Latitude Ref : North
GPS Longitude Ref : West
Image Width : 1024
Image Height : 683
Encoding Process : Progressive DCT, Huffman coding
Bits Per Sample : 8
Color Components : 3
Y Cb Cr Sub Sampling : YCbCr4:4:4 (1 1)
Image Size : 1024x683
Megapixels : 0.699
GPS Latitude : 37 deg 14' 10.83" N
GPS Longitude : 115 deg 48' 50.43" W
GPS Position : 37 deg 14' 10.83" N, 115 deg 48' 50.43" W
Not only has the Exiftool revealed the first solution, but it has also provided undeniable proof that Aliens are located at Area 51 (37 deg 14′ 10.83″ N, 115 deg 48′ 50.43″ W). Arguably, there are few things as important as this indisputable fact.
Challenge 2: SecureVault
>> Initialization
payton@OpenSecurity:~$ wget https://redsiege.metacorp.us/problems/securevault
payton@OpenSecurity:~$ file securevault
securevault: ELF 64-bit LSB shared object, x86-64, ...
The SecureVault is a provided Linux Executable and Linkable Format (elf) file. This is the Linux equivalent of an Executable file (.exe) on Windows. In most configurations, Linux requires the user to manually assign permissions to execute the binary. This can be done with the chmod command to assign the -x (execute) permission to the binary. The user can then execute the file from the current folder with ./securevault.
payton@OpenSecurity:~$ chmod +x securevault
payton@OpenSecurity:~$ ./securevault
payton@OpenSecurity:~$ chmod +x securevault
payton@OpenSecurity:~$ ./securevault
_____ __ __ _ _
/ ____| \ \ / / | || |
| (___ ___ ___ _ _ _ __ ___ \ \ / /__ _ _ _ | || |_
\___ \ / _ \ / __|| | | || '__|/ _ \ \ \/ // _` || | | || || __|
____) || __/| (__ | |_| || | | __/ \ /| (_| || |_| || || |_
|_____/ \___| \___| \__,_||_| \___| \/ \__,_| \__,_||_| \__|
---------------------------------------------------------------------
Please enter your password to decrypt the secret note.
>>
We need to provide a password but we don’t have one. Even worse, I attended the conference remotely, so I can’t even bribe the Red Siege Staff with Open Security stickers. So we will unfortunately, need to hack our way in.
>> Thought Process
The application appears to implement some type of decryption method, and will likely return the flag if we provide the required password. This file likely contains either an abstracted form of the password, a system to solve for the password, or the password itself. We need to dive into the binary, and look for the sensitive string, or methods to retrieve that password.
>> Exploring Inside
The file is a ELF binary, and as a result cat (concatenate), may return portions of the binary file’s ASCII representation, but it could also return nothing, and simply result in a broken terminal session. An alternative solution, would be to use a command to extract ASCII strings from this file. Failing these methods, we may need to employ more advanced disassembly techniques.
payton@OpenSecurity:~$ cat securevault
...
Please enter your password to decrypt the secret note.
>> dolphin_bandit
Correct! Decrypting message
...
payton@OpenSecurity:~$ strings securevault -n 8
...
Please enter your password to decrypt the secret note.
dolphin_bandit
Correct! Decrypting message .
...
>> Why?
It appears that the binary contains a static password. This password is likely checked in a similar statement, resulting in its plaintext storage. As all variable-data is stored as plain-text unless the programmer implements strong hashing or encryption that would permit individuals to access these endpoints.
payton@OpenSecurity:~$ ./securevault
_____ __ __ _ _
/ ____| \ \ / / | || |
| (___ ___ ___ _ _ _ __ ___ \ \ / /__ _ _ _ | || |_
\___ \ / _ \ / __|| | | || '__|/ _ \ \ \/ // _` || | | || || __|
____) || __/| (__ | |_| || | | __/ \ /| (_| || |_| || || |_
|_____/ \___| \___| \__,_||_| \___| \/ \__,_| \__,_||_| \__|
---------------------------------------------------------------------
Please enter your password to decrypt the secret note.
>> dolphin_bandit
That’s all it takes. Halfway to taking home a fungible non-fungible token.
Challenge 3: The Bank
It’s time for a heist! Similar to the previous challenge, the bank requires us to submit valid credentials, and without those credentials we are stuck, both outside the vault, and in this depressing coinless dystopia.
>> Thought Process
Forgetting the basics I assumed that the bank would be a trivial misconfiguration that causes a violation of the OWASP-T10. Initially, I thought that the session cookies were either Insecure Direct Object References (IDORs), or that I could reveal sensitive information, upon rendering the UI by intercepting Packet Responses and returning “success”-ful values. My next thoughts were weakly protected sensitive accounts, and that the account was inadequately secured with a weak password.
Unlike the real world, this was more difficult than a trivial misconfiguration – the credentials weren’t admin:admin! Had I met my match? Was my career over? Confused, I recollected my thoughts, and looked for my attack vector within these dark and confusing times. If only there was a way to achieve credentials from a database, when I have absolutely no information, then it hit me SQL Injection.
>> SQL Injection
SQL Databases operate from a series of operations executed within a query. These queries empower the database to execute commands that perform data manipulation. These commands can be used to execute database operations such as SELECT, UPDATE, INSERT, DELETE, TRUNCATE, DROP, or ALTER.
sql='SELECT * FROM DATABASE WHERE USER = '".$user."' AND PASS = '".$pass."'';
If we can control the data that is embedded into this statement, then we can freely modify the database SELECT queries to request alternate data, or bypass the requirements for a valid password. This injection only works if the modified query is a valid syntax that parses within both the MySQL Driver and PHP.
By providing the following input as the password, this forces the webpage to modify the database query by injecting additional logic to ignore the username and password logic. The new logic implicitly states where (a=”” and b=””) or TRUE. Any provided input will now satisfy the logical expression, and as a result it should always return a row, usually the first row.
$user: admin $pass: ' or 1=1 ;-- sql='SELECT * FROM DATABASE WHERE USER = 'admin' AND PASS = '' or 1=1 ;--';
>> Retrieving “admin”
We have the power! We can perform SQL Injection and this has given us the power to control the world, or at least this website.
As a result we can provide transitions to the data, select subsequent rows, sort the rows, or even in some cases implement custom filters via conditional selectors.
- We can offset the pointer to select the next or previous row
A. LIMIT 1 OFFSET [ID]
- We can sort the data by ascending or descending to try to access the first or last rows.
A. ORDER BY [column_name] ASC **Requires valid column name
B. ORDER BY [column_name] DESC **Requires valid column name - We could implement additional filters and attempt to filter for any known column name.
A. OR (1=1 AND [column_name]=’admin’) **Requires valid column and valid case-sensitive value.
Each statement has their own benefits, but if you can achieve a single SQLI, you can modify it to perform any of the above actions with relative ease. It is worth noting that ORDER BY and Filtering both require additional information that can be retrieved from Error Information Disclosures, or simply guessing.
>> Execution Authentication
For this challenge we will be using Burp Suite as an Intercepting Proxy. The free community edition contains all of the modules necessary for this challenge.
Navigate to the website and intercept the POST request to /problems/bank/api?a=login. It should have the requested username and password in the body of the request.
Next, we will want to send this to Repeater either by hitting Control+R on Windows, or right clicking on the request and choosing to send it to Repeater.
Repeater is a powerful tool as it allows the submission of multiple fuzzed requests. Being able to modify these requests, and immediately view the response, eases exploit development, especially against live websites.
At any point we can select “Send” to send the request, to view the server’s response on the right side.
From the response (on the right), we have successfully performed a trivial SQL Injection, and retrieved some information pertaining to Adalynn’s user account. Further investigation (either blind or through error information disclosure) shows that we can manipulate this request, and use the following methodologies to select other rows.
username=test&password=' or 1=1 ORDER BY user_id DESC ; -- username=test&password=' or (1=1 and user_name=admin) ; -- username=test&password=' or 1=1 ORDER BY user_id ASC OFFSET 4; --
Our payload is effective at retrieving the required data. Since the exploit works, we can test it by injecting these body parameters back into the original request, and test how the original website reacts to our retrieval of valid data. Hitting Forward in the Proxy tab permits the transmission of this newly modified request.
>> Attacking 2-Factor Authentication
Providing this input to the application retrieves a new input for a 2FA token. Intercepting the submission of 111111, shows a new request to a simple endpoint /problems/bank/api?a=checkmfa.
Intercepting the request reveals the following data.
mfa_in=111111&mfa_correct=299012&password=test&user_id=1337
We can see that mfa_in is the value that we are supplying to the application, and appears that mfa_correct is the expected value, for simplicity let’s set both of these values equal to the value of mfa_correct to satisfy any conditional checks with these values.
Sending the request to the application via Repeater, discloses that the data is not valid. This error is most likely because the submitted password is invalid. If only there was a way to login without the account’s password. Oh wait. We already figured this out!
Injecting any of the previous SQL Injection payloads as a value of password and resubmitting the request retrieves valid account information, and the sensitive flag.
>> Debugging
How do we identify SQL Injection, and how to we modify this to work in these particular statements? If we find a way to break the query, for instance sending a single quote ( ‘ ). This indicates that not only is this service insecure, but it will also likely respond with incredibly verbose error disclosures. This application will respond with the following information disclosure, oftentimes disclosing the query, including table and column names. This information oftentimes eases payload creation.
---------------------------
Error [2] on line 57:
SQLite3::querySingle(): Unable to prepare statement: 1, unrecognized token: "'''"
52 | // Verify MFA code
53 | if ($_POST["mfa_in"] != $_POST["mfa_correct"]) {
54 | $out["message"] = "Invalid code. Please try again.";
55 | } else {
56>>>| $result = $db->querySingle("SELECT first_name, last_name, username, savings_balance, checking_balance, personal_note, savings_account_id, checking_account_id, session_string FROM users WHERE user_id='" . addslashes($_POST["user_id"]) ."' AND password='" . $_POST["password"] ."'", true);
57 | if ($result && count($result) > 0) {
58 | $out["success"] = true;
59 | $out = array_merge($out, $result);
60 | } else {
61 | $out["message"] = "An error has occured. Please try again later";
62 | }
---------------------------
{"success":false,"message":"An error has occured. Please try again later"}
>> Dumping Records
RETRIEVE ALL OF THE DATA! By sending the MFA request to Burp Suite Intruder (control+I on Windows). Clearing all of the injection points, and update the OFFSET value, as the only payload position, by highlighting the 0 after OFFSET, and choosing “Add”.
PS C:\> 0..100 |% { echo $_ >> numbers.txt}
Running the above PowerShell command will create a file in the current directory with the name numbers.txt with values of 0 to 100, then selecting the Payload tab, and loading this list into the application, will allow us to systematically retrieve all records from the Application.
Burp Suite Intruder Results
We can then use the response lengths to identify the variations in response sizes, indicating that various unique data records are being retrieved. In this case it appears there are 5 total records in the Database.
>> Stealing Passwords
Would it be possible to retrieve passwords?
In the information disclosures that retrieve the queries. None of the queries are structured in a way that would immediately retrieve the individuals passwords from the database.
But with a little bit of deeply cursed SQL magic we can simply embed a new UNION ALL SELECTion to retrieve the passwords, and injecting the following parameter, with the previous intruder attack retrieves the following data.
SQL Injection:
' union all SELECT username,password from users LIMIT 1 OFFSET {val} ; --
Retrieved Credentials:
- awyndham:n9Faym$6KQJ5f
- e_burnham:5hNyU9jq%TqXwfWrR
- hurstj1:7NSQ!y2jKCcW
- clay1977:h@YkrGguSK
- admin:D8WvXHbFBs75!wNjd
>> Summary
SQL Injection permits an attacker access to effectively everything. Full control of the database, and commonly additional access. While, this depends heavily on configuration, it can lead to arbitrary read, write, and command execution. This is very dependent on server configuration, database version, and vendor. However, the implications of SQLI can be disastrous.
Challenge 4: Wireshark
Wireshark is a powerful tool for network recording and analysis and in most cases the recommended software to open and examine a PCAP (Packet Capture Data File) for it’s versatility and ease of use.
Opening the file we can identify that there are two types of protocols in use within the recorded traffic, TCP and HTTP.
>> Follow TCP Streams
Right-clicking on a TCP Entry -> Follow -> TCP Streams. (or Ctrl + Alt + Shift + T) enables you to view the packets transferred in a form that resembles a conversation.
The client messages are on the left, the client that recorded the traffic, while the server messages are on the right. Sifting through this information we can see what appears to be an adversary’s shell sending commands, and receiving responses. This visualization enables us to view the commands that an adversary sent, and begin to analyze what actions the adversary performed with this connection.
>> Extracting Files
Another extremely powerful mechanism in Wireshark is the ability to extract files from Network History (File -> Export Objects -> HTTP). This will extract all files that were cached in the Recorded Traffic over HTTP.
Choosing Save or Save All will extract the contents from any HTTP Requests (in this case Payload.zip). The only issue is this file is password protected. Unfortunately, we cannot bypass the protections via file manipulation. We must instead identify the file’s password for this challenge. If the password was not easily identifiable, it is possible to attempt a bruteforce that may or may not work, depending on complexity.
We need to take a step back, and think! Where did this zip file come from? Looking at the previously identified Wireshark TCP Traffic, we can see that it is the attacker’s file was downloaded from an untrusted server, the attacker then unzips this file with the command line using a very long parameter.
And with that the final flag is revealed, and at this point we should have all the information needed to solve this collection of challenges. Concatenate the contents of each flag, and decrypt the final challenge only then will you recover the secret phrase.
That’s it folks, with that final simple password we have done it, and have become the proud recipient of a coin. How close were you to receiving a coin this year? I hear the a new competition is in the works for Wild West Hackin’ Fest. Rumor has it that there will be more chances to win a coin but there will be even more competition.