How Prevalent Are SQL Injection Vulnerabilities?

[Update 01.31.07 - A follow up blog on the prevalence of XSS vulnerabilities has now been posted.] 

[Update 01.17.07 - This blog is now also available as a webcast.] 

Earlier this month, Mitre revealed that web application vulnerabilities have now claimed the top three spots on the CVE request list. Specifically, the ranking for 2006 is as follows:

  1. Cross Site Scripting (21.5%)
  2. SQL Injection (14%)
  3. PHP includes (9.5%)
  4. Buffer overflows (7.9%)
The statistics are significant as they provide evidence of the prevalence of web application vulnerabilities. Coverage of this issue has however been somewhat misleading as reports have suggested that it is a measure of what attackers are doing. This assumption is false. CVE requests represent the volume of discovered vulnerabilities in commercial and open source applications, they do not reflect the degree to which those vulnerabilities exist in the real world, nor do they reflect what vulnerabilities attackers are actually using to access vulnerable systems.

Web applications pose a unique threat as programming web applications does not require employing skilled programmers. Anyone with access to various point and click tools is now a web developer. For that reason, I suspect that web application vulnerabilities are even more of a threat in the real world than the Mitre statistics would suggest. CVE numbers tell us that web application vulnerabilities are plaguing software developers but they do not provide insight into vulnerabilities within custom built sites.

Of the vulnerabilities discussed in the Mitre report, I feel that SQL injection represents one of the greatest threats for the following reasons:
  • Any website worth going to has a database on the back end.
  • Many development texts actually teach programmers insecure SQL syntax.
  • Databases often house sensitive data such as credit card numbers, social security numbers and other personal data that phishers would love to get their hands on.
  • Many sites are exposed to SQL injection attacks but don't know it.
It's that last bullet point that I wanted to prove to myself by compiling some sort of empirical evidence. How can I do that without breaking into a website? Hmmm....perhaps my friend Google will have the answer. After some contemplating, I came up with the following theory:
  • Identify a population of web sites likely to have databases and determine the request syntax.
    • For this requirement, I turned to Google and took a bit of a shortcut. I selected a portion of a GET request that would likely be used to query a database. For my purposes, I chose inurl:"id=10". This query was selected for two reasons. First, using a GET request would allow me to leverage a search engine to identify a population of URLs for testing. Second, a URL containing a query such as "id=10" is likely to be querying a database for something such as a product catalog. That query in Google returns nearly 6 million hits, so obtaining a sample population clearly wasn't going to be a problem.
  • Submit an altered query in order to elicit a SQL error message.
    • Once again, I took a relatively simplistic approach here by altering the query to inject an single quote ahead of the actual query. Therefore, the request would now be in the form of "id='10". This is a common technique when attempting to identify SQL injection attacks as SQL queries enclose strings within single quotes. Injecting an extra quote will create a query with an open quotation mark and this will often cause the application to return an error message. I took this one step further and URL encoded the single quote to bypass sites that may be filtering for unusual characters. Therefore, the injected query was now "id=%2710".
  • Parse all responses to look for signs of verbose SQL error messages.
    • After much trial and error, I settled on three simple words that allowed for the identification of most SQL error messages. I would grep responses for "sql", "query" and "error".
With a theory in place, it was now time to build an automated solution in order to make the test practical. For that, I turned to the Google API. Using the API, I was able to build a C# application (shown below) to automate the steps listed previously. While building the application, I realized that a few extra steps would be required:
  • Remove duplicate sites
    • I started with a sample population of 1000 sites from my initial query. I realized however, that Google would return some duplicate URLs that were from the same web site. These were filtered out as I was looking to determine the prevalence of vulnerable web sites, as opposed to web pages.
  • Remove bad queries
    • Google will actually ignore many special characters such as "=" and I therefore ended up with some URLs which contained "id" and "10" but not the "id=10" name value pair that I was looking for.
  • Remove failed queries
    • Just because a URL is indexed in Google, doesn't mean that it will be accessible when you want to view it. I therefore had to also ensure that the tool was capable of recording any failed requests.
  • Manual verification
    • I realized that no level of grepping the results was going to eliminate all false positives. I therefore implemented a system that would allow me to quickly visually validate the results. I settled on a system that would highlight the responses that appeared to contain verbose SQL errors based on the grepping of results. As the full response was captured and stored in memory, I could then quickly view the response to determine if it was a false positive. What I soon realized is that it was important to look at both the interpreted HTML and source code as SQL errors were occasionally hidden in the source code and not visually displayed.

Using all that I'd learned form various manual experimentations, I ultimately hacked together the tool shown below using C# and the Google API.

Google API - SQL Injection 

While far from perfect, this provided an easy to use tool that allowed me to quickly validate findings with a visual inspection. In the end, the results were as follows:

Initial population of URLs1000
Population after removal of duplicate servers732
Population after removal of failed requests708
Total number of verbose SQL errors80
Percentage of sample web sites potentially vulnerable to SQL injection attacks11.3%

While I don't find this result surprising, it certainly is sobering. This was a simple test. It was certainly not a comprehensive audit of the web servers which would no doubt have uncovered many more vulnerabilities. The experiment looked at only a single input vector on each of the web sites and did not take into account the possibility of blind SQL attacks. Granted, this test did not proceed to attempt to extract data from the databases as that would be illegal but it does in my opinion shine some light on just how poorly database connectivity is implemented on public websites and the dangers that it poses.

- michael

Published 26 September 06 01:01 by Erik
Filed under:

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

# caleb said on September 26, 2006 1:54 PM:

You will get better results if you restrict to filetype:asp and site:(org,gov,com,edu etc)

# Erik said on September 26, 2006 3:10 PM:

Thanks Caleb. I did experiment with the 'filetype' filter but in the end opted against it as I didn't want to limit the results only to MS based servers. It would however be interesting to see if there's a variation in results when comparing commercial domains to non-commercial, government and military.

# Thomas Mueller said on October 2, 2006 3:29 AM:

There is an obvious way to protect against this vulnerability: don't embed user input into the SQL statement, use parameterized statements instead. I suggest that this should be enforced by the database engine (or, by the driver), by disabling literals in SQL statements. See here for more details:

http://www.h2database.com/html/advanced.html#sql_injection

What do you think about this solution?

# Erik said on October 2, 2006 8:27 AM:

Thomas - Thanks for providing readers with a solution. I completely agree. Paramterized queries as opposed to concatenating user input in SQL strings is a great solution. Unfortunately, many (most) programming texts still team the later.

# Jim said on October 3, 2006 3:54 PM:

That is pretty scary - I'm sure the hackers have been using their own programs to do much the same thing. Thanks for doing this research - hopefully it will scare more people into protecting themselves.

# glguy said on October 3, 2006 5:35 PM:

I'd like to make a correction to one of your first paragraphs.  It should read:

"Computer programming poses a general threat as programming applications does not require employing skilled programmers."

Any idiot can program anything given enough time.  I worked on projects with these idiots.  What makes web programming more challenging is that these programs are run on a company's own server and are exposed to the whole world.  This is different than writing an application that will run on a local machine on the user's local hardware, and poses unique security concerns.

# Erik said on October 4, 2006 12:59 PM:

glguy - fair point. The open nature of web apps does directly impact the risk posed by vulnerabilities in such apps. Bad coding can happen anywhere, the desktop is certainly not immune.

# Mutton said on October 4, 2006 5:04 PM:

Another easy way to guard against this is to convert the string id parameter to a numeric value. If the conversion function/method throws an exception, then revert to a default or forward to an error page.

This results in

id=10 -works as expected

id='10 -fails conversion

id=%2710 -fails conversion

id="10 -fails conversion

All the cases where conversion failed will not permit a SQL-injection attack, because the failure occurs prior to the database commands.

---

This is nothing new, though. In my experience of consulting at many more companies than I care to count, the majority of them suffer from this vulnerability. They get this way because "Bob's 12-year-old cousin knows how to write programs,

so they use this kid to hack up some code for their website.

The glut of personal data out there--not from just the credit card companies--and the totally non-existant data protection + infinite data retention (because they don't know any better) means that there are too many ways to get burned.

Just remember that when you fill out that survey card, complete an application, or enter a contest -- all that data is permanently going into a database that has slim to no security.

# b said on October 4, 2006 7:07 PM:

glguy,

I tend to agree with sutton here.  With web programming the gui aspect is degrees easier, and little to no knowledge of the underlying network protocol is required.

Not that your statement isnt true in it's own merit, it is imo easier to create a decent looking and robust (or atleast seems robust) application on the web than other environments.  This look and feel of robustness causes people to put code in production that they most likely shouldnt.

Would be interesting to compare vulnerabilities in j2ee compared to in php.  Wonder if the higher education level/competence of java programmers would factor into vulnerabilities.

# Erik said on October 4, 2006 7:15 PM:

Mutton - While the fix may apply for this specific example, what about sceanrios where user input used in a SQL query needs to be astring value?

i.e. SELECT * FROM users WHERE name = 'Michael'

--> http://example.com?name=Michael

# mm said on October 4, 2006 7:26 PM:

An interesting article, but there is one major discussion missing here, and that is of the quality of the developers behind the site.

The last half of the article deals with identifying vulnerabilities and is something you probably do for your job, (according to your bio below). so I will not focus on the vulnerability testing ( and its interesting use of google).

The first half of your article states:

    "web applications does not require employing skilled programmers"

    "I feel that SQL injection represents one of the greatest threats for the following reasons"

    "nor do they reflect what vulnerabilities attackers are actually using to access vulnerable systems"

So in essence you are stating that poorly developed applications will have vulnerabilities (no surprises there then).

Also, SQL injections are going to exist (actually any vulnerability will be present as the website have been poorly developed)

Finally, there is no tests to prove the other 3 top stats quoted by yourself.

So for an analogy, it does not surprise me that a cheap Korean car does not match the performance of a Porsche, however I wouldn't then try to prove that assumption by testing a random sample of tyres. Then state that as I have found 11% of tyres to fail at 100kmh therefore Korean cars are worse than Porches.....

# Erik said on October 4, 2006 8:08 PM:

mm - You may not have interpreted some of my comments as I intended them. I'm certainly not saying that all web applications are created by weak programmers. I'm simply stating that web application programming does not require the same skills as say network level programming. Even then (as noted by glguy), poor programmers exist in every domain.

I do believe that SQL injection is the most dangerous web app vulnerability and that it is far too prevalent regardless of whether the site was designed by a one man shop or a team of experts. Take a look at the Cardsystems breach that exposed 40 million credit card numbers or the vulnerable Rhode Island government web site that allowed Russian hackers to steal 53,000 credit card numbers. Both are examples where SQL injection attacks led to the loss of private data. Both sites were designed by presumably professional development teams that didn't take security seriously.

# Kirit said on October 5, 2006 12:38 AM:

It'd be interesting to see what you get if you check logins.

Usernames and passwords have to be properly mangled and can't be hidden using data hiding techniques.

The scary thing here is of course that you don't need to go and write software to find these sites, simply Google for this:

"please don't use apostrophes"

:(

K

# Zorak said on October 5, 2006 2:59 AM:

Regarding:

SELECT * FROM users WHERE name = 'Michael'

Database libraries should include a method (like $dbh->quote() in Perl using the DBI module) for quoting string literals.  Not only does this allow the right thing to happen when you *want* a quote in the literal, like where the name is O'Something, but it also protects against using '; for arbitrary SQL injection.

# Wouter Verhelst said on October 5, 2006 6:48 AM:

It would appear that web applications are more vulnerable, not because they're running on your own hardware, but because you simply need to verify more.

When you write a GUI application, everything runs on the same system. There is no possibility of anyone intercepting your cookie, because there is no cookie to be intercepted. There is no possibility of anyone bypassing the user interface to feed some invalid data to the processing bits of the application, because they're more tightly coupled.

That's not to say that you don't need to do /any/ verification when writing a GUI application, but the risks to make mistakes are smaller.

# sql-ballmer said on October 5, 2006 9:01 AM:

Parameterized SQL statements! Parameterized SQL statements! Parameterized SQL statements! Parameterized SQL statements!

# Erik said on October 5, 2006 9:28 AM:

sql-ballmer - I couldn't agree more.

# Cleiton said on October 5, 2006 10:10 AM:

Nice article, very straight and to the point. Towards the end you state that:

"Granted, this test did not proceed to attempt to extract data from the databases as that would be illegal ..."

Agreed. But is it legal to insert that apostrophe in the first place?

# Erik said on October 5, 2006 10:54 AM:

Cleiton - That's a fair question and one that I certainly contemplated before making the posting. It's also the reason that I wasn't comfortable naming any of the vulnerable servers or releasing the code that I had produced. I should never be confused with a lawyer so take my thoughts with a grain of salt. After the post, Jeremiah Grossman pointed out a UK law which states that "it is an offense to make a computer perform a function and for that function to be deemed unauthorized by the owner of that computer". Could this be interpreted to mean that the insertion of an apostrophe is an illegal act? Perhaps. I agree with the comments on Jeremiah's blog however that this is a frighteningly broad definition. In short, I don't know. I'm not aware of any legal precedence that would suggest that such a test is legal or illegal. I certainly welcome any posts related to the topic as the emergence of laws that try to address computer security as it’s something which certainly interests me.

# b said on October 5, 2006 11:34 AM:

Most us laws regaurding internet crimes have intent as a factor.  Assuming sutton did not do any damage, and did not have intent to do any damage, chances are low of any conviction.  Although it still took some balls to post this.

# Richard said on October 5, 2006 12:49 PM:

The best solution is to always use bind variables when querying a database if your programming language supports it. This ensures any SQL embedded in a query is automatically escaped.

# mat said on October 5, 2006 12:53 PM:

By the way: just entering some strings from the screenshot in google is enough to track down the sites you've been testing on ...

# Erik said on October 5, 2006 1:11 PM:

...and building a comprable application or conducting a manual search based on what was discussed will return the full results. The vulnerable sites are out there and are publicly accessible. Hopefully discussing the threats posed by SQL injection will increase awareness among developers.

# itsme said on October 5, 2006 1:30 PM:

How many vulnerable sites were PHP/MySQL compared to ASP/SQL? Your screenshots (where visible) show PHP but no ASP - could this be that open source proponents = bad programmers, MS = good?

# rebels said on October 5, 2006 1:34 PM:

For us, the only way around SQL injection was to filter the input before passing it into a store procedure.  

For example,

Function FilterAlphaNum(str)    

 Dim regExp    

 Set regExp = New RegExp

 regExp.IgnoreCase = True

 regExp.Pattern = "[^A-Za-z0-9,\s]"

 regExp.Global = True

 FilterAlphaNum = regExp.Replace(str, "")

End Function

If the use of quotes potentially might be needed, we do a replace of ' with '' and then filter.  So far so good.

# jose said on October 5, 2006 1:41 PM:

Ok what are some steps to protect from such attacks?

# some guy said on October 5, 2006 1:46 PM:

This search only looks at GET based SQL injection and does not capture POST-based requests that are often thought of by developers as "hidden".  I've tested apps that had no SQL injection in any GET's but were a mess on POST-baesd input.

# wirefall said on October 5, 2006 1:51 PM:

Regarding the potential "illegality" of these tests, there is a precedent setting case at least in the UK. Search for "Tsunami appeal site 'hacker' found guilty". This security professional argued that he believed he had fallen victim to a phishing scam and performed a few basic queries, such as directory listing attempts, in order to verify the legitimacy of the site. The judge stated that it was "with deep regret that he was finding him guilty". Deep regret, but guilty all the same. Caveat Testor!

# Mike said on October 5, 2006 2:00 PM:

Just curious, did you try to notify the sites you tested of their vulnerabilities? Not saying you should have, or anything, because the fact that you are bringing this to light is great. Made me walk over to an colleagues computer and check a site he is developing to make sure he is using parameter-based db transactions. :)

# Brenno said on October 5, 2006 2:24 PM:

Fascinating article, Michael.  I do agree that more and more individuals are able to elevate themselves to the false status of "webmaster" or "programmer" simply by downloading many open source applications (Joomla, Drupal, Wordpress, etc.)  While I would imagine that larger projects such as the aforementioned would have a reasonable baseline of security integrated into their core, the trouble comes when users begin to download plugins written by others or attempt to write their own plugins and modifications by hacking away at the code.  These additions may be written by very unskilled (but well intentioned) programmers who simply don't realize the flaw in their coding or methodology.

# Ran said on October 5, 2006 2:37 PM:

> how to protext against such attacks?

Get a web application firewall. Even with the best, most security concious developers, mistakes will happen.

# Erik said on October 5, 2006 2:49 PM:

Mike - To answer your question I did not individually contact each of the websites that showed verbose error messages. While I would love to be able to have tracked down contact info. for any affected sites and speak to them directly, it just isn't reasonable to do so given the time that it would take. That's why I chose to not directly reveal the names of affected sites. Hopefully by discussing the risks posed by SQL injection in the long run we'll see less of this.

# Maria said on October 5, 2006 2:51 PM:

I don't really get this.  Did you do anything to screen out content management systems where the whole point is to give people the data anyway?  I have a feeling my sites would flunk your "test" but why would I care?  How do you think you're going to get to tables I don't have pages accessing this way?  What am I missing?

# Lhotian said on October 5, 2006 2:53 PM:

A good solution is to use the escape API from the vendor driver.

MySQL: http://dev.mysql.com/doc/refman/5.1/en/mysql-real-escape-string.html

Its common to found a wrapper to the C API from language specific driver (eg.: PHP -> mysql_escape_string() or mysqli_escape_string() ), becose the driver will escape multi-byte chars too, dont known if parametrization will do that :)

Another good way is clean _evil_ code like commit ( ; ) and quotes ( ' " ), but in this case you can loose information :(

In web applications you can convert your data to html entities, like " => &quote;, but with the drawback of use more bytes to store the same information.

Btw, great post :D

All the best

# Erik said on October 5, 2006 2:59 PM:

Maria - to clarify, SQL injection attacks are not limited to data that the web page has access to. Based on ACLs within your database such attacks can be used to access all data, whether the developer intended to expose it or not. Even if all data was meant to be be readable, data corruption could occur by injecting new data or deleting existing data. It can be taken even further if things such as extended stored procedures are permitted. Take a look at some of the many whitepapers on the topic of advanced SQL injection such as this one from Chris Anley to better understand the risks posed by SQL injection.

# J. Freeman said on October 5, 2006 4:24 PM:

The old adage: sanitize user input. This goes for database insertion as well as outputting to the client.

My preferred method is to cast all incoming variables to their expected types, and to escape all strings before database insertion.

SQL injection becomes impossible when you take the appropriate steps; problem is there's a lot of people who don't.

# sql-ballmer said on October 5, 2006 4:26 PM:

I’ll say it again:

Parameterized SQL statements!

Parameterized SQL statements!

Parameterized SQL statements!

Parameterized SQL statements!

I… LOVE… PARAMETERIZED SQL STATEMENTS!

If you try to filter queries yourself, you ARE going to miss edge cases. You ARE going to mess up the URL decoding. You ARE going to forget to look for semicolons.

Use the provided library functions. In .NET, use IDbCommand.Parameters (a.k.a. SqlCommand.Parameters). In PHP-PDO, use prepared statements and bindParam(). In Python, use DB-API parameter substitution.

Do not: insert strings into SQL statements by concatenation, even if you believe you have properly "escaped" them.

# Toad said on October 5, 2006 6:48 PM:

I may be a paranoid programmer, but along with parameterized queries I also use custom 500 error pages and restricted database users.  The article about the Rhode Island vulnerability clearly shows how the hacker used detailed error messages to their advantage.  When possible, I'll configure the web server to run a custom 500 error page that displays a generic error message to the user and records the error details for the administrator.

As a final safegaurd, I'll configure the database user with only the privileges they need to run the web app.  While it can be a PITA to develop against a database where privileges have been granted at the object level, it's more secure than connecting to the database as a user with dbo privileges, or worse, connecting as root or sa.

# Sridhar said on October 5, 2006 8:16 PM:

what a simple and amazing way to find the vulnerable sites.

After id=10'.. after the websites coughed up the table names

i tried id=uri_escape("10' or 1=select count(*) from table;--") {uri_escape is a func in perl} and could easily get that statement executed... god save them if their database is writable... I forced myself to stop there :)

# Rodney said on October 5, 2006 9:21 PM:

That's pretty odd & sad in this day and age. None of these are new...

Cross site infection: I thought everyone knew to only allow SQL connections from localhost, for this specific purpose?

SQL Injection: WTF? Isn't this were people use things like appending "?username like 'x' or id = '1" etc to a URL? Again, I thought this was pretty well understood that you need to a) sanitise variables and b)don't use SQL authentication that includes a superuser.

Buffer overflows: Patch. URLScan (IIS). ModSecurity (Apache). Nothing more to say.

Just goes to show that lots of people still aren't getting the message, I suppose... This is why everyone should use ModSecurity on their Apache box and configure it to dump any requests that are obviously not nice. That way, you're not at the mercy of programmers who don't care /understand about security.

To remove buffer overflows, include ModSecurity in Apache and do:

SetEnvIfNoCase Content-Type \

"^multipart/form-data;" "MODSEC_NOPOSTBUFFERING=Do not buffer file uploads"

URLScan prevents long string entries on IIS 5 (and is built into IIS6) so you cannot run simple buffer overflows, even where the kernel is vulnerable.

To filter out SQL injection (for example phpBB2 injection uses phpbb_root):

SecFilter phpbb_root

SecFilter cmd (no more stupid Windows robots trying to run cmd through a shell exploit)

Basically, it's all about trying to stay ahead of the game which is that much harder when you've got other people putting code on your box. Seriously though, if you take a more agressive approach and shield the code from odd requests, life will be easier.

Good luck all. Enjoy! :)

# LV said on October 5, 2006 9:44 PM:

Parameterized SQL statements!It's the best!

# Andrew said on October 5, 2006 10:34 PM:

To Maria;

I submit the following (equivalent) modification to your website:

username=me'; drop database;

So the answer to your question of "What am I missing?"...

You could be missing your entire database shortly.

# Gregory said on October 5, 2006 10:49 PM:

> I have a feeling my sites would flunk your "test" but why would I care?  How do you think you're going to get to tables I don't have pages accessing this way?  What am I missing?

You should care... what if I replaced "id=10" with "id=10;DROP TABLE users"? By putting a semi colon in there, I can execute arbitrary SQL and I HOPE you can see the danger in that.

# Me said on October 5, 2006 11:12 PM:

While I don't discredit the importance of security, and while I do recognize the possibility of SQL injections in such a manner, I have to point out a serious flaw in your logic.  Many programming APIs simply do not allow multiple queries to be sent in one statement.  Simply containing a semicolon would cause them to throw an error and quit.  However, I don't use ASP or Java, so maybe they do allow it?   Perl's DBI doesn't.  If memory serves, PHP's built-in database stuff doesn't.  I seriously doubt Python or Ruby allow it.  So, even without doing any validation of your input values, all a hacker could do is alter the select query to include additional arguments of his choosing.  Since the variables are used in the WHERE clause, you can't join additional tables (you'd get an SQL error), although I suppose you could do a UNION which would require you to extract the same number and types of fields in the original query (or get another SQL error).  Of course, I'm in no way excusing the laziness (or inexperience) of the programming in question.  I just don't buy the seriousness you're lending to the method.  If anything, I'd consider it a minor threat, especially given the need to know the database schema to even possibly do anything useful with it.  Of course, if you could throw any willy-nilly query on the end, which may be possible with some programming libraries of which I am not aware, then you could sniff the schema and do all sorts of nastiness.

# Eddie Romingo said on October 5, 2006 11:55 PM:

I have been reading a lot about SQL injections. Our developer has left one of the main SQL queries visible in the HTML. How large a risk does this pose to me?

# Dave said on October 6, 2006 12:27 AM:

Couldn't agree more. However I am always surprised by the number of people who use dynamic sql in their procedures!

I recently purchased an ASP forum app and I choose the one I did because it was the only one that stated that it used stored procedures. Well you can imagine my shock and dismay to find a whole load of crappy stored procedures using dynmaic sql built with strings passed as variables. :(  an utter waste of time and cash.

Also, In response to itsme:

"Your screenshots (where visible) show PHP but no ASP - could this be that open source proponents = bad programmers, MS = good?"

I think it is more likely to be due to the fact that until very recently mySQL did not feature stored procedures so ALL sites built with mySQL had to use dynamic SQL in thier pages.  (a lot of php sites are backed with mySQL)

Every time I thought I should take another look at mySQL I stopped as soon as I saw that lack of support.  I guess now I have run out of excuses and should take it for a spin.

# SQLDemon said on October 6, 2006 5:38 AM:

sql-ballmer, you are right, Like you I wonder how many times you have to say

Parameterized SQL statements!

Parameterized SQL statements!

Parameterized SQL statements!

Parameterized SQL statements!

... before people will listen. Perhaps they're all too busy hacking together regexes to escape user input ;-)

# Dionysis said on October 6, 2006 6:28 AM:

Can we download this "tool" that uses the Google API?

# Erik said on October 6, 2006 7:57 AM:

Dionysis - I don't plan to post the tool as I suspect that it would be used for more evil than good. However, I can assure you that it's nothing special. An hour and a basic knowledge of the Google API is all that it took.

# Cleiton said on October 6, 2006 9:06 AM:

"Me" said:

"Many programming APIs simply do not allow multiple queries ... I suppose you could do a UNION ...  I just don't buy the seriousness you're lending to the method.  If anything, I'd consider it a minor threat"

Well, many programming APIs do allow it. Even if they don't you still can do a lot of harm. As you said you could use UNION, and when you do, it usually goes on like:

1. Find out the number of columns in the query (using order by)

2. Insert the second statement (using nulls to bypass type errors)

3. Extract metadata from catalog tables (MSSQL, oracle, DB2, etc)

4. Extract important data such as credentials or CC #s

So, I have to disagree, it is still a major threat. Yes, It can be stopped (or mitigated) in many different ways, such as application layer firewalls, stored procedures, Parameterized SQL, avoiding detailed error messages, lowest database privileges,  escaping, validating user input, etc... we just need to educate the average developer on the subject.

# Tom said on October 7, 2006 3:12 PM:

I totally agree about parameterized SQL.  It seems like every time there's one of these discussions, there's a minority of people who insist on parameterized statements but they get drowned out by people recommending regular expressions (hint: it won't work) or something like mysql_real_escape_string in PHP (MySQL-specific and probably still exploitable).

There are infinitely many games people can play with comments, semicolons, special keywords, etc. to trick your escaping method or your validation, and whatever validation rules you have for one flavor of SQL definitely won't work for a different database's SQL language.

# chinesed said on October 9, 2006 5:38 AM:

interesting results and nice way to search for valid data! thanks for sharing!

# Green_Monkey23 said on October 13, 2006 4:15 PM:
Sorry for your time.... Why i can't see images on this resource? My Browser is: Opera. Thank you.
# Erik said on October 16, 2006 9:43 AM:

Green_Monkey23 - Are you using the latest version of Opera? I just tested the site with Opera 9.02 and didn't have any problems with images.

# Jeff said on October 16, 2006 2:27 PM:
Good stuff, but I wonder - what makes you think you didn't hack the sites? Sure - you used Google to find a set of interesting targets, that's not hacking. But then you used your computer to directly connect to those sites and enter a mutated GET request knowing full well that some of them would demonstrate a vulnerability. That's a weak form of hacking. It is more or less like walking down the street turning door knobs, but not opening doors. Is that breaking and entering? Hard to say - but it is definitely different than looking a photos of doors and guessing which are locked.
# Erik said on October 18, 2006 5:01 PM:

Jeff - You bring up a fair point that is certainly worthy of debate and one that I've discussed with various people. The short answer is that I'm not aware of precedence that would suggest just where the line lies between browsing and hacking. As mentioned previously in the comments for this blog, I'd love to have people forward examples of past/current cases/articles/laws/etc that provide insight. Are the many XSS Hall of Shame sites illegal? Good question. What if I increment a numerical value in a linked URL and access a non-linked page? Is that illegal? It's a publicly accessible page just as an error message is publicly accessible, it's just a matter of browsing the correct URL. My point is simply that laws surrounding web application security and security in general are not well defined. My intent is of course to educate rather than cause harm. This is a topic which is very worthy of a much larger debate.

# Jeff said on October 19, 2006 4:13 PM:

Agreed - a very sticky issue. I think we would all like to know exactly where that line is. There are many fun and informative projects that are just a little in the grey...

# Russ said on October 21, 2006 12:19 PM:

@Kirit:

Just followed your suggestion (http://www.google.co.uk/search?q=%22please+don%27t+use+apostrophes%22), and result number 5 was this gem:

"Please don't use apostrophes in your user name or password. All information is kept secure and confidential."

- http://www.botanicalbee.com/xcart/catalog/FAQ-sp-8.html

# upyrs said on October 24, 2006 5:49 PM:

man is always nice to see what people born with a book in their hand have to say ! (! is for negate, you all know that)

# valentinv8 said on October 25, 2006 5:01 AM:

It is good practice to use only PHP/MySQL functions to check the variables. A simple preg_match('/^[a-Z]*$/', $var)-only letters- used before the query should do just fine. If not only letters found, don't execute the query or replace the input with something valid, something like displaying all the database items (if it is a search). Keep everything as simple as possible. Watch out for ASCII.

# BugsBunny said on October 30, 2006 3:00 PM:

nice hands-on video on sql injection

http://youtube.com/watch?v=MJNJjh4jORY

# Michael Sutton's Blog said on November 1, 2006 12:48 AM:

I often surf the web and see blatant design errors that make me shake my head. Without even investigating

# Anurag said on November 1, 2006 3:21 PM:

Even if your programming env does not allow execution of multiple db statements at one go, SQL injection leaves you vulnerable to exploits like this:

http://www.oracle.com/technology/oramag/oracle/05-jan/o15asktom.html

Bind variables! Bind variables!!

# wholeshebang said on November 2, 2006 1:16 AM:

<blockquote>The scary thing here is of course that you don't need to go and write software to find these sites, simply Google for this:

"please don't use apostrophes"</blockquote>

Just for kicks, I did. Furthermore, I randomly picked a site and purposely did just that (everything else was plain text and nothing that could be intrepreted as a command):

<blockquote>Isn't it a great day</blockquote>

Results:

<blockquote>Technical Information (for support personnel)

   * Error Type:

     ADODB.Connection.1 (0x80004005)

     SQLState: IM002 Native Error Code: 0 [DataDirect][ODBC lib] Data source name not found and no default driver specified

     /guidetos8/notifyLS8.asp, line 14

   * Browser Type:

     Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7

   * Page:

     POST 151 bytes to /guidetos8/notifyLS8.asp

   * POST Data:

     Name=+bob&Company=testing&EmailAddress=123test%40fake.email&EmailAddress2=123test%40fake.email&Phone=123-456-7890&Comments=Isn%27t+it+a+great+day&OK=OK

   * Time:

     Thursday, November 02, 2006, 1:11:37 AM

   * More information:

     Sun ONE Active Server Pages Support</blockquote>

# Jonathan said on November 2, 2006 12:57 PM:

"It is more or less like walking down the street turning door knobs, but not opening doors."

We used to pay Beat cops, trusted individuals, to do this for us.  Are we internet users prepared to start paying taxes to fund a security force?

Of course, just because a cop is on the gov't payroll, doesn't mean they aren't on someone else's too..

jbd

# Tasen Software said on November 3, 2006 4:44 PM:

I also see SQL injections as a particularly prevalent problem. It behooves us, as web developers, to learn as much as we can about security vulnerabilities. In fact I probably need to investigate some of my old old sites to see if they fail the test.

http://www.tasensoftware.com

# Thomas said on November 4, 2006 6:37 AM:

For the PHP-fans interested in a real easy solution (Only for the noobs, if you know PHP, you know this ^^)

use this:

$userInput = addslashes($_GET['page']);

$query = mysql_query("SELECT * FROM pages WHERE pageid = '$userInput'");

this way, if the (malicious) user enters something like

10'; malicious command

PHP will convert it to

10\'; malicious command

so that you stay in your SQL command

# Mike Katchourine said on November 6, 2006 8:59 PM:

The simple fact is that the free market is a self regulating force, alway had been. So let's not freak out and allow the market to regulate itself :) SQL injection had been here for close to a decade now, and bad programmers for close to 50 years, yet things keep moving forward :)

So far, overall, and quite unfortunately, bad development is more cost effective than good development. Similar to investment in greater fuel efficiency for automakers - not cost effective while cheap or relatively cheap fuel is abundant.

While the number of potentially problematic sites identified by Mr. Sutton, is large, so is the Internet. I daresay that the absolute majority of the googled sites, even if breached, would have no information of any significal financial worth.  The more financial exposure a company carries in its web outlet, the larger security investment it's bound to make.

As far as parameterized commands and queries..... He he :) Why do you guys thing they are used so infrequently? They require much greater expertise to write. A person has to KNOW they exist and how to use them :) People start learning from raw select/insert/update statements, and most stay there. You go to what you know :)

# Richard said on November 7, 2006 12:21 PM:

IANAL, but from my understanding of the law, you would only have committed an offence under the law of England and Wales if you had the "intent to secure access to any program or data held in any computer" when you ran these tests. It's arguable whether you did or did not. I don't think there is any case law in our courts to test this particular situation.

However, the Police and Justice Bill currently going through the UK parliament will amend the law so that any unauthorised act with regard to a computer system, irrespective of the intent underlying that act, will become a criminal offence punishable by up to five years in prison! Scary. Your actions would be caught by such a law, so it's a good thing it has not received royal assent yet.

# wahooga.com said on November 21, 2006 3:44 AM:

It is still quite hard to believe how many web &quot;designers&quot; and &quot;developers&quot; implement

# Michael Sutton's Blog said on December 6, 2006 4:17 PM:

Earlier this week, yet another rapidly spreading MySapce worm reminded me of a frequent dilemma in computer

# Ivan said on December 7, 2006 4:42 PM:

It is amazing what you can do with SQL Injection.

A few years ago, when I first started hearing about SQL Injection and started testing the concepts out on my own server, I developed several really neat "scripts" that could be added to a querystring/form field that was vurnerable.

For example, I was able to inject a script that created a stored proc, that opened up a tcp/ip connection to a FTP site, downloaded a binary file, and then executed it right on the server.  Scary stuff.

# David Conrad said on December 12, 2006 6:49 PM:

Michael: Twice you have referred to legal 'precedence' -- you mean legal precedents.

Let me repeat it again for those who have wax buildup in their ears: parameterized queries, parameterized queries, parameterized queries!

# Erik said on December 13, 2006 1:16 PM:

David - Thanks for the correction. Surprisingly I've never won a spelling bee.

# Michael Sutton's Blog said on January 8, 2007 6:49 PM:

Yesterday, Google Labs launched a search tool that has many developers salivating. It&#39;s called Google

# Mehran said on January 30, 2007 8:18 AM:
Hello can you Mail to me Linke of That Goolge SQL Injection Software ? Thanks in Advance My Email : Mehran_Kherkhere@hotmail.com
# Erik said on January 30, 2007 4:47 PM:

Mehran - I'm not handing out the code because it could be abused. However, it's a pretty simple application. There are certainly adequate details in the blog to re-create it if it's needed for research.

# Michael Sutton's Blog said on January 31, 2007 1:38 PM:

How Prevalent Are Cross Site Scripting (XSS) Vulnerabilities? Based on a recent experiment, I wasn&#39;t

# ljianl said on February 25, 2007 12:33 AM:

【原文地址】Tip/Trick: Guard Against SQL Injection Attacks

# 黑星 said on March 6, 2007 7:53 PM:
# emacs said on March 12, 2007 9:18 AM:

Has anyone experiences with sql-injection on systems using Hibernate the OR-Mapping tool in java?

I just wonder if this is a good approach to secure your webapp...

# Eeve said on April 23, 2007 2:29 PM:
I find it shocking how many programmers don't do a parseInt/intval on integer id parameters. So simple- yet so crucial.
# Save money on taxes said on October 6, 2007 9:57 PM:

It is right on that getting accurate information on this topic can be troublesome.

# Neil Carpenter's Blog said on March 14, 2008 4:25 PM:

A number of people are reporting that 10K+ websites have been hacked via a SQL injection attack that

Leave a Comment

(required) 
(optional)
(required) 

About Erik

Erik is Sr. Director of Products for the Application Security Center.