Professional Documents
Culture Documents
Server Code
txtUserId = getRequestString("UserId");
txtSQL = "SELECT * FROM Users WHERE UserId = " + txtUserId;
The example above, creates a select statement by adding a variable (txtUserId) to a select
string. The variable is fetched from the user input (Request) to the page.
The rest of this chapter describes the potential dangers of using user input in SQL statements.
SQL Injection
SQL injection is a technique where malicious users can inject SQL commands into an SQL
statement, via web page input.
Injected SQL commands can alter SQL statement and compromise the security of a web
application.
Server Result
SELECT * FROM Users WHERE UserId = 105 or 1=1
The SQL above is valid. It will return all rows from the table Users, since WHERE 1=1 is
always true.
Does the example above seem dangerous? What if the Users table contains names and
passwords?
The SQL statement above is much the same as this:
SELECT UserId, Name, Password FROM Users WHERE UserId = 105 or 1=1
A smart hacker might get access to all the user names and passwords in a database by simply
inserting 105 or 1=1 into the input box.
Password:
Server Code
uName = getRequestString("UserName");
uPass = getRequestString("UserPass");
sql = "SELECT * FROM Users WHERE Name ='" + uName + "' AND Pass ='" + uPass + "'"
A smart hacker might get access to user names and passwords in a database by simply
inserting " or ""=" into the user name or password text box.
The code at the server will create a valid SQL statement like this:
Result
SELECT * FROM Users WHERE Name ="" or ""="" AND Pass ="" or ""=""
The result SQL is valid. It will return all rows from the table Users, since WHERE ""="" is
always true.
Example
SELECT * FROM Users; DROP TABLE Suppliers
The SQL above will return all rows in the Users table, and then delete the table called
Suppliers.
If we had the following server code:
Server Code
txtUserId = getRequestString("UserId");
txtSQL = "SELECT * FROM Users WHERE UserId = " + txtUserId;
And the following input:
User id:
105; DROP
The code at the server would create a valid SQL statement like this:
Result
SELECT * FROM Users WHERE UserId = 105; DROP TABLE Suppliers
Another Example
txtNam = getRequestString("CustomerName");
txtAdd = getRequestString("Address");
txtCit = getRequestString("City");
txtSQL = "INSERT INTO Customers (CustomerName,Address,City) Values(@0,@1,@2)";
db.Execute(txtSQL,txtNam,txtAdd,txtCit);
You have just learned to avoid SQL injection. One of the top website vulnerabilities.
Examples
The following examples shows how to build parameterized queries in some common web
languages.
SELECT STATEMENT IN ASP.NET:
txtUserId = getRequestString("UserId");
sql = "SELECT * FROM Customers WHERE CustomerId = @0";
command = new SqlCommand(sql);
command.Parameters.AddWithValue("@0",txtUserID);
command.ExecuteReader();
INSERT INTO STATEMENT IN ASP.NET:
txtNam = getRequestString("CustomerName");
txtAdd = getRequestString("Address");
txtCit = getRequestString("City");
txtSQL = "INSERT INTO Customers (CustomerName,Address,City) Values(@0,@1,@2)";
command = new SqlCommand(txtSQL);
command.Parameters.AddWithValue("@0",txtNam);
command.Parameters.AddWithValue("@1",txtAdd);
command.Parameters.AddWithValue("@2",txtCit);
command.ExecuteNonQuery();
INSERT INTO STATEMENT IN PHP:
A SQL injection attack is exactly what the name suggests it is where a hacker tries to
inject his harmful/malicious SQL code into someone elses database, and force that
database to run his SQL. This could potentially ruin their database tables, and even extract
valuable or private information from their database tables. The idea behind SQL injection is
to have the application under attack run SQL that it was never supposed to run. How do
hackers do this? As always, its best to show this with examples that will act as a tutorial on
SQL injection.
The SQL that would retrieve the email address in the email me my password form would
typically look something like this keep in mind that this SQL really is embedded within a
scripting language like PHP (it depends on what scripting language is being used by the
application):
SELECT data
FROM table
WHERE Emailinput = '$email_input';
This is, of course, a guess at what the SQL being run by the application would look like,
because a hacker would not know this information since he does not have access to the
application code. The $email_input variable is used to hold whatever text the user inputs
into the email address form field.
If the hacker puts that exact text into the email address form field then there are basically 2
possibilities:
1. The application will first sanitize the input by removing the extra quote at the
end, because we will assume that the application considers email addresses with
quotes as potentially malicious. But, a side note: email addresses can actually contain
quotes according to IETF standards. Sanitizing data is the act of stripping out any
characters that arent needed from the data that is supplied in our case, the email
address. Then, the application may run the sanitized input in the database query, and
search for that particular email address in the database (without the quote of course).
2. The application will not sanitize the input first, and will take the input from the
hacker and immediately run it as part of the SQL. This is what the hacker is hoping
would happen, and we will assume that this is what our hypothetical application is
doing. This is also known as constructing the SQL literally, without sanitizing. What
it means is that the SQL being run by the application would look like this pay extra
attention to the fact that there is now an extra quote at the end of the WHERE
statement in the SQL below:
SELECT data
FROM table
WHERE Emailinput = 'hacker@programmerinterview.com'';
Now, what would happen if the SQL above is executed by the application? Well, the SQL
parser would see that there is an extra quote mark at the end, and it will abort with a syntax
error.
Note that the SQL above is completely SQL compliant and legitimate. You can see that after
the Y there is an extra quote followed by a semicolon, which allows the hacker to close the
statement and then incredibly run another statement of his own!
Then, if this malicious code is run by the application under attack, it would look like this:
SELECT data
FROM table
WHERE Emailinput = 'Y';
UPDATE table
SET email = 'hacker@ymail.com'
WHERE email = 'joe@ymail.com';
Can you see what this code is doing? Well, it is resetting the email address that belongs to
joe@ymail.com to hacker@ymail.com. This means that the hacker is now changing a
users account so that it uses his own email address hacker@ymail.com. This then means
that the hacker can reset the password and have it sent to his own email address! Now, he
also has a login and a password to the application, but it is under someone elses account.
In the example above, we did skip some steps that a hacker would have taken to figure out
the table name and the table layout, because we wanted to keep this article relatively short.
But, the idea is that SQL injection is a real threat, and taking measures to prevent it is
extremely important.
Now, the question is how to prevent SQL injection attacks? Well, read on to the
next page or just click here: SQL Injection Prevention.
In our earlier tutorial on SQL Injection, one way to have prevented the SQL injection attack
was by simply having the user input sanitized which we briefly discussed. Since we are
dealing with email addresses in our example, this means that we should be able to safely
exclude certain characters which dont normally appear in email addresses. Here is a list of
characters that would normally appear in emails, and anything else should not be allowed
inside the database the user should just receive an error saying something like Invalid
email address if he tries to input an email address with any characters other than the ones
below:
abcdefghijklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ
0123456789
! $ & * - = ^ ` | ~ # % ' + / ? _ { } @ .
This is whats called escaping strings. If we did not escape the quote in our string then it
would not output anything, and would result in a PHP error because the quote is also used to
enclose the characters in an echo statement.
Now, how would escaping the quotes have helped in our previous example? Remember our
hacker is trying to input this harmful/malicious code into the email form field:
Y';
UPDATE table
SET email = 'hacker@ymail.com'
WHERE email = 'joe@ymail.com';
What if we escape the quotes in the string above before we pass the SQL to the database?
Well, that would mean the quotes in the string become a part of the string that is searched for
using the Emailinput field in effect the query is searching for an email address that is equal
to that giant string. In other words, the quotes are part of the string literal, and will not be
interpreted as SQL. In MySQL, we can escape a quote simply by prepending a quote with
another quote basically 2 single quotes will be interpreted as one quote which is what we
do in the example below. So, the actual SQL that will be run looks like this:
SELECT data
FROM table
WHERE Emailinput = Y''; --the quote after the Y is escaped
UPDATE table SET email = ''hacker@ymail.com'' -- escape quotes
WHERE email = ''joe@ymail.com'' ; --and, more quotes escaped
The key in the example above is that the quotes are now being treated as part of a string that
gets compared to a field in the table, and NOT being translated as actual SQL its very
important that you understand the distinction because it is exactly the problem that
escaping quotes solves for us.
If we do not escape quotes, it allows those quotes to become part of the SQL, and basically
allows the hacker to run 2 statements at once which is exactly what is so dangerous. The
2nd statement (the UPDATE table SET email = hacker@ymail.com WHERE email =
joe@ymail.com';) is what really messes things up, because it allows the hacker to change
the email address of an existing account to his own email address. And, that 2nd statement is
only allowed to run because the quotes are not escaped. Escaping a string is also known as
quotesafing, since you are essentially making the SQL query safe for quotes.
Lets say that we choose to escape quotes manually by just adding a single quote every time a
string comes in with a quote. Because, if we have a name field, we want to allow people with
quotes in their name to be able to save their name without any issues for instance, someone
with the name Jack OLeary should be able to be saved in our database without the quote
causing any issues.
So, if we are retrieving someones name from our database, then the SQL may look like this:
SELECT *
FROM customers
WHERE name = 'Jack OLeary';
And this works perfectly fine because the double quotes will be interpreted as a single quote,
and MySQL will search for Jack OLeary (with one quote), and not Jack OLeary (with 2
quotes).
But, lets say a clever hacker realizes that you may be running a MySQL database, and knows
that MySQL also allows you to escape quotes by preceding the quote character with a
backslash so a quote could also be escaped like this: \
So, our clever hacker tries to insert a string like this into the email field on our form:
\'; DROP TABLE users;
But after we do our own manual string escaping (by adding the extra quote), that string turns
into this:
\''; DROP TABLE users; --
What happens when this SQL is run? Well, the \ gets interpreted by MySQL as a string with
a single quote, meaning that the system will just search for a name with a single quote. The
2nd quote (the one that comes after the \), will allow the hacker to close the first statement,
insert a semicolon, and then run another malicious statement (the DROP TABLE users; code).
The hacker essentially fools the system into NOT escaping one of the extra quotes by taking
advantage of 2 things here:
Remember, the quotes are key because it allows the hacker to close one statement and run
any extra statement of his or her choosing.
Looking at the examples above, you can see that even though the syntax details are different
for each language, they are all fundamentally the same because they all use a ? as a
placeholder for the value that will be passed in later. And they all prepare the SQL first and
execute later, which is of course the whole point behind prepared statements. A good way to
think of a prepared statement is as a template for SQL because of the fact that its not a
complete SQL statement since it does not have the values it needs in the placeholder areas.
values to execute with since there is no data in the placeholders/parameters. The SQL is only
executed once the respective execute function is called and data is passed in for the
parameters.