Originally posted on antoinettestevens.com
I finally made it back to SecDSM after missing a month. I don't have a solution for February's MiniCTF, but it involved machine learning, CAPTCHA brute-forcing, and scripting. Unfortunately, I was busy preparing for a large event that I planned on March 1 and didn't have time to dedicate obsess over this challenge even though I found it really interesting.
The March SecDSM MiniCTF was a lot of fun and I learned about AWS cli and the importance of making sure you're using the most up-to-date versions of a tool. Let's take a look together. I'll try my best to walk through this and explain the thought patterns that I had as I go along. I should preface this by saying that I have never worked with AWS before. I've only read about it and saw a talk once at a security conference.
Recon
Visiting http[s]://portfolio[.]xbcw[.]net shows a fairly innocuous website. There aren't any fields to input text so I immediately ruled out about half of the web exploits that I know of, mostly injections. The only thing to do is begin browsing around the site. I use a Chrome browser, so I tend to browse with 'Inspect' open to look at files and network connections. I try to see if there's a robots.txt and get an error in the form of an XML files. That seemed weird to me since I usually just get a normal 404 page if a page doesn't exist. Moving on, I noticed that the icons at the top are for LinkedIn (doesn't go anywhere), a Github Repo, and a link to a PDF resume. I look at the PDF and don't see anything particularly special. I decided to begin inspecting the Github repo because I figured I'd be able to find out more about the deployed code, if nothing else.
The README for the repo is uninteresting, so I started clicking through files without really knowing what I was looking for or where to start. After a few minutes, I decided to go through the commits. I can't fully rationalize why, other than saying that I figured it would be helpful to know what the repo owner changed or removed just in case it gave me a hint about what I should look for on the website. At this point, I still don't know it's AWS.
Going through the commits on the repo and dots start to connect as I realize there are some very interesting things hidden in the commits for this project.
The first thing I found was this:
Now, I didn't know what it meant but the word 'bucket' is how I knew we were dealing with AWS. In the future I'll probably be able to recognize it faster but, in that moment, that's what did it. ¯_(ツ)_/¯
I hear about Amazon S3 Buckets being improperly configured and vulnerable all of the time. It's a popular topic among developers, so I knew this would probably be something like that. Whenever I feel like I have a pretty strong grasp on my goal, my next step is always to Google it. That resulted in me finding an article from Rhino Security Labs, Penetration Testing AWS Storage: Kicking the S3 Bucket.
I browsed to the S3 URL and find XML listing all of the content for this bucket...including a file called secrets.zip.
I do a wget on that zip file (you need pzip) and find out that it is password protected. A strings
on the zip will reveal that there is a file called secrets.txt, but nothing resembling a password here. This is where things get rocky for me.
Random observations from recon:
- Somewhere in this I tried Wireshark. It wasn't until I was filtering the IP address that I remembered that it was useless because the site is HTTPS and the traffic is encrypted.
- While looking at the code, I noticed that the names of the images used on the webpage were named things like "gotcha", just in case people thought the images were a steg challenge I'm assuming. #The Exploit(?)
A lot of people's first instinct when faced with a password prompt is brute forcing it. In all of the CTFs I've seen (not that many really), they will usually do one of two things if they want you to brute force. They'll either provide (or hide it somewhere for you to find) you with a wordlist or make some type of pun about a popular wordlist. Otherwise, brute forcing usually isn't the answer. Check out this article from Better Buys to learn about the time it takes to attempt to blindly brute force a password.
Looking back at the commit I found for lambda-upload-portfolio.py, there's a comment that mentions that the password "will be in the parameter store under the filename". I have NO CLUE what that means, so I Google again and eventually find an article on Medium explaining how to access the parameter store. It's exactly what I need. I go to the AWS CLI (installed somewhere in this process with apt-get) and I get an error saying I have to run aws configure
first. The aws configure
command requires me to know the access key ID and access key secret for the S3 bucket. Well Shit. I don't know that or how to find it. I go back to looking around the Git commits after minutes of banging my head against the wall, thinking maybe I missed something. And then...
And this is why you should always be very careful when committing to a public repository. Oh well. Now I can configure the AWS CLI and do what I need to do. I follow the instructions from the Medium blog and run into a problem. get-parameters
is missing. It doesn't exist. I figure that I must be doing something wrong and try other things with no luck. Eventually someone else gets the flag before I do and they mention that they used get-parameters
.
I run aws --version
and sure enough I'm not using the most up-to-date version, the version I'm using doesn't have the get-parameters
command and other commands yet. When I got home I uninstalled awscli completely, updated my repos, added the suggested repo from the awscli documentation, and reinstalled awscli. I could finally see the get-parameters
command.
antoinette@dev:~/secdsm/march$ aws ssm get-parameters --names secrets.zip
{
"InvalidParameters": [],
"Parameters": [
{
"Version": 1,
"Type": "String",
"Name": "secrets.zip",
"Value": "Dodongo Dislikes Smoke"
}
]
}
While reading about Parameter Stores, I learned that the parameter store will store values in key:value pairs. The --names
flag on the command is 'secrets.zip' because the comment in the python script mentioned that the pw was under the filename. Meaning in a key:value pair, the filename was the key and the pw was the value.
Finally, I pasted the password, unzipped the file, and printed it out the contents of secrets.txt.
antoinette@dev:~/secdsm/march$ cat secrets.txt
flag{iTsAsecReTtoEverYBodY}
Moral of the story: Make sure your programs are the latest version so that you don't get screwed.
Oh well. You win some. You lose some. Hope you found this helpful! Leave your questions and comments below.
Top comments (2)
Wow, that was an awesome read. Thanks for bringing us through it step-by-step -- cool to understand your train of thought while approaching this problem!
Awesome write-up. It reads like a mystery novel unwrapping itself, and the first person really adds to the suspense.
Thanks for sharing!