Even if you’ve only loosely followed the events of the hacker groups
Anonymous and LulzSec, you’ve probably heard about web sites and
services being hacked, like the infamous Sony hacks. Have you ever
wondered how they do it?
There are a number of tools and techniques that these groups use, and
while we’re not trying to give you a manual to do this yourself, it’s
useful to understand what’s going on. Two of the attacks you
consistently hear about them using are “(Distributed) Denial of Service”
(DDoS) and “SQL Injections” (SQLI). Here’s how they work.
Image by xkcd
Denial of Service Attack
What is it?
A “denial of service” (sometimes called a “distributed denial of
service” or DDoS) attack occurs when a system, in this case a web
server, receives so many requests at one time that the server resources
are overloaded the system simply locks up and shuts down. The goal and
result of a successful DDoS attack is the websites on the target server
are unavailable to legitimate traffic requests.
How does it work?
The logistics of a DDoS attack may be best explained by an example.
Imagine a million people (the attackers) get together with the goal
of hampering Company X’s business by taking down their call center. The
attackers coordinate so that on Tuesday at 9 AM they will all call
Company X’s phone number. Most likely, Company X’s phone system will not
be able to handle a million calls at once so all the incoming lines
will tied up by the attackers. The result is that legitimate customer
calls (i.e. those that are not the attackers) do not get through because
the phone system is tied up handling the calls from the attackers. So
in essence Company X is potentially losing business due to the
legitimate requests being unable to get through.
A DDoS attack on a web server works exactly the same way. Because
there is virtually no way to know what traffic is sourced from
legitimate requests vs. attackers until the web server is processing the
request, this type of attack is typically very effective.
Executing the attack
Due to the “brute force” nature of a DDoS attack, you need to have
lots of computers all coordinated to attack at the same time. Revisiting
our call center example, this would require all the attackers to both
know to call at 9 AM and actually call at that time. While this
principle certainly will work when it comes to attacking a web server,
it becomes significantly easier when zombie computers, instead of actual
manned computers, are utilized.
As you probably know, there are lots of variants of malware and
trojans which, once on your system, lie dormant and occasionally “phone
home” for instructions. One of these instructions could, for example, be
to send repeated requests to Company X’s web server at 9 AM. So with a
single update to the home location of the respective malware, a single
attacker can instantly coordinate hundreds of thousands of compromised
computers to perform a massive DDoS attack.
The beauty of utilizing zombie computers is not only in its
effectiveness, but also in its anonymity as the attacker doesn’t
actually have to use their computer at all to execute the attack.
SQL Injection Attack
What is it?
A “SQL injection” (SQLI) attack is an exploit that takes advantage of
poor web development techniques and, typically combined with, faulty
database security. The result of a successful attack can range from
impersonating a user account to a complete compromise of the respective
database or server. Unlike a DDoS attack, an SQLI attack is completely
and easily preventable if a web application is appropriately programmed.
Executing the attack
Whenever you login to a web site and enter your user name and
password, in order to test your credentials the web application may run a
query like the following:
SELECT UserID FROM Users WHERE UserName='myuser' AND Password='mypass';
Note: string values in a SQL query must be enclosed in single quotes which is why they appear around the user entered values.
So the combination of the entered user name (myuser) and password
(mypass) must match an entry in the Users table in order for a UserID to
be returned. If there is no match, no UserID is returned so the login
credentials are invalid. While a particular implementation may differ,
the mechanics are pretty standard.
So now let’s look at a template authentication query which we can substitute the values the user enters on the web form:
SELECT UserID FROM Users WHERE UserName=’[user]‘ AND Password=’[pass]‘
At first glance this may seem like a straightforward and logical step
for easily validating users, however if a simple substitution of the
user entered values is performed on this template, it is susceptible to
an SQLI attack.
For example, suppose “myuser’–” is entered in the user name field and
“wrongpass” is entered in the password. Using simple substitution in
our template query, we would get this:
SELECT UserID FROM Users WHERE UserName='myuser'--' AND Password='wrongpass'
A key to this statement is the inclusion of the two dashes
(--)
.
This is the begin comment token for SQL statements, so anything
appearing after the two dashes (inclusive) will be ignored. Essentially,
the above query is executed by the database as:
SELECT UserID FROM Users WHERE UserName='myuser'
The glaring omission here is the lack of the password check. By
including the two dashes as part of the user field, we completely
bypassed the password check condition and were able to login as “myuser”
without knowing the respective password. This act of manipulating the
query to produce unintended results is a SQL injection attack.
What damage can be done?
A SQL injection attack is caused by negligent and irresponsible
application coding and is completely preventable (which we will cover in
a moment), however the extent of the damage which can be done depends
on the database setup. In order for a web application to communicate
with the backend database, the application must supply a login to the
database (note, this is different than a user login to the web site
itself). Depending on what permissions the web application requires,
this respective database account can require anything from read/write
permission in existing tables only to full database access. If this
isn’t clear now, a few examples should help provide some clarity.
Based on the above example, you can see that by entering, for example,
"youruser'--", "admin'--"
or any other user name, we can instantly login to the site as that user
without knowing the password. Once we are in the system doesn’t know we
are not actually that user so we have full access to the respective
account. Database permissions will not provide a safety net for this
because, typically, a web site must have at least read/write access to
its respective database.
Now let’s assume the web site has full control of its respective
database which gives the ability to delete records, add/remove tables,
add new security accounts, etc. It is important to note that some web
applications could need this type of permission so it is not
automatically a bad thing that full control is granted.
So to illustrate the damage which can be done in this situation, we
will use the example provided in the comic above by entering the
following into the user name field:
"Robert'; DROP TABLE Users;--".
After simple substitution the authentication query becomes:
SELECT UserID FROM Users WHERE UserName='Robert'; DROP TABLE Users;--' AND Password='wrongpass'
Note: the semicolon is in a SQL query is used to signify the end of a particular statement and the beginning of a new statement.
Which gets executed by the database as:
SELECT UserID FROM Users WHERE UserName='Robert'
DROP TABLE Users
So just like that, we have used an SQLI attack to delete the entire Users table.
Of course, much worse can be done as, depending the SQL permissions
allowed, the attacker can change values, dump tables (or the entire
database itself) to a text file, create new login accounts or even
hijack the entire database installation.
Preventing a SQL injection attack
As we mentioned several times previously, a SQL injection attack is
easily preventable. One of the cardinal rules of web development is you
never blindly trust user input as we did when we performed simple
substitution in our template query above.
An SQLI attack is easily thwarted by what is called sanitizing (or
escaping) your inputs. The sanitize process is actually quite trivial as
all it essentially does is handle any inline single quote (‘)
characters appropriately such that they cannot be used to prematurely
terminate a string inside of a SQL statement.
For example, if you wanted to lookup “O’neil” in a database, you
couldn’t use simple substitution because the single quote after the O
would cause the string to prematurely end. Instead you sanitize it by
using the respective database’s escape character. Let’s assume the
escape character for an inline single quote is prefacing each quote with
a \ symbol. So “O’neal” would be sanitized as “O\’neil”.
This simple act of sanitation pretty much prevents an SQLI attack. To
illustrate, let’s revisit our previous examples and see the resulting
queries when the user input is sanitized.
myuser'--
/
wrongpass:
SELECT UserID FROM Users WHERE UserName='myuser\'--' AND Password='wrongpass'
Because the single quote after myuser is escaped (meaning it is
considered part of the target value), the database will literally search
for the UserName of
"myuser'--".
Additionally, because the
dashes are included within the string value and not the SQL statement
itself, they will be considered part of the target value instead of
being interpreted as a SQL comment.
Robert'; DROP TABLE Users;--
/
wrongpass:
SELECT UserID FROM Users WHERE UserName='Robert\'; DROP TABLE Users;--' AND Password='wrongpass'
By simply escaping the single quote after Robert, both the semicolon
and dashes are contained within the UserName search string so the
database will literally search for
"Robert'; DROP TABLE Users;--"
instead of executing the table delete.