SQL Injection Mitigation: Using Parameterized Queries
Michael Howard wrote an excellent article yesterday on how the SDL addresses SQL injection. He walks through three coding requirements/defenses:
- Use SQL Parameterized Queries
- Use Stored Procedures
- Use SQL Execute-only Permissions
As Michael points out, only the first, parameterized queries, remedies the problem. The other two provide additional defense.
The good news is that changing your ASP pages to use parameterized queries instead of just dynamically building the query is dead simple. The bad news is that MSDN doesn't have a lot of samples of how to do parameterized queries in ASP so I thought providing one would be helpful.
As an example, I'm sure that a lot of the websites that have been compromised recently via SQL injection have something like this:
Set objConnection = Server.CreateObject("ADODB.Connection")
objConnection.Open "Provider=SQLOLEDB;Data Source=SQLSERVER;" _
& "Initial Catalog=website;User Id=user;Password=password;" _
& "Connect Timeout=15;Network Library=dbmssocn;"
strSQL = "SELECT name, info FROM [companies] WHERE name =" & strSearch & "';"
Set objSearchResults = objConnection.Execute(strSQL)
This code is going to be extremely vulnerable to SQL injection since it's just taking the user input (which was passed in via a query string from a web form) and pasting it into the SQL statement.
The good thing about parameterization is that it separates the 'executable' code ("SELECT name, info...") from the 'data' (strSearch) we're using. With a few changes, we can make this code use parameters for the query and, with this small change, defend against being exploited in this way.
Set objConnection = Server.CreateObject("ADODB.Connection")
objConnection.Open "Provider=SQLOLEDB;Data Source=SQLSERVER;" _
& "Initial Catalog=website;User Id=user;Password=password;" _
& "Connect Timeout=15;Network Library=dbmssocn;"
strSql = "SELECT name, info FROM [companies] WHERE name = ?;"
set objCommand = Server.CreateObject("ADODB.Command")
objCommand.ActiveConnection = objConnection
objCommand.CommandText = strSql
objCommand.Parameters(0).value = strSearch
Set objSearchResults = objCommand.Execute()
All that we needed to do was:
- Replace the query string in our SQL squery statement with a ? (which is the placeholder for a parameter).
- Create a new Command object for our command.
- Assign our active connection and command text to the Command object.
- Set the first parameter in the parameters collection to our dynamic string.
- Execute the command.
If we needed to use multiple parameters in our query, we'd add additional question marks to strSQL and additional parameters to the Parameters collection. For example:
...
strSql = "SELECT name, info FROM [companies] WHERE name = ?" _
& "AND info = ?;"
...
objCommand.Parameters(0).value = strName
objCommand.Parameters(1).value = strInfo
...
There is a BIG caveat on this -- the method I show above has a performance hit because I haven't specified the types of the parameters. This means that ADO has to make a roundtrip to the SQL server to figure out the type before actually using it. You can fix this by creating parameters objects with the appropriate type which would have the added bonus of doing simple input validation as well. If there's interest, I'll write a followup in the next few weeks with some samples of typed, parameterized queries. (EDIT: Written, it's here.)
Additional info is available on MSDN here. NomadPete has a fuller walkthrough here that covers parameterized queries and stored procedures.
As always, this is only part of the job in securing against SQL injection; however, it is probably the single most useful change you could make.
(Big thanks to Bala Neerumalla for tech reviewing this for me.)
(Edit: Fixed two minor issues with the code examples. Thanks, Steve!)
Comments
Anonymous
January 01, 2003
While the default apps on a SBS 2003 (and upcoming SBS 2008) go through a SDL process so that I'mAnonymous
January 01, 2003
While the default apps on a SBS 2003 (and upcoming SBS 2008) go through a SDL process so that I'mAnonymous
January 01, 2003
Well, there was quite some chatter over the last few weeks with regards to the massive defacements weAnonymous
January 01, 2003
Trodde egentlig dette emnet var dekket godt nok opp i gjennom, men den siste ukas begivenheter viserAnonymous
January 01, 2003
SQL injection may be over a decade old, but even the best of us need a reminder once in a while. YouAnonymous
January 01, 2003
Microsoft has recently published a series of best practices to help developers build SQL code that isAnonymous
January 01, 2003
本文翻译自微软博客上刊载的相关文章,英文原文版权归原作者所有,特此声明。(特别感谢NeilCarpenter对本文写作提供的帮助) 近期趋势 从去年下半年开始,很多网站被损害,他们在用于生成动...Anonymous
January 01, 2003
There s a lot of noise arround currently ongoig SQL injection attacks and even if that is quite an "old"Anonymous
January 01, 2003
I just sent a piece of e-mail to my team about input validation and SQL injection and it occurred toAnonymous
January 01, 2003
攻击依然持续不断。Michael和Neil添加了关于这方面的blog,大家可以看看: Michael: How the SDL Addresses SQL injection Neil: SQL InjectionAnonymous
January 01, 2003
The comment has been removedAnonymous
January 01, 2003
Microsoft has recently published a series of best practices to help developers build SQL code that isAnonymous
January 01, 2003
- Introduction SQL Injection is a potential threat to any web application that has a SQL based database
- Anonymous
January 01, 2003
It is very common to us from CSS Security receive calls about SQL Injection and sometimes customers prefers