Simple and Terrifying Encryption Story
A short story about Open Source, trust and responsibility.
See added paragraph at the end of the post.
Problem
I wanted to build an app where users can encrypt and decrypt messages. AES seemed to be a reasonable choice for such a symmetric encryption, so my first step was to find a proper AES library.
Solution
I was programming in Ruby, so I did what every Rubyist would do — I googled “ruby gem aes”. I found a gem called — surprisingly — “aes”, which basic usage is pretty simple:
If you pass a wrong key, aes
gem raises an error:
Bug
When I was developing my new feature, I found something very disturbing. I wrote a test for decoding messages with wrong keys. To be more specific, I replaced the key first char with some other chars (a
, b
, and so on). I expected bad decrypt
error to be raised, obviously. And… my test failed! Not only was nothing raised, but after a quick inspection I discovered that my message was properly decoded:
Ok, I had found some scary edge case, I thought. Like one of a million. So in my next attempt I replaced two chars instead of one:
…and I was still able to decrypt the message. Ouch!
Well, there was only one thing left to do. I tried “totally wrong password”.
At this point it was a critical security issue, so I needed to know exactly what was going on.
Debugging
The problem was caused by the following line in the aes
gem:
First, let’s explain the unpack part. In this case it splits a string into an array of 32 strings (see documentation for more details):
Then, on each of these small strings #hex method is called. String#hex in Ruby converts hexadecimal strings into an integer and if it fails, zero is returned:
Therefore any string without a hexadecimal sequence (like “ff” or “13”) is transformed to an array with 32 zeroes:
As a result it is possible to decrypt messages with almost any key.
I think it’s safe to say that the author expects key to be hexadecimal (or numeric) string. Described critical security issue is probably a consequence of this assumption.
Summary
aes
gem is not a big gem. Currently it has 45 stars and 13 forks. The problem is that it’s the first Google search result for “aes gem” or “ruby aes gem” query and we don’t question top Google results very often. We rarely verify external libraries at all. Apparently it might be a mistake. When it comes to security, a huge one.
EDIT
I want to be clear that my aim wasn’t to blame the gem author. He wrote it a few years ago and couldn’t predict it would end up as the first in search results in 2017. I found an important bug and felt like it’s the right thing to do to share it. This is how I feel about community’s responsibility in Open Source.
Technical details:
- Gem: https://github.com/chicks/aes
- Affected version and revision:
0.5.0
/12c3648
- Sample code
Tap the ❤ button if you found this article useful!
About the Author
Kacper is a Senior Ruby on Rails Developer and Team Leader at EL Passion. You can find him on Twitter.
Find EL Passion on Facebook, Twitter and Instagram.