Aug
ASP security case study
No comments
The Legacy
I recently worked on a legacy asp web application that had been hacked. The problem? The programmers didn’t think that hackers would/could attack them. This seems to be a prevalent problem in the development world. Developers have a zebra mentality. ‘Ok, we all have to cross the river, but if we all jump in at the same time hopefully I won’t be the one to get eaten’. If you don’t see the flaw in this logic please do not waste any more time with this article and go have loads of fun playing Click the Button. If you do see the logic continue on.
Case Study
One day this particular website (which I will leave unnamed) starts to attempt to download viruses on users computers from a malicious website whenever anyone visits their site. The results are devastating. Users are now getting infected with viruses. Google lists the site as a dangerous site and anyone using Firefox gets a big scary warning sign whenever they try to go to the site. This seriously hurts the reputation of the site and drives valuable traffic away.
Diagnosis
Upon close inspection of the site I noticed many ‘<script>’ tags who’s source was pointing to some suspicious looking urls. It didn’t take long to find on google that these were listed as malicious domains that were hosting viruses. The verdict; Cross Site Scripting. Cross site scripting attacks are usually malicious scripts that are inserted by hackers to force a non-malicious website to dish out malicious code.
How did they do that?
Malicious scripts are usually injected into a website on the back of SQL injection. SQL injection is a way for hackers to break into a database and inject their malicious code. A quick inspection of the database and sure enough, the database was full of malicious scripts in the content. I quickly ran some queries using the SQL ‘Replace’ function to strip out the maliciou scripts, but what would stop them from doing it again?
Understanding the Problem
Before you can fix a problem you have to be able to understand it first. SQL injection is the process of breaking a sql statement typically by adding SQL characters ( ‘ ; — ). For instance, lets say you have the following SQL statement being sent to your database:
Dim sSQL Dim JobID JobID = Request.QueryString("jid") sSQL = "SELECT * FROM jobs WHERE jID = " & JobID
jid is being sent from the browser and can easily be changed. What if jid included the following ” testjob’; SELECT * FROM sysobjects — “. When this is concatenated into the SELECT query it produces the following:
"SELECT * FROM jobs WHERE jID = 'testjob'; SELECT * FROM sysobjects -- '"As you can see, the single quote (’) breaks the sql statement and the semicolon character tells the SQL query that this is the end of this particular SQL statement and to start looking for the next command. You simply enter in the next list of SQL commands trailed by a SQL comment (–) to void out the extra single quote so that it doesn’t break the query.
In Microsoft SQL the sysobjects table gives you lots of critical information about your database including a list of all the user tables that you have created. You can imagine how valuable this information is to a hacker who now has the capability to run UPDATE INSERT and DELETE statements on your database. Once they have the list of tables, they can simply get the id of the table they want and query the syscollumns table. You can probably guess what that table has,,, yup,, an entire list of all the column names in your entire database along with the table ids that they are related to. The hackers are having a huge party at this point. All that’s left for them to do is run an update statement and concatenate an evil script tag to the end of all your content and your site is now aiding in making the internet a bad place.
The Fix
Ok, so now we understand the problem so we can take what we’ve learned and apply it to the problem. ‘Never trust any data that comes from a user’ isn’t a rule of thumb at all. It is an imperative principal that, if ignored, can/will wreak havoc on your application. What we need to do is disable the hackers ability to break the SQL queries. We do this by using ‘data sanitizing’ techniques. There are many different methods to do this, but I’ll show a couple here. This is applicable in many languages, but being that the case study we’ve been looking at is in ASP I’ll give some ASP code examples. Ok, enough talk, here’s the code:
<% Class libStrings Function sanitize(strData, removeHTML) Dim strOutput strOutput = strData If (removeHTML = "true") Then strOutput = stripHTML(strOutput) End If strOutput = Replace(strOutput, "'", "''") strOutput = Replace(strOutput, ";", "") strOutput = Replace(strOutput, "--", "") strOutput = Replace(strOutput, "update", "update_", 1, -1, 1) strOutput = Replace(strOutput, "insert", "insert_", 1, -1, 1) strOutput = Replace(strOutput, "delete", "delete_", 1, -1, 1) strOutput = Replace(strOutput, "drop", "drop_", 1, -1, 1) strOutput = Replace(strOutput, "select", "select_", 1, -1, 1) sanitize = strOutput End Function Function stripHTML(byVal strHTML) Dim objRegExp, strOutput Set objRegExp = New Regexp objRegExp.IgnoreCase = True objRegExp.Global = True objRegExp.Pattern = "<(.|\n)+?>" strOutput = objRegExp.Replace(strHTML, "") strOutput = Replace(strOutput, "<", "<") strOutput = Replace(strOutput, ">", ">") stripHTML = strOutput Set objRegExp = Nothing End Function Function isEmail(byVal strEmail) Dim objRegExp, matched Set objRegExp = New Regexp objRegExp.IgnoreCase = True objRegExp.Global = True objRegExp.Pattern = "[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9]{3}?" matched = objRegExp.Test(strEmail) If matched Then isEmail = true Else isEmail = false End If End Function Function isPhone(byVal strPhone) Dim objRegExp, matched Set objRegExp = New Regexp objRegExp.IgnoreCase = True objRegExp.Global = True objRegExp.Pattern = "^(\(?\d{3}\)?[ .-]\d{3}[ .-]\d{4})|(\+\d{2}[ -]\d{2,4}[ -]\d{3,4}[ -]\d{3,4})$" matched = objRegExp.Test(strPhone) If matched Then isPhone = true Else isPhone = false End If End Function Function isZip(byVal strZip) Dim objRegExp, matched Set objRegExp = New Regexp objRegExp.IgnoreCase = True objRegExp.Global = True objRegExp.Pattern = "^\d{5}([\-]\d{4})?$" matched = objRegExp.Test(strZip) If matched Then isZip = true Else isZip = false End If End Function Function isAlpha(byVal string) dim regExp, match, i, spec For i = 1 to Len( string ) spec = Mid(string, i, 1) Set regExp = New RegExp regExp.Global = True regExp.IgnoreCase = True regExp.Pattern = "[A-Z]|[a-z]|\s|[_]" set match = regExp.Execute(spec) If match.count = 0 then IsAlpha = False Exit Function End If Set regExp = Nothing Next isAlpha = True End Function End Class %>
This is a simple class that encapsulates several string functions. The ’sanitize’ function strips out the SQL characters I mentioned earlier and also concatenates an ‘_’ to SQL commands and invalidates them. This function also makes use of the ’stripHTML’ function (thanks to 4guys for this function) and strips out any malicious scripts from getting to your database. Here’s how to use it:
Dim strObject Dim strSQL Set strObject = libStrings varToSanitize = strObject.sanitize(varToSanitize) strSQL = "SELECT * FROM table WHERE criteria = '" & varToSanitize & "'"
This strips the ability to break the SQL statement by injecting characters and malicious scripts. A couple more methods you’ll notice validate what type of string is being received, such as a phone number or email address. These are common values that are inserted into a database. Not only is this kind of validation good for your application and data ‘correctness’ but it can also deter hacker attacks. When your application ‘knows’ what data it’s supposed to receive it can handle data in a much more stable manner. Also, there is an isAlpha function that helps to validate things such as a name or other string you know should not contain numbers or special characters. ASP also has built in functions such as isNumeric that help you to validate variables you know should be only numbers.
Conclusion
This is by no means an exhaustive article on SQL injection or website security, but it can get you going. The techniques here can be implemented in many other languages such as PHP, Perl or Python. If you take nothing more away from this article please remember one thing… never trust any data that comes from a user. Treat all data that comes from users as though it has been tainted.
Saturday, August 30th, 2008 at 10:37 pm and is filed under ASP. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.
