Thursday, January 13, 2005

Hacking Websites

I attended a talk recently at ADNUG (Austin .NET Users Group) which was supposed to be about Garbage Collection. Unfortunately, the dude who was supposed to give the talk couldn't make it in time so they had another guy present in his place. He didn't care much for Garbage Collection and instead gave a talk on hacking websites.

He talked about three basic ways people hack web sites...

1) Manipulating hidden form input elements
This one seems so simple. The web is a stateless protocol so everytime you need access to some data, you have to hit the server and retrieve data from a database. To avoid this, one trick many people use is to put this information in a hidden form input element. These elements are not shown in the browser but you have programatic access to them through client side scripting. So for example, a shopping cart has a final price value. This data can be stored in an hidden input element. If you change the quantity of an item, instead of hitting the server, changing the price and returning a new page with a updated price, you can just update the price client side.

Consider this simple example. When you change the quantity, the price is calculated on the client side, instead of hitting the server.

< script>
function updatePrice()
    var quantity = document.frmCart.txtQuantity.value;
    var price = document.frmCart.hdnPrice.value;

    var updatedPrice = quantity * price;

    document.frmCart.hdnPrice.value = updatedPrice;

    spnPrice.innerText = "$" + updatedPrice;
< /script>

< form name="frmCart" action="checkout.asp">

    < input type="hidden" name="hdnPrice" value="30">
    < input type="text" name="txtQuantity" value="1" onChange="updatePrice();">

    < span id="spnPrice">$30< /span>

< /form>

So a hacker can just save this page, manually change "hdnPrice" to any value he wants and then submit the page to checkout.asp. This is such an easy way to cheat. I mean who would ever use something like this on their site? Believe it or not, the presenter said that it's quite common. He said some dude was able to get airline tickets for 50 cents using this technique from a major airline company.

So, the solution he gave, was that you should put security first and forget performance. Take that hit on the server. Or if you must use client side scripting use it for more trivial things and not for financial stuff.

2) SQL injection
This is a bit more sophisticated in that you need to know SQL quite well. I don't, so I'll just give the simplest example. Maybe after Rahul and Dinesh finish their data module, they can invent new advanced attacks ;-)

Many sites have forms where they ask the user to enter some data and then use that data to make a query into a database. A very common example of this is the Login form. I'm sure everyone who uses the web has seen this one. You have two input boxes to enter your username and password. Generally, the page on the server will take these two pieces of data and form an SQL statement like so...

Dim strUserName = Request.QueryString( "txUserName" )
Dim strPassword = Request.QueryString( "txtPassword" )

"SELECT COUNT(*) FROM users WHERE username='" + strUserName + "' AND password='" + strPassword + "'"

This is a basic statement that counts the number of rows in the table (users) that have username=strUserName and password=strPassword. Here we are not validating the username and password the user enters. So if he knows SQL, he could enter ' or 1=1-- for username and leave the password blank.

This will result in the above SQL statement becoming

SELECT COUNT(*) FROM users WHERE username='' or 1=1-- AND password=''

This will always return true since 1 is always equal to 1. Everything after -- is a comment. So you can gain access to a site without entering a valid username and password.

The speaker gave more advanced examples where he was able to figure out the structure of the table (ie. what columns it contains) and using that information was able to access data contained in those columns. The SQL was advanced so I couldn't follow it, but it was this same technique.

Solution: Be paranoid and ALWAYS validate data coming from the client. And as far as possible use Stored Procedures. Besides getting a performance boost (since they are compiled vs SQL statements that are interpreted), they use typed parameters.

3) Cross site scripting.

This one is where you get your scripts to run on someone else's site. A lot of times sites will have forms for users to enter data and then they just display that data on the page. For example, consider a message board. In a very simple one, there is one page with message posts and at the bottom there is a form to fill out your username, subject and message. When you submit, the page probably enters this info in a database and then just spits out what you just entered along with the other messages. Now what if you include some html or script in your message? For example, if you entered < script> alert( "You suck" ); < /script>. When the page is displayed you will get a message box with your very welcoming message in it. Every visitor to the web page will get that message.

That was a simple dumb example. Here is another simple one. Browsers are pretty linient when it comes to html being well formed. As in, they won't choke if you pass in an opening tag and leave off the end tag. So if you had written < div> and not closed it in the message above, the page would show everything up to the < div> tag. The rest of the page would be blank. Or you could enter an < img> tag and link to some porn image. This will be posted on their site.

But you can see how it could potentially be more damaging. You can gain access to cookies through client side scripts (document.cookies) and you can change the location of the browser (document.location.href=""). So you can combine these to retrive cookie information and pass it on to your site. This gets more sophisticated, but it's all possible.

The solution for this is to never ever blindly send back whatever the user has entered. ALWAYS encode the data before sending it down to the client. So instead of sending down < script> alert( "You suck" ); < /script>, you should encode it to &lt;script&gt; alert( "You suck" ); &lt;/script&gt; and then send it down. Many server side platforms offer utilities that do it for you. The encoded text will DISPLAY the script on the page, but won't execute it.

Anyway, hope this gave you some ideas of how sites are hacked. Now go forth and practice. And make sure to use someone else's computer.

You guys heard of any other techniques?

No comments: