Verizon DBIR Puzzle 2016
May 9, 2016
I’ve been watching my brother solve various crypto puzzles here and there on the internet for years. So, I figured I’d give one a shot—I mean, if he could do it, how difficult could it really be? Spoiler: It was a giant pain in the ass.
My brother is into puzzles, he goes to ‘cons’ all over the country to have a go at hacking badges and cracking codes—apparently he’s pretty good at it. One puzzle in particular I see him talk about every year is the Verizon DBIR Cover Challenge. Basically, when Verizon releases its annual Data Breach Investigation Report, they embed a clue or two on the front and/or back covers that are the start to a long and winding puzzle—eventually leading to denial, isolation, anger, bargaining, depression, and acceptance—not necessarily in that order.
When I found out my brother wasn’t going to be competing in the #DBIRPuzzle this year, I figured I’d give it a shot. This was my first mistake.
I won’t go into the whole twisted tale here, the third place winner Matthew Keyser has a good writeup of most of the journey. Like him, I found the hidden text on the back cover, the morse code on the front, and ended up at the Cyber CDC Global page trying to solve as many of the mini puzzles as I could. I ended up solving six out of the nine:
After getting 4 recruits and assembling my team, the Cyber Pathogen spit out an ‘infection log’. I took a quick look at it, realized I had no fucking clue what was going on there (aside from the generic descriptions in the first row) and quickly set it aside. When I hit 5 recruits and grabbed the second version of the log, I ran a quick diff between the two files and landed on 11 records that I assumed must contain patient zero. A quick Google for the first hash in the first record revealed a pastebin of all victims. I filled in what I could and quickly realized that ‘otiliawilliamson’ was the ‘node’ in all 11 records.
I don’t know how Cyber Pathogen’s are supposed to work, but Otilia seemed pretty involved to me. I thought about submitting a guess naming her as patient zero but a simple diff and a quick Google search seemed way too easy for it to be correct—I reached out to my brother to see what he thought.
Now, I should mention here that apparently my brother was somewhat involved in crafting the 2016 DBIR Puzzle.
I knew that he had been working on some component of the larger puzzle—he mentioned something about audio tones over Easter—but that was all I knew. I’m still not sure of what all he was or wasn’t responsible for, or what he did or did not know—but he agreed that Otilia seemed too easy to be correct. So I set the logs aside again and started working on the one puzzle I’d spend the rest of my time banging my head against: Dr. Tipton.
The Strange Case of Dr. Tipton
The first Tipton clue I saw mentioned by the @Cyber_CDC Twitter account was: ‘Dr. Pedro Tipton is a brilliant researcher but his contributions often remain in the background’. I immediately grabbed the full image from his bio on the Cyber CDC website (a photo of him standing in front of a cluttered whiteboard) and had a look. After some Googling of the text scribbled on the whiteboard, I found the original image and noted that the only addition was the good Doctor himself, and the string of text on the left hand side.
My immediate reaction upon focusing on the added text was:
“It’s DNA, duh. I saw GATTACA—this shouldn’t be a problem.”
I wasn’t sure how the x’s figured into it—I thought maybe one section was a key and the other was encoded text, I decided to consider them both separately until I learned more.
I figured A goes with T and G goes with C, I must be able to convert it to binary. I considered one base pair as 0 and the other as 1, then tried to convert it to ASCII: Nope. I switched the assignment around and tried it again: Nope. I created a new string of nucleobases that would pair up with the existing string, converted that to binary, then tried to convert that to ASCII: Nope. I looked at the original string, squinted hard, and tried morse code: Nope. I gave up.
I stumbled upon some random DNA encode/decode schemes and tried to run the string though them: Nope. I tried reversing the binary string: Nope. I tried a bunch of other stuff I’m too ashamed to admit to: Nope. Eventually, I came to the conclusion that the string I was starting with was no good. I gave up.
I saw a Tweet from @mattjay, who would go on to be the 1st place winner, which mentioned all the printing and cutting he was doing. Then I saw the second Tipton clue from the @Cyber_CDC account, it mentioned that “sometimes a puzzle starts with a puzzle”. I gave in and started back at the beginning, printing and cutting out each row of the text and looking for patterns.
Eventually, I saw it. Each row overlapped with another, forming one single string. I fit them all together, copied out the new string of nucleobases and ran it through all the previous attempts mentioned above: Nope. I gave up.
I was pretty confident I had the right nucleobase string at this point, but was still stuck—then another idea occurred to me. I split the string into two equal rows and applied a kind of anti XOR type operation to each column—base pairings resulting in a 1 and misses resulting in a 0: Nope. I reversed the assignment: Nope. I gave up.
The third and final Tipton clue from the @Cyber_CDC account, unlocked it all for me: “Tipton thinks that pyrimidines are #1”. After a quick Google I learned that two of the four nucleobases found in DNA were pyrimidine derivatives, Cytosine and Thymine (obviously). I converted the string to binary one last time, assigning a 1 for each C or T and a 0 for each A or G. Then I converted the binary to ASCII, and I finally had my answer: ‘primenumber’.
After assembling my team of 6 and getting the third and final log, I quickly looked again for the ‘otiliawilliamson’ hash but found she was all over the place, and of no help. I then looked for the ‘enc_data’ string shared by all of the original 11 records I was focused on—this looked like a base64 string to me but I was never able to figure out what it was. Finding those 11 records again in the new log, I was able to see that they all shared the same ‘infected_by’ hash: ‘206e52ca829a42776c8b7b9c81cfd061’. A quick Google found the Hash Killer Site containing both the hash and the original text: ‘kevinthompson’ i.e. patient zero.
I submitted my guess, but missed 1st place by 40 minutes or so. Second place isn’t so bad.
This was a lot of fun, and I’d do it again—maybe, probably not. It’s easy to see how I could have done better. I held on to assumptions, way past the point I should have abandoned them and looked for a new thread to pull on. Time and time again, I ran down the first path I found rather than staying where my assumptions were solid and gathering more information. Still, it was lots of fun—sometimes frustrating—but mostly fun.
Geometry Club at the National Arboretum
TL/DR: it’s amazing.
As you can see, the italic style is strikingly different—I’ve been toying with using this style for tag labels, and when templating with Liquid I find it actually works rather well. Now, let’s be clear: spending $180 on a typeface for your text editor is pretty close to the height of privilege. When my free trial runs out, I doubt I’ll buy it outright—but if I was going to throw around cash like that on typefaces, Operator Mono would be at the top of the list.
Environment Variables, Bundler Groups, and Jekyll
Oh my. If you’re working with Jekyll and rolling your own build and deployment process, chances are you’re slowly but surely accumulating sundry plugins, gems, and build scripts. Some of these are for local development, some are for deploying your site, some are for both—but configured differently for each. How do you manage all this? Bundler groups and environment variables are here to help.
JEKYll_ENV. It defaults to
"development" and you can set it when building or serving e.g.
JEKYLL_ENV=production jekyll build. Most plugins like Jekyll-Assets will look for the variable and act accordingly—only compressing and digesting in production, etc. The variable is also available in your templates at
jekyll.environment so you can include and exclude things as appropriate.
When it comes to managing your site’s dependencies for a given environment, Bundler’s groups can help out. Organize your Gemfile into the approprate groups to make sure you’re loading the right gems when you need them.
source 'https://rubygems.org' gem 'github-pages' gem 'jekyll-paginate' group :development do gem 'guard' gem 'guard-livereload' end group :production do gem 'rake' gem 'uglifier' end
This is especially helpful when using something like a continuous integration service to build and deploy your site. By passing in the
--without development flag as a bundler argument you can leave those gems behind and not bother loading them onto the build server since you don’t need them.
Jekyll and Continuous Integration with Travis CI
Using GitHub Pages to host your Jekyll site is great—it’s fast, secure, and free (as in beer)—but it’s also restrictive. There’s a whitelist of plugins Jekyll can build with, but it’s pretty limited. If you want to run your own plugins or post build scripts there’s no automated way to do that.
Of course, you could just build the site locally, and then deploy it—but if the site is for a client, or if you’re collaborating with others, that’s not really going to be sustainable.
One way around GitHub’s restrictions that I’ve been considering lately is using a continuous integration service like Travis CI. Basically, Travis looks for updates to a GitHub repo, clones the given branch, builds the site, runs any post-build scripts you want, and then commits the site straight to the GH-Pages branch for hosting.
This lets authors and content managers, using something like Siteleaf, add content as they wish—when they hit publish and the changes are sync’d to the repo, Travis takes over, builds the site, and then deploys it back to GitHub. Travis is primarily used for testing code in pull requests before merging it with a master branch. If we wanted to include tests into our workflow we could, but I’m mostly just interested in using it to build and deploy.
There are a couple hoops to jump through to get this all working. As an example, you can see the files I’m using with Travis to generate this very site below:
- Setup a Travis CI account
- Enable the repository you want it to work with. You can set it to build on pushes, pulls or both.
- Add a travis.yml file to the root of your repo. The file will tell Travis how to build and deploy. Travis will run a bundle install before getting started so make sure any gems you need are in your Gemfile.
- Add a deploy.sh script that Travis will use to commit the build directory to the gh-pages branch of the repo.
- You’ll also need to generate a personal access token with GitHub and use it to set a GITHUB_URL environment variable in Travis. This will point to the remote repo to be used when Travis commits the built site. e.g.: https://[personal-access-token]@github.com/username/repo.git
That’s it, mostly. As always, there are a few landmines to look out for. You want to make sure that your _config.yml file excludes the vendor directory, or Jekyll will try to include those when it builds. Also, if you’re having Travis install any Node dependencies you will want to exclude them as well.