In the world of programmers, it has always been a real battle when dealing with user inputs. From the low C handling to
the very high modern typed language, they surely contain injection problems. There is no assurance possible when releasing a software that it can't be abused by anyone. With low language, it becomes a nightmare to handle and filter inputs. You will have to ensure length is correct, data is correct, copy does not overflow, usage does not overflow, anything does not overflow ... And with highly typed language that handle everything for you, they are still vulnerable.
As you can find a ton of documentation about how to do the evil, today we will showcase some of the most popular injections as an education purpose and for fun and profit. This will not be the biggest or more complex, but simply three examples that I picked out.
Remember HeartBleed? No, well heartbleed was a security bug disclosed in April 2014 in the OpenSSL cryptography library,
which is a widely used implementation of the Transport Layer Security (TLS) protocol. OpenSSL is known to be one of the
most security oriented code, and yet, this very basic issue escape through all the code control.
I said basic because, in the main idea, it is a simple trivial buffer over-read. The bug touches the implementation of
heartbeat that is a handshake exchange to see if the server is still alive. It goes like this:
_ Client: Server, if you are still alive answer with this 3 letters: "foo"
_ Server: I'm alive: [foo]
The problem was that the client send the length of the data, and the server blindly trust it. So if one client said:
_ BadGuy: Server, if you are still alive answer with this 100 letters: "foo"
_ Server: I'm alive: [fooâbarÔ´@’þÀ password: alick âÅê¦d....]
The server returns a raw series of bytes after our string and exposes his memory. When running this multiple times with a
much larger length, one could have read important information from the memory stack of openSSL. This is pretty bad.
The lines of code that made everyone fears for their security was these one:
/* Enter response type, length and copy payload */
*bp++ = TLS1_HB_RESPONSE;
memcpy(bp, pl, payload);
payload is the message receive from the client and what the server should return.
bp is a pointer to the start of the response, the code writes the type
TLS1_HB_RESPONSE and move the pointer to the next byte.
s2n write the 16-bit payload length to memory and increment the buffer pointer by two bytes.
memcpy copies payload number of bytes from the received payload into the outgoing payload for the reply.
There is no control over the payload length more that it is 64KB maximum, even if the data sends is not that size.
So if the actual HeartbeatMessage sent by the attacker only has a payload of, say, one byte, and its payload_length is
a lie, then the above memcpy() will read beyond the end of the received HeartbeatMessage and start reading from the
victim process's memory.
Once disclosed, OpenSSL was rapidly patched, but everyone started to panic as nobody could have known if their server had been compromised.
In doubt, anyone is strongly advice to update to the lastest version of OpenSSl and regenerate password and ssl keys.
This one is particularly fun because the author is well known (he posts his adventure on his blog) and he did one of the largest attack in social media website by accident.
Yep, you read right, accident ... As he did not expect to cause such a mess and expand that quickly
For the younger reader, Myspace is a platform that allow one to have his personal web page with a profile and friend. Similar to facebook later on, but it also has the possibility to customize content and style of the page.
Samy was a lonely genius, one night of the year 2005, he goes to his Myspace and notice that he had not so many friend and even less interaction with them. So what he did was to use a XSS worm to change the profile of the victim and write "but most of all, samy is my hero" and force the victim to add him as a friend. He proudly succeed, anyone who saw his profile got infected.
That was already a highly villainous trick, but Samy wanted more. What if all the infected account can also change the profile of the viewers. That's where it got crazy.
What Samy did not know is that this kind of propagation goes fast, like very very fast. And that was the accident.
One thing to understand is that in this kind of very popular social website everyone is highly connected. Even the lonely guy who just create an account to stalk women or this old granny who never used her account are really close. Facebook for instance did some statistics on all of their users and conclude that 92% of them are connected to just five steps and this number is decreasing though time.
In real live it applies too, but it is way more difficult to prove, if you want to learn about it is called the six degrees of separation.
In 17 hours Samy add more than a million people saying that he is their hero, Samy was happy as 1/35th of all Myspace users loved him. Shortly after Myspace put their servers in maintenance and fix as soon as they could the problem, roll backing the data before any infection. Samy got evicted and could not touch a computer for three years after that.
For the bit of technical part, what Samy did was abusing the parser to include scripts.
Myspace only allowed a limited set of html block to work like
<a>, <img>, <div>. Of course, they blocked any
<script> tag or onclick attribute and so on.
Next, using some trick like
fromCharCode and concatenating strings Samy was able to let the browser download the victim profile, get their id, post a newaddFriend request and do his evil.
If you want to see more about Samy and his story and code, I recommend you to get to his old personal blog where he details the how in an unique and fun article: http://namb.la/popular/
And after all, Samy is my hero.
Github have an api and back in 2014 it had a major issue that allow anyone to connect as anybody.
It did not make a lot of noise has it was reported in silence through their bug report program, but it is possible that some account where abused before it was fixed. Also, for the record, it is very likely that some website still have this issue as it isn't a very popular injection.
The problem touches two components used by Github, MySQL that is used as their main database and Ruby On Rails on which was coded the Github public API.
Let's start with mysql and try to guess what will return the next queries:
SELECT 1 as result WHERE 0 = 0;
SELECT 1 as result WHERE 0 = 1;
SELECT 1 as result WHERE 0 = "0";
SELECT 1 as result WHERE 0 = "1";
SELECT 1 as result WHERE 0 = "1azerty";
SELECT 1 as result WHERE 0 = "0azerty"
SELECT 1 as result WHERE 0 = "azerty"; ***
SELECT 1 as result WHERE 1 = 0;
SELECT 1 as result WHERE 1 = 1;
SELECT 1 as result WHERE 1 = "0";
SELECT 1 as result WHERE 1 = "1";
SELECT 1 as result WHERE 1 = "1azerty";
SELECT 1 as result WHERE 1 = "0azerty"
SELECT 1 as result WHERE 1 = "azerty";
(Answers in your favorite MySQL server :P)
A hint, the one with the * will produce a 1, and is what cause the trouble.
The type casting of MySQL is behaving really strangely and is not a natural way of comparing integers and strings, so without knowing these cases, it is a common pitfall for any unaware developers.
The Ruby On Rails problem was on how Rails handle body of POST requests. By default JSON and XML are supported, while JSON does not cause any trouble for github, XML with his typed syntax taht normaly is an assurance of security for every SOAP lovers :wink: is here a source of nightmares.
When deserializing XML, the parser includes support for other types like integers and floats but also more dangerous type like symbol and yaml. If you have a Rails application, you may want to look for the last two type as they are very unsafe.
But for our Github case, only integers are interesting.
By sending a token as an integer with value 0, it was possible to bypass the whole authentication mechanism. Life is sometime that simple...
Also notice that JSON allow to pass integers, but for that part it wasn't working on Github API, still be safe and refuse any type that should not be in some user inputs.
We saw three differents security breach on different systems. Some of them are still common on other applications and the goal of this article is to entertained and raised awarness of these issues. I hope that you will learn and be sure to securise your great projects.
As always, code safe.