Definitively Not( James )

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?