2021/03/03
The “far right” social media platform, Gab, was breached sometime last month and had public messages, private messages and password hashes leaked on March 1st.
Let’s ignore the… uh… unprofessional (to put it lightly) statement the founder made and how they responded to this event in general. It’s not worth unpacking all of that. It really isn’t. I promise you.
Instead, let’s chat about how this happened. It’s pretty simple.
The site in question had a commit from the Gab CTO which migrated a specific SQL query away from the library abstraction SQL and into raw SQL - the query language used to interact more directly with their database. This is often done because a custom SQL query can often be used to greatly improve performance.
However…
As part of this, they used string interpolation do craft the query. String
interpolation is kinda like saying VARIABLE_U
is james
and I want to
interpolate that into SELECT * FROM user WHERE username = '$VARIABLE_U'
so
that I end up with the final string of SELECT * FROM WHERE username = 'james'
.
Simple, right?
This way of crafting SQL can fail because of what is known as
SQL Injection. In our example, what if VARIABLE_U
was coming from an
input field on a website? In that case, a user could type whatever they wanted
into that field.
If a user was to type in ' OR 'a' = 'a
, the final string would then look
something like SELECT * FROM user WHERE username = '' OR 'a' = 'a'
.
Instead of limiting to a single username
value, we’d instead retrieve any
users.
This can be elaborated on to do even more - such as with Blind SQL Injection techniques.
How should they instead of handled this? By using the library to “bind” parameters. Ruby on Rails supports this in the function used by the change that caused the breach.
In our example, we could instead write the query as
SELECT * FROM user WHERE username = ?
and then tell the library to bind
VARIABLE_U
to the first numbered parameter. No string interpolation would
be performed, and with most databases the query would be sent over completely
separate from the bound parameters!
This should have been caught in code review. I mean.. if they do code review, right?