Tuesday, 6 November 2012

OWASP Top 10: #1 - Injection. The risk explained.

This is one in a series of videos and blog posts that explore the top 10 most critical web application security risks as defined by OWASP.
OWASP - the Open Web Application Security Project, was formed in 2001 and is a not for profit charitable organisation.
It is an open community dedicated to enabling organisations to conceive, develop, acquire, operate and maintain applications that can be trusted.
In this session, I will deal with the OWASP #1 risk. Injection.
You can read the transcript below.
HTML5 player


I will define Injection and provide several examples of injection at work. In a follow on session, I will demonstrate various techniques that can be employed to mitigate against the risk of injection.
So let’s begin with a definition:

“Injection flaws, such as SQL, OS, and LDAP injection, occur when untrusted data is sent to an interpreter as part of a command or query. The attacker’s hostile data can trick the interpreter into executing unintended commands or accessing unauthorised data.” -OWASP Top 10, 2010

A key message to take from this definition is that although many people assume that Injection refers to SQL Injection, it needn’t be so. Although for the purposes of this session I will focus on SQL Injection.

OWASP’s top 10 doesn’t restrict itself to just .NET technologies. Therefore QA do have two other courses:


For the purpose of these videos and blog posts however, I will focus on .NET technologies.

The best way to demonstrate this risk of injection is by way of an example.
So let me start up Internet Explorer 10 and then load up a vulnerable website at http://injection.
This website is hosted under a local instance of Internet Information Services - IIS and uses a SQL Server database at the back end to store the data.
If navigate to the Beverages list by clicking on the link in the top right hand corner of the page, I will see the URL reflect a query string of CategoryID=1 and 10 beverages listed on the page.
It is the fact that a CategoryID of 1 has been appended to the query string that dictates that it is just the beverages that are displayed.
Now if we wanted to exploit a potentially vulnerable application we might experiment with the query string. So for example if I update the query string to add  or 1=1 so that the URL now appears as http://injection/Products.aspx?CategoryID=1 or 1=1 and then press Enter to load the page again, a much larger set of results should appear.
This indicates the likely presence of a SQL injection risk.
So thus encouraged, let’s try something else.
I’ll change the query string to read CategoryID=1 or x=1.
Now this is syntactically invalid SQL and the fact that if I reload the page we have an error page returned saying “Invalid column name ‘x’”, would suggest that this web application takes the values in the query strings and uses them directly in its use of SQL.
Let’s see what else we can figure out as a potential hacker.
This time I’ll update the query string to read http://injection/Products.aspx?CategoryID=1 OR 1=(SELECT COUNT(*) FROM Customer) then press Enter to load the page again.
Once again I get an error but from an attacker’s point of view this is really useful because this once again proves that the application is taking the value entered at the query string and using it to query the database.
In this case, the database has come back and said there is no such object as Customer. So now the attacker could update the query string and rewrite Customer as Customers to see where that gets them.
And this time it’s paid off because as you can see there was no error generated and so the attacker now knows that a table called Customers exists.
You can imagine that over time an attacker could build up a picture of all the table names in the system.
OK so let’s try to see if as an attacker, we are able to chain queries. I’ll update the query string to append a second query following a semi-colon as follows: http://injection/Products.aspx?CategoryID=1; SELECT * FROM Customers then press Enter to load the page again.
The fact that the page loads without error confirms that subsequent queries can be chained.
Now that we have established that the web application literally takes the value in the query string and uses it to build queries to send to the database, the attacker could update the query string one more time and add in two hyphens at the end. This will serve to comment out any remaining SQL that the application might append to the statement.
Not only will an attacker try to figure out the names of tables and we know that they can already do that. We have proved it.
They’ll probably also want to confirm the existence of columns.
So I’ll update the query string again so that this time I am selecting from Customers where the Company = 1. I am guessing at the name Company. As follows:
http://injection/Products.aspx?CategoryID=1; SELECT * FROM Customers WHERE Company = 1--
If I reload the page, I will receive a helpful error message informing me that there isn’t a column called Company.
Now as an aside, if the ASPNET web developer had actually used the customErrors flag in their web.config file, then the attacker wouldn’t be receiving such useful information.
So the attacker now knows that there isn’t a column called Company in the Customers table.
Well they have all the time in the world. They can just update the URL and try different column names.
So let’s try CompanyName.
Well, there is no error received. So that has confirmed to the attacker that there is indeed a column called CompanyName in the Customers table.
Now that they know this, the attacker could write a query to trick the database into revealing data in the CompanyName column.
Let me add in this query to the address bar:
http://injection/Products.aspx?CategoryID =convert(int,(char(82)%2bchar(33)%2b(select top 1 cast(isnull([CompanyName],char(32)) as nvarchar(4000)) from (select top 1 [CompanyName] from [Customers] order by [CompanyName] asc) sq order by [CompanyName] desc)%2bchar(33)%2bchar(82))) and 1=1-- 
And then press Enter to load the page again.
This query attempts to retrieve the CompanyName column from the Customers table and convert it into an integer so that it can be compared with the CategoryID.
Now this query will fail because SQL Server wouldn’t be able to cast the CompanyName string into an integer for the CategoryID.
But that was the point because what the attacker was trying to do was generate an error message that would reveal some information.
Look at this error. Not only does SQL Server tell us that it cannot convert an nvarchar into an int, it also revealed the data. In this case, a CompanyName of “Alfreds Futterkiste”.
Thus encouraged, the attacker could continue to update the query placing different values in the second select top statement to change select top 1 [CompanyName] from [Customers]… to select top 2 [CompanyName] from [Customers].
And so on. Generating error message after error message revealing company name after company name.

As you can see from these simple examples, a vulnerable application can be easily exploited by an attacker using SQL Injection.
In my next video and blog post, I will show you how to quite easily mitigate against this risk and thus protect yourself from the #1 in OWASP’s top ten. Injection.

Flash player


If you are interested in OWASP training, we offer the following courses:

Developing Secure Java Web Applications – Mitigating the OWASP Top 10 Security Vulnerabilities

Developing Secure .NET Web Applications – Mitigating the OWASP Top 10 Security Vulnerabilities


See you soon

Phil Stirpé
"I don't do average!"

No comments:

Post a Comment