SQL Injection Attacks Increasing
An anonymous reader writes "Help Net Security has a story that covers the dramatic increase in the number of hacker attacks attempted against its banking, credit union and utility clients in the past three months using SQL Injection." Article follows up on press release with a little more information. Not a lot here shockingly surprising, but it's worth mentioning that SQL injection is a real pain for web developers. You have to be very careful about checking user input.
Sudden traffic surge from certain news sites can be a pain.
Simply forcing request variables to the correct type and escaping all strings is pretty much the only thing you need to do.
Most languages provide the functionality to do that (in php: intval() for all integer request vars, and _escape_string() for string data.).
It's just a small amouth of work, yet a lot of people are way to lazy.
"SQL injection is a real pain for web developers. You have to be very careful about checking user input." Say what? All you have to do is use parameters, not string catenation. Of course, checking the user input is good for other reasons but not for SQL injection attacks. Or are there web application frameworks which don't support parameterized SQL statements?
Perhaps all programmers working on professional database systems should have to get a professional qualification to show that they can write secure code. I wouldn't say the same should be manditory for things like usability or stability (except for special sensitive areas), but being able to write code that actually allows serious danger without qualification is pretty weird. Builders need qualifications, electricians do, gas installers do, ...
The only people who consider it a pain in the ass are people who are (a) lazy, (b) not adequately security-conscious, (c) programming without a framework that provides good tools to do this. The reason we have so many SQL injections is because we have legions of web programmers who were never taught how to write code in a hostile environment. Web programming is never presented in that light; it's always, "here's a quick little script that fetches twenty records from a database and displays them." Security is far too often a footnote or an appendix that beginning programmers never get to. Building apps for the web is not like doing your Data Structures I homework. You need a different mindset. It's a lot more like designing locks--for prisons full of inmates eager to get out.
People are never as simple as their stereotypes. This applies equally to Christians, Muslims, and Emacs-lovers.
How can it be that hard for web developers to check data before it is submitted? I wouldn't imagine trusting the data that an anonymous user can enter into my website.. so maybe I'm just trained to check data. Of course, I'm also glad I use MySQL with PHP where a simple mysql_real_escape_string can prevent any popular SQL Injection attempt.
but it's worth mentioning that SQL injection is a real pain for web developers
Which web developers would these be? MuppetsR'US ? SQL injection is a pain if you take the input and lob it directly to the database without doing any sort of validation that the information is sensible.
Its a great example of all those people who scream "THIS IS SO MUCH QUICKER TO DEVELOP IN THAN THE OLD WAY" and then bite it after the system goes live.
SQL injection isn't a pain, except for those who think they've found a new quick magic bullet that solves all the problems and the old fuddy duddy practices are now all redundant.
An Eye for an Eye will make the whole world blind - Gandhi
Interesting, given that SQL injection is one of the easiest attacks to protect against, by making all database access through an abstraction layer that escapes input, many web frameworks have support for database abstraction layers and prepared statements, like PEAR::DB for PHP, developers just need to make use of them.
python>>> q="'";s='q="%c";s=%c%s%c;print s%%(q,q,s,q)';print s%(q,q,s,q)
You're absolutely right - SQL injection attacks are extremely simple to avoid (note - avoid, as in never being able to do them) Mostly it is incompetent and/or lazy code monkeys that are at fault.
The cesspool just got a check and balance.
You mean everyone doesn't use parameters and stored procedures. Sheesh.
Checking input for escape attempts is error-prone. Passing in parameters as bind variables *isn't* error-prone (with regard to blocking SQL injection attacks); makes string quoting completely moot; and can result in a massive performance increase (particularly against Oracle) to boot.
I continue to be in disbelief that anyone doing professional database work can *not* follow this widely accepted best practice and continue to be employed.
But I can't imagine that it would be much more difficult to protect a database, that is accessable through the web at large, than by ensuring that the only thing that goes through the form is alphanumeric numbers, and possibly the @ symbol and periods in email spaces, and then you can employ format checking to make sure it's something like blah@foo.com.
I don't think I've ever had a need to enter anything that isn't as simple as my name, email address, phone number, or numbers with periods (for banking), so why would putting a check for this be such a difficult prospect?
I'd imagine that the only circumstances where someone might have to input contrary data to plain alphanumerics might be inside corporate sites, but then wouldn't there be security in place to ensure that only valid users have logged in, again with nothing more than alphanumeric characters?
Don't tell me that there's a growing number of web sites that aren't doing format checking (on the server side of course, to prevent people working around javascript checks locally) on their login inputs and other form fields before processing the input further.
Te Quiero, Puta!
If your webapp is Java based, use PreparedStatements. Never use Statements. PreparedStatements are immune to SQL Injection based attacks since the variable replacements are never interpreted. PreparedStatements are also much, much faster.
Sure, if I'm putting together a blog for myself security may not be my top priority and in a situation like this the "I'm too lazy and this is a pain in the ass" excuse is fine (just dont complain if things go wrong).
However, it's an alltogether different story if you're doing professional web development - the "I'm lazy" excuse doesn't cut it when you're developing something commercially. It is your job to make a functional application and a (large) part of that is making it resilient towards exploits. How pretty your app is doesn't mean squat if every 14 year old script kiddie can have his way with it.
Furhtermore, note:
2 +vulnerability+perl
2 +vulnerability+php
http://www.google.com/search?q=sql+perl
"Results 1 - 10 of about 69,700,000 for sql perl"
http://www.google.com/search?q=sql+php
"Results 1 - 10 of about 151,000,000 for sql php"
http://www.google.com/search?q=%22sql+injection%2
"Results 1 - 10 of about 243,000 for "sql injection" vulnerability perl"
http://www.google.com/search?q=%22sql+injection%2
"Results 1 - 10 of about 2,170,000 for "sql injection" vulnerability php"
The ration of pages about SQL in general on PHP and Perl is about 1:2. The ration of pages on SQL injection is about 1:9.
SQL injection is mainly a problem with PHP, because of the useless design of the database interfaces.
I thought if you just parse out the ' in user input you are immune. No?
;.
With all my Web Apps I create a function called SafeChar, and have it replace the ' with '
How else is SQL injection done? It's an embarrassing questions to ask, and fortunately I write software for small companies internal use only... but if you don't ask I guess you don't learn.
Oh and what does? ASP-Visual Studio.NET Framework 3.14159265358979323846 Express Enterprise Edition?
Make sure you specify where you get your incoming data from, like using $_POST, $_GET, $_SESSION, etc, don't just grab them from the air (with globals on).
Make sure you use mysql_real_escape_string() on all incoming data that is headed for the mysql database (to get rid of SQL injection).
Make sure you use strip_tags() on all incoming data that is headed for output on your page (to get rid of cross-site scripting).
Meh.
Well, better to light a candle rather than curse the darkness.
Here is an article for beginners about SQL injection hacks.
Just don't build your query on the fly.
Bind ALL parameters to placeholders in a prebuilt query. Binding is an instant kill for any SQL injection attack. It is also much more effecient on many databases.
There is nothing so silly as other peoples traditions, and nothing so sacred as our own.
Since when is it the job of the language to protect you from SQL injection? I think you're confusing the language of PHP with the standard libraries it ships with, mysql_*() and co. It's worth noting that PHP *does* support prepared statement's using the 'new' object oriented mysqi interface much like the Perl DBI. This handles the casting of types and escaping of strings for you.
This advertisement for stored procedures has been brought to you by Slashdot!
ADO.NET has had parameterized queries since 1.0 was released in 2002...
.NET.
The old ADO also had paramaterized query support, although they weren't as easy to use as in
this approach seems more correct than escaping strings.
Perl does. Python does. I'm pretty sure Ruby does. I'm told there are several modules for PHP that do.
SQL injection is only a problem in PHP because PHP does it all wrong by default.
Of course it's the job of the language to make it as easy as possible to write secure code, and as hard as possible to write insecure code. That should be blindingly obvious, especially for a language that's pretty much aimed at people with little programming experience who are likely to have no idea what they're doing.
u twatfaced fuck-wuppit.
Well, better to light a candle rather than curse the darkness.
You must be new here.
As a code monkey who, in my ever-dwindling spare time, is helping a friend set up a small business website - and learning PHP as I go, I appreciate the link.
Some of us are not lazy or even stupid - just inexperienced.
Running Windows^H^H^H^H^H^H^H OSX and Linux in the home. (I don't have time for Solitaire any more.)
it's worth mentioning that SQL injection is a real pain for web developers.
I think it is worth mentioning that SQL injection is a real pain for poorly developped web applications. A simple paying-attention and good design of the application layers makes sure SQL injection cannot happen at a cheap cheapo price. 3-tiers anyone?There is the mysql-real-escape-string to prevent injection in MySQL along with pg_escape_string for PostgreSQL.
Was anyone else bothered by the ads on that site? That has to be one of the worst content/ad ratios I've ever seen. Each article had to have maybe 2 sentences of code, and the rest was covered in blinking ads or google ads.
You have to be very careful ...
This phrase is a common tipoff to one of the main problems.
The computer doesn't give a damn how careful you are. If you spend hours carefully crafting a chunk of code that, through your ignorance, has a big security hole, all your care hasn't helped a bit. You have merely produced bad code.
OTOH, someone with good knowledge of the subject might toss off a 30-second routine that, due to their understanding, is highly secure.
Carefulness has little to do with doing a good job. Carefully doing it wrong is merely doing it wrong, no matter how careful you are. And doing it right is doing it right, even if you hardly gave it a thought.
What we need here isn't useless exhortations to "be careful". What we need is education about how code gets into trouble, and training in writing code that doesn't have problems.
Yeah, I routinely write code that checks input. But if there's some hidden gotcha that I don't know about (typically in some library routine that's not visible to me), I'm quite aware that my careful checking might do little good.
Those who do study history are doomed to stand helplessly by while everyone else repeats it.
If you just remove or escape any ' characters, you're depending on there not being any byte sequences that the database interprets as ' characters that your function doesn't. This has often turned out not to be the case, particularly with respect to invalid UTF-8 strings. The only safe method to avoid injection attacks is to make sure that no database code parses a statement including user input, because you never know exactly how the database parser will handle statements that programmers wouldn't send intentionally, and so you can never be sure that you're cleaning the input enough. (You can clean the input enough that the standards say it can't end the string, but then you're depending on the database's parser to be bug-free in this area, which has not historically been the case.)
Just stick it around any non-constants you pass in to MySQL (especially ALL user input or user-influenceable input) and you should be good.
Of course, to minimize the risk that you miss one, you might want to use functions or classes to wrap mysql_query. EX I might make a "function selectFromTableX" that takes one field name and one value to compare for equality in the WHERE clause (assuming that's all I ever use SELECT on that table for). Or you can make a class for every table and wrap up ALL queries for that table you'll need.
First rule of writing CGI: never trust the data! I work in Perl, and when an app is exposed to the outside world, I have to assume someone is going to try and get in through some hole if they can (or worse, will do something stupid that would have a negative affect oon my systems).
It starts with the web page -- validate input data. I know, I know, anyone can copy your page and rip out the JavaScript validation, but it doesn't hurt to put up a first line of defense. Next, before you actually use the data from the form for anythig validate it separately. In Perl, I have taint mode enabled by default for external apps and I treat all the data I receive as if it were dog crap. I massage it with regexes to make sure it is what it's supposed to be, and then pass it on to be processed. I find the best way to put up a wall is to have the form parameters sent to a validation script, then have the validation script call the script which would run the actual query, throwing back an error message to the user (and sending me a message in the process) if something's not right.
Data validation is really not that hard, especially if you know exactly what the inout is supposed to be. It gets iffier if the user can put in pretty much anything -- then you have to be a little more paranoid.
GetOuttaMySpace - The Anti-Social Network
I've been writing my code on a paranoid basis for a long time - all my queries are built by a class that does its own escaping. I wish I'd known about this earlier.
Last post!
- Stored Procedures
- Parameterized Queries
- Learn the SQL-92 Specification (so that you're familar with the language beyond just SELECT, INSERT, UPDATE, and DELETE. There are all kinds of things out there to help you get rid of that dynamic code, like COALESCE, and CASE WHEN, etc.)
Here's the SQL-92 Specification (pops in a new window)Often when I am on a page that looks SQL-injectionable, I'll try a few things just for giggles. I've been doing this for a few years now. I'd say that there are much, much fewer injectionable sites then there used to be...
are there web application frameworks which don't support parameterized SQL statements?
that would be PHP.
see the problem now?
A better solution is to define all input fields by means of a framework that properly escapes apostrophes and other unwanted characters. This will effectively make SQL injection impossible with a minimum of fuss.
Visit http://ringbreak.dnd.utwente.nl/~mrjb/growingbettersoftware to download your free copy of the book
The last time I did a SQL injection, I hallucinated that everything around me was displayed in an orderly array.
He who knows best knows how little he knows. - Thomas Jefferson
There is a way to solve SQL injection problems: Disallow text literals in the database engine. Or even, disallow literals (including numbers) at all. This could be a setting in the database that is on by default, and only off for certain applications (ad hoc query tools). What do you think about that?
I'm thinking about implementing this feature in the database I write (http://www.h2database.com/):
This would be a persistent setting, and only an admin can change it.(Of course there are other security risks, like using 'customer id' in URL or hidden fields in a web application. Or relying on Javascript data validation. I don't know what to do about those problems.)
Where does the article state that PHP is the cause for it to turn into a anti PHP forum? Im really getting bored of slashdot now where every geek and their dog just posts a rant about the Microsoft, Sony, PHP, spelling.. sorry did i forget any?
Do people here still really not have girlfriends? Or is this place really the geekiest of the geeks. Seriously, this is not meant to be flamebait..
I should have also mentioned that Pro PHP Security is a good book on the subject of creating secure PHP code.
Meh.
No, you don't, unless you are either using an utterly shitty language like PHP that doesn't have built-in protection from SQL injection, or you are going out of your way to make your program insecure by using string interpolation in your queries.
I'm not a PHP guy, but from what I can see it's not a language issue. Or, at least it's not primarily a language issue, although admittedly loose type checking contributes to the problem. It's a library/API issue.
IIRC PHP 5 has the equivalent of prepared statements. The problem is the vast body of code in PHP4 and earlier, or which has been ported to 5. The older APIs should be deprected or removed. This would be a minor pain; however, having installed a few php programs on a later interpreter, it's clear to me the PHP folks haven't scrupled to make pain inducing changes in the past.
Post may contain irony: discontinue use if experiencing mood swings, nausea or elevated blood pressure.
Data Abstraction Layer.
I have a couple hundred SP's in a few SQLServer databases on two servers (test/prod) along with entirely separate Sybase and OMD databases and servers with their own SP and (compile time)SQL. All of that work is taken care of in my DAL. I don't screw around with assembling SQL in code. If I want customer information, I create a customer object and I use objCustomer.Find(CustomerID) or objCustomer.FindByName(CustomerName), etc... I don't have to remember stored proc names, or even complex field names (like the Sybase database where all tables are 3 letter acronyms starting with the letter 'r', it's freaking insane.)
-Rick
"Most people in the U.S. wouldn't know they live in a tyrannical state if it walked up and grabbed their junk." - MyFirs
My department was repsponsible for a maintaining major portion of content on my university's server. Some idiot decided to put phpBB up on his personal site, and our whole data root was deleted and replaced with an "I 0wn j00" message. Hack attempts, which we had been monitoring, went from 2-3 attempts per day up into the thousands.
If any attempts on their servers were successful, attacks would increase a thousandfold. Thus, the number of hackers could be staying the same, but their earlier successes could be focusing their work.
So, anyone know if any of these credit unions have been breached?
are there web application frameworks which don't support parameterized SQL statements?
that would be PHP.
Quit spreading FUD. PHP supports parameterized SQL just as well as any other language I've worked with. See, for example this doc page (search for "Example 2"). Even for databases whose native C APIs don't support the feature (i.e. MySQL), the database abstraction layer PEAR::DB that is distributed with PHP provides emulation.
SQL isn't code. It has absolutely nothing to do with PHP in any integral sense, it's entirely provided by a library. I've already pointed out that there are better libraries and methods available to PHP users as part of the standard package. I am not seeing your point, just random PHP bashing...
No shit! As more people use SQL, and as more bad devs can't test user input properly, THERE WILL BE MORE SQL INJECTION ATTACKS!! Slow news day?
You feel sleepy. Close your eyes. The opinions stated above are yours. You cannot imagine why you ever felt otherwise.
I'm a student web programmer for the webdevelopment lab in a major U.S. University. The platform they basically told me I had to program on is PHP with MySQL. The server doesn't support anything else and getting the server guy to update or add anything new is a major pain and usually impossible. Point in case: I'm still working with PHP 4.1.2 and MySQL 3!!!!!!!
I still have to write some fairly secure applications (if they get breached there won't be any terribly sensitive information, but there are some things that we would rather be kept private (such as an online-store system for one of the on campus labs.... no purchases online, but the entire store (4000+ items in inventory) is there, along with purchase records, etc). I tried to get the server admin to either upgrade PHP and install the mysqli library so I could actually do compiled queries and all of that, but no go.... Maybe by next year -_- (the guy thought SQL Injections were a local exploit and then thought that since we were running over HTTPS it was okay....)
My point is that sometimes it is not the programmers fault that they cannot make use of the some of available options to make their application supposedly more secure. You have to do the best you can with what you have and write code that is put together well enough that when new features do become available on the server or someone does get breached and it needs to be improved, it is easy enough to upgrade and maintain the code. Right now I'm stuck using mysql_escape_string and type checking (heh, not even _REAL_escape_string...... the PHP version is that old!) and keeping my fingers crossed (and continuing to pester the admin hoping for better results faster). So don't always blame the programmers!! We do have to work within limitations too!
If you can't say something nice, make sure you have something heavy to throw.
Input checking is a half-assed solution.
maybe, but you need to do it anyway. You menton bind variables, and that's definitely something that people should do, but bind variables wont stop out-of-bounds inputs. For example, if you are expecting an integer between 1 and 3, you still need to do input checking.
You might as well call it an MCDBA or some other stupid acronym.
I know plenty of people with letters after their name (MCSE, PMP, etc.) that fall into one of two categories:
1. Capable and knowledgeable about their area of expertise.
2. Complete idiots.
I know plenty of people WITHOUT letters after their name that fall into one of two categories:
1. Capable and knowledgeable about their area of expertise.
2. Complete idiots.
Certifications are pretty meaningless to me. As for whether a CS degree would help, I'd almost say no (The "lesser" MIS might actually be better in terms of requiring DB courses). I finished my CS degree in '94 without having had a single database class. It was an elective, but not a required class. I didn't think I'd need it. My first job, I had to learn database stuff on my own. And in fact, even without taking a database class until I had been working with them for over 7 years, I was considered the database expert at my first company and now second company (both large Fortune 500's).
BTW, the class I took was the one on Oracle tuning...and it was a joke: they recommended using hints in your SQL. You should tune the statement without hints first. Hints should be a last resort. Why do programmers constantly think that they can do a better job tuning than a large team of programmers who's sole job is to tune a database engine?
Layne
You are arguing semantics. The end result of the current state of PHP is: There are a huge amount of scripts out there that are vulenarable to SQL injection, that would not be vulnerable if they were written in another language, because that other language would provide safer mechanisms and encourage their use.
They're called bind variables. Use them and SQL injection attacks go away.
You get what you pay for. A lot of people already suggested easy solutions to the problem that are just as easy to implement and that would immediately make the problem disappear. So why is it not done?
Simple: The people who write those insecure databases don't even know that those functions and features exist. Some ages ago, they learned a bit about SQL, maybe did a course about it (so they have a sheet of paper saying "Look, I can do it!") and that's it.
HR managers tend to go by papers, and by price. Now, who do you think is cheaper to hire? A person with a well rounded education concerning computers, programs and the fallacies, pitfalls and security issues around them, or someone who learned his SQL statements by heart and has no clue what exactly is going down inside the server?
Sure, both of them will create code that does what the specs say. As long as you only enter data according to spec (which is, interestingly enough, ALL that is checked, even under the SOA). The true quality of code is revealed as soon as you pit something unexpected and malicious against it.
We used to have a Bill of Rights. Now, with the rights gone, all we have left is the bill.
The API is the language. Claiming otherwise is silly semantic games with no connection to the reality of the situation, which is: There are a million scripts out there with SQL injection vulnerabilities, and most of them will be written in PHP, because PHP encourages (by not actively discouraging) you to write insecure code.
I like ColdFusion's method for helping coders protect against this issue -and quite a few other things too: select blah from blah where field = by setting the cfsqltype correctly it also gets around those sodding issues with databases that cant figure out WHICH field you've referenced incorrectly. How many times have you written a 30+ long insert or update statement, go to test it, and receive a message about incorrect data type with no other info... tells you which field broke your query! So the crux of my comment is, I dont know much about PHP or ASP, but ColdFusion developers have ZERO excuse for making the mistake of NOT using cfqueryparam to protect against injection attacks.
I'm thinking if it's a simple form, you can download it. Then you can see how the (very stupid) devs structured their tests and/or edit the form to remove those checks and have the modified form submit the info for you.
Cliff Claven
K.E.G. Party Chairman
Founding Leader of: Koncerned for Egalitarin Governance
Mark me OT or mod me down with something, I'm fine with that.
/.. In many circles, this question would have gotten "do you want me to write your code for you?" or "RTFM", or "Google (something here)", or statements that question the poster's value in the world. I learned something from the replies, and I appreciated the tone of voice of the replies. I, for one, am so glad so many smart people post here.
The responses to the serious question post are an example of what's good about
OK, back to your regularly-scheduled time sink...
A Passionate Independent Musician
Those statistics are pretty meaningless when you look at this.
G =Search
g le+Search
http://www.google.com/search?hl=en&lr=&q=perl&btn
Results 1 - 10 of about 370,000,000 for perl.
http://www.google.com/search?hl=en&q=php&btnG=Goo
Results 1 - 10 of about 5,540,000,000 for php
So based on those numbers there should be more results for anything on PHP.
"You need a different mindset. It's a lot more like designing locks--for prisons full of inmates eager to get out."
Fortunately slashdot doesn't have that problem.
It's really easy to write a stored proc that builds dynamic sql and calls "EXEC" or "EXECUTE" etc on that statement.
e ction.ppt#369,93,Advanced%20SQL%20Injection
This powerpoint presentation is about the best I have read:
http://www.owasp.org/images/7/74/Advanced_SQL_Inj
Remember folks, you have to do more than parameterize your queries.
m.
I came accross this PDF a while ago, and though it was very informative, even providing examples of a few injection ways I hadn't thought before. Their White Papers section is overall pretty good, should be kept in your bookmarks for one of those slow news day.
Uncopyrightable: The longest word you can write without repeating a letter.
I for one welcome our new SQL-injecting script-kiddie overlords!
I like my coffee the way I like my women - roasted and ground up into little tiny pieces.
For PHP, there is an option in your php.ini file called "magic_quotes_gpc" and it should be turned on. That automatically assigns slashes to every single or double quote.
Is this enough to stop most SQL injection attacks? Can anyone give more input on this?
I did a quick google and found this as a description for sql injection. I would think that, at the very least, if you handle all your strings (and numbers) properly then this problem goes away. Say you have a field "LastName". If you just concatenate the value entered into the field into your SQL then you're asking for all kinds of problems (Any O'briens etc. out there?).
For all my fields I use a simple function to ensure that the data being put into the query is safe for the query (Replace(foobar, "'", "''") - for SQL Server). For numeric values, well, you just make sure that they are numerical as part of the validation (or you limit the characters they can type into a numeric field).
dnuof eruc rof aixelsid
Checking strange and unknown data should not be a "hassle" - it should be something that every programmer does without thinking, like breathing. If you are getting input that the user of the software has control over, you have to treat it like a spiky poison radioactive pirhana. This should be second nature to everyone - the fact that this vulernability exists so much shows how poor the state of software is these days.Programmers should have this sort of thing drilled into their brains as far as it can go.
Did you ever notice that *nix doesn't even cover Linux?
That's why I included the "sql php" and "sql perl" searches at the top. Searching for just "php" will include every page which is written in PHP!
Look again at my original post. There are double the amount of pages talking about SQL in PHP than talking about SQL in Perl. However, there are NINE times the pages talking about SQL injection vulnerabilities in PHP than those talking about SQL injection vulnerabilities in Perl.
- Stored procedure: a function that runs within the database server.
- Prepared/bound statement: something in code -- usually provided by the programming language's database layer -- that looks like the following:
Then you set item 1 to some value, item 2 to another, etc. Other variations exist as well:Here you can set values by name rather than by index. The implementation of this on the back end (where you should not be able to see it) may in fact be a stored procedure in databases that support it -- especially for SQL statements that are run repeatedly. However, even if the database doesn't support stored procedures, binding variables will always work since the issue is handled completely in code.And then of course there are folks who don't want SQL anywhere near their code. That's when you may opt for an object-relational mapping library and/or stored procedures within a database.
Bottom line: escaping each time on your own is error-prone. Better to solve the problem right the first time. And it's easier than manually escaping/validating as well!
- I don't need to go outside, my CRT tan'll do me just fine.
The API is the language. Claiming otherwise is silly semantic games with no connection to the reality of the situation
I won't argue that most PHP programs I've seen are utter crap. But in software, semantics isn't a game. It's engineering. If you don't have words for distinctions, you don't have tools for fixing situations like this.
There are language oriented things that could be done in PHP to improve this situation, but short of incorporating the offending APIs into the language (e.g. so that SQL had to be compiled before interpretation), the simplest thing is to drop the offending APIs. It would break nearly every program written in PHP, but in a trivial way. And all those programs are broken anyway.
Post may contain irony: discontinue use if experiencing mood swings, nausea or elevated blood pressure.
This is basic stuff that people learn 2 weeks into their first database driven website. Anybody who paid good money for a site that is susceptable to input validation flaws should be looking for a refund.
It amazes me that there are banks out there don't do code reviews and pen-test to prevent simplistic attacks like this prior to rolling something into production?
God lord!
We require 3 layers of data validation (as part of the web interface, as part of the middle-ware layer, and within the database as triggered stored procedures for updates and inserts.)
Not doing this SHOULD be criminal in my mind.
Sure you can use stored procedures. And sooner or later you might regret it:
- Your company merges with another company using a different DBMS and you're told the infrastructures should be merged.
- You business grows. While you can always add new application servers, J2EEs etc pretty easily, you'll have a hard time upgrading your DBMS over a certain point - and it's going to be more costly.
- Maybe something is twice as fast on the database compared to the application server. However, you will always have 1 database for all your application servers. So where will the bottleneck be? I'd rather have the operation take twice as long for each request - on each of my half dozend app-servers - than have it run twice as fast on my single database that's slowing down to a grinding halt while the app-servers are idling away. Bye bye minimum response time.
I had a friend that was convinced her web front end to a database centric application was bullet proof. The user interface was accessed by clicking on a java script link which controlled the browser behavior. It brought up a browser window without toolbars. In the browser window all of the options were choosen via select boxes. Nothing new was added by the user through the application. She started to brag about the amount of code she didn't have to write to filter user input.
I started a tcpdump -xX port 80 and host her.host Because everything was being passed plain text we could see everything in the uri. After a quick nmap -vv -sV -P0 her.host I connected via telnet her.host 80 After the required http 1.1 hello stuff I started submiting commands to her cgi script; alpha characters instead of numeric, big decimal numbers, negative values... It didn't take long for her to decide to rewrite it.
Having to work for a living is the root of all evil.
1) stop writing
2) stop writing code NOW
3) get a book from a reputable distributor like Wrox or O'Reilly
4) understand how to write code properly. Note my emphasis of the word "understand". This is more than simply hacking code together.
5) PROFIT!!! (ok, couldn't resist that one)
I am not a
--
Why yes, I am a genius!
blah blah blah
Everywhere I go to look about PHP security, I see mysql_real_escape_string() as a panacea. But I don't use MySQL, I use Oracle and PostgreSQL. So, mysql_real_escape_string() is not a fix-all for all php programers.
A few years ago (circa 2002 - php v4.x) , I did a rapid application in PHP4 for a demo. It was never really meant to be deployed but was just to give an idea to our managers about what we could do with our data. The backend was Oracle and I used the OCI8 API with no abstraction and it was strictly procedural. Now, several years latter, I've decided to make it deployable in php 5 and PEAR::DB. (As an aside, try reading your own spagetti code several years latter, luckily). So I am busy rewritting the thing by encapsulating some of the logic in PHP5 classes and thinking about security (which was not a part of the orgininal demo). I've scoured the web and O'Reilly safari for sources on php security. From what I've gleaned from various sources, it fighting SQL injection basically seems to come down to the following:
I've checked out some of the validation classes such as pear::validate but I haven't found anything that really meets my needs. There are thousands of classes to validate email addresses, but fewer for specialized things like a National Motor Freight Conference Commodity, so I tend to fall back on writting my own functions with regex and ctypes and strlen.
...with the user inputs passed as input parameters.
While it was an interesting read, the referenced articles did not present any earth shaking 'new' information other than overall numbers so...
...and that both of these are necessarily a good thing? ;)
Is it me or is the referenced article just an advertisement for how well they can tweak Network Intrusion Prevention Systems (N.I.P.S.?), or increase how tightly secured Host Intrusion Prevention Systems (H.I.P.S.) are?.
Not that 'techies' are in any way interested in that stuff...
Comment removed based on user account deletion
Seriously, if I had mod points today, I would have simply modded every post of yours down today,
I never get mod points anymore, but if ever there was a case for bitchslapping someone it's this. I've been mod-bombed before and its dumb because it usually does not have permanent effects and when it does "who cares?". Basically, modbombers waste the mod points they've been giving.
Check the IP address and strip this user now.
It has always amazed me that people programmaticly build SQL queries using strings of concrete syntax! What the hell? Leverage your type system! It's there for a reason! Build an abstract syntax tree, and then let some library take care of communicating it to the database. Look, Mommy! No injections! (And it's not by "being careful".)
Good insights. I remember my jaw hitting the floor when I picked up an actual book on C++ and not learning from Joe Script Kiddie website #90210. Funny how sites never tell you about important stuff like implicit copy constructor invocation which, by the way, seriously tears up jack if you're dynamically allocating memory.
The difference in books vs. websites is night-and-day, most sites assume a certain level of proficiency. Books teach things, well, by the book. From the beginning.
Also, it's not hard to find PDF versions of very good SQL books online.
- For every action, there is an equal and opposite criticism.
It's not C's job to protect you from using strcpy(buffer_on_stack, untrusted_input), and it's not PHP, Perl, MySQL, or your database layer's job to protect you from "SELECT * FROM table WHERE name = " . $name. You're a programmer. Do your job. If you don't know what something does, don't do it.
I mod down pyramid schemes in sigs.
But in Classic Visual Basic ASP, other than HTMLEncode() and custom string parsing, what other methods are there to protect your data from SQL Injection Attacks?
Hey /.,
I'm a tester, and we check all of our applications for SQL Injection as a matter of course. I've written an in-house crawler/injector that does a blind attack against a site (no, I will not give it to you, script kiddies). This is OK, but I would prefer an open source / free tool of some kind that is a bit less "user unfriendly" and a bit better maintained.
Does anyone know of one?
Alf
In Soviet Russia, sig types you!
PHP's mysqli extension supports paramaterized SQL, but it is still not in wide use. The majority of web servers still don't even have mysqli installed, and most programmers stick with the old extension out of habit anyway. Not to mention the huge base of code already written that's being exploited every day.
Even in mysqli, the process is not very elegant. I work in PHP but the first thing I ever did in the language was write a database framework that works similarly to DBI (as implemented in Perl), I would totally hate PHP if I didn't have it.
The PHP devs also decided to create the craptacular "magic quotes" feature, which I'm sure seemed to be a good idea at the time, but in retrospect stalled real web security awareness for years. So yeah, PHP is a big culprit here.
These are all good points. Add in the mess your code becomes when, rather than using good OOAD, you instead do everything in proceedural code (even Java stored procs affect a proceedural style).
Neat separation of layers for UI, Business and Data Access is pretty much manditory for any large scale application - anything else and you are creating unmaintainable, unreusable, spagetti that will not work well in an SOA. Stored Procs won't get you there.
Learn to bind your variables or use Hibernate or use any one of a zillion other techniques besides using stored procs. Don't use them for anything except simple CRUD operations.
In fact, Perl's DBI is not only fast, but when used properly (variable substitutions, binding variables, etc) it works extremely well. Also the fact that everytime you change your data source (CSV, XLS, MySQL, SQLite, MSSQL Server, Oracle, PostGres, etc) all your functions don't change. You can always count on:
If you're not doing some kind of column binding or type-casting on your form-derived query arguments, you are always leaving yourself open to sql injection.
While I agree PEAR is a good way to prevent such attacks, your statement "PHP supports parameterized SQL just as well as any other language I've worked with" is a bit misleading. PEAR is not part of PHP, it's a class library that runs on top of the PHP framework. As such, the mysql interface class (The one that supports PHP 3.x), does NOT have parameterized queries at all.
That is not FUD, it's the truth, and yes, there are workarounds, and fixes, but that's still a big hole unless you use the magic_quotes_runtime, which causes it's own issues.
For all your anti-script kiddie needs! Just don't EVER type the words "insert" and "select" in your forum post. Or "insert" and "into". Or "update" and "set".
/.'s mod_security rules. :P
True story. Took me hours to figure out why people were complaining about missing posts.
Wow I hope this gets through
software techniques prevents this from happening.
Any "webmaster" that creats a page that allows SQL injection should be terminated on the spot.
The Kruger Dunning explains most post on
one would assume 'carefull' means researching what you are doing, and then implementing it. AS opposed to gently pressing on the keys trying to avoind repetitive stress injury.
The Kruger Dunning explains most post on
Misinformation does not equal FUD.
The Kruger Dunning explains most post on
Enough said. Jon
While it's no cover for good app design, I don't worry to much about this attack after implementing a Web App firewall from Teros/Citrix. :)
And I know several banks in town have too.
I think misinformation that causes people to believe that using a particular type of system will make it harder to have a secure system is FUD: it will instill fear, create uncertainty and cause doubt. Whether it was intended to do so or not, I don't know. Given the anonymous nature of the original poster, I'm not inclined to give him the benefit of the doubt.
I hate these topics on slashdot. Typically Im a lurker, hence no account. But i have to say, that it amuses me how each one of you has "The Best Solution"(TM). There are many ways to do something, and not all of them are bad. I will only agree that consideration for injection attacks should be taken when writing code, but clamouring on about whats the best method just proves to me that the developers on slashdot are ego maniacs and can usually be proven wrong by someone else.
And if you were using PostgreSQL, you'd probably use pg_(send_)query_params() instead...
PEAR is not part of PHP, it's a class library that runs on top of the PHP framework.
./configure --without-pear. You might as well argue that C++ doesn't support parameterized queries, cause, you know, ODBC et al aren't part of the core language. Or C doesn't, because the API library that's supplied with MySQL doesn't. Besides: if you're running any database other than MySQL, you get parameterized queries in the standard library. The reason for this is because the standard library consists mostly of direct conversions of vendor-provided APIs to the nearest possible PHP equivalent. The MySQL C API doesn't support the feature, so the MySQL PHP API doesn't. The Oracle one does. The Postgres one does. The Sybase one does. And so on.
PEAR is distributed with PHP, and is installed along with it unless you specifically run
The fact is that there is a well known, commonly-used, officially sanctioned solution to this. The fact that it's an object oriented solution implemented in PHP rather than a procedural one implemented in C like all the stuff in the standard library doesn't matter.
As such, the mysql interface class (The one that supports PHP 3.x)
PHP 4 was released over six years ago. PHP 3 was the current version for only two years prior to that. Support for PHP 3 is no longer available; security fixes are no longer applied to it by the PHP developers, who haven't been accepting new bug reports for that version for over a year now. Using it would probably be suicidal, as it included a large number of design decisions that are now widely believed to lead to insecure applications in many situations. Why is compatibility with PHP 3 such an issue?
From the article:
..." Including a link to SecureWorks.
"SecureWorks announced
A Network Intrusion Prevention System and Host Intrusion Prevention System can offer many of these protections, especially if they are being monitored by a 24x7x365 security team that can stay on top of the newest types of SQL Injection attacks, as there are new variances being released all the time."
Interesting that this is SecureWorks business - doing 24/7 monitoring. So, you can skip fixing your apps so long as you hire SecureWorks, is basically what the last paragraph is saying.
Sometimes its not feasible to shut down an application because its vulnerable to spam or sql injection. The Apache mod_security module can provide a stopgap until you can fix the app. Probably a good idea to have it in place in any case.
It is completely wrong. The database bindings for a language should do this for you. Just because PHP is garbage and makes you manually *_escape_string() everything, doesn't mean that's ok. Decent languages let you pass params and have them auto-escaped.
It is also hard to believe that XSS vulnerabilities are so frequent, even google had a couple of them (solved the same day they were announced though)
Copyright infringement is "piracy" in the same way DRM is "consumer rape"
Hmm did some research on this and turns out PHP 6 is doing away with gpc_magic_quotes() so you should switch to mysqli_* instead of mysql_* it was introduced in PHP 5 and requires mysql 4.1 or better. Kinda sucks I'll have to redo all my database code but escape quotes wasn't cross database compatible anyway since postgres apparently uses a single quote instead of a backslash to escape.
Don't put words in my mouth. I never said you should use/not use PHP, or Perl for that matter.
What I DID say, however, is that anyone who disparages Perl, while at the same time using PHP, doesn't have any idea what they're talking about.
It has NOTHING to do with elitism, and everything to do with using tools properly. Most PHP devs don't know what they're doing, but that doesn't mean there aren't competent devs using PHP too.
Sticking feathers up your butt does not make you a chicken - Tyler Durden
For all my fields I use a simple function to ensure that the data being put into the query is safe for the query (Replace(foobar, "'", "''") - for SQL Server).
And what about this input?:
foo\'; delete from user;--
which in query
SELECT id FROM user WHERE name='$input'
your function turn into:
SELECT id FROM user WHERE name='foo\''; delete from user; --'
Do you sleep well now?
since I speed-misread the title as "SQL injunction attacks".
I sleep very well. That query doesn't do anything - Unless I have a user who's name is 'foo\''; delete from user; --'
Try typing the query into Query Analyser and see what it does (like I said - nothing).
Maybe this'd work on Oracle or mySQL but on SQL Server (as I said in my original post) it's perfectly safe. If you're using a database that allows you to interupt a string like that then you should change you're database. I suspect, though that the correct output for your example would have been:
select id from user WHERE name='foo\\'; delete from users; --'
And the function you would be using on your database would be:
REPLACE(foobar, ''', '\'')
ie. Your escape sequence is different to the SQL Server escape sequence.
dnuof eruc rof aixelsid
With the help of a whiteboard (!) I explained to about half a dozen ( okay, mostly junior ) developers and -- here's the real kicker for me -- *the three most senior members of out QA department, including the department head* that you could use the password
' or 1 = 1 --
for many, many sites on the Internet, regardless of user name.
The whiteboard came in when I had to explain *why it worked*...
_shakes head_
remember the wisdom of Mahatma Gandhi: If enough peasants die horribly, someone will probably notice
.. because avoiding SQL injection is relatively easy to do.
1. Use only prepared statements or stored procedures (Note even without concerned of SQL injection this is a good idea).
2. If you use stored procedures do not use any of the passed in values to generate dynamic SQL (otherwise you have just moved the problem from the app to the database).
meh
and with products like Catalyst and Jifty getting even easier and flexibler.
"...we should just trust our president in every decision that he makes and we should just support that." B.Spears 2003
yes.. never trust the data. and know all the data that needs to be validated. form fields, cookies, referer, useragent, and one I _bet_ web developers are ignoring - Accept-Language (in IE - Tools > Options > Languages > Add.. > type whatever you want).
if you are using any of these to build up some dynamic SQL - VALIDATE YOUR INPUT! or as other posters have mentioned don't use dynamic SQL, use Stored Procedures and Parameterized Queries...
My bad, I meant MySQL 3.x not PHP 3.x. A lot of web hosting providers STILL haven't moved to MySQL 4.x yet.
A large number of hosting providers also don't give you access to PEAR either. If you want it, you have to go and get it yourself. As for C and C++ supporting parameterized queries, that's a different argument. Neither of those are really a web framework, and neither of those include database support at all in the core. However, on the windows platform, ODBC is the standard and most accessable way of accessing databases from those languages, and as such is what is most commonly used, and most likely the way a beginner would use. In addition, many (All 2 of the ones I've worked on) projects out there don't use PEAR, and they have their own database abstraction layer, which is something the other frameworks don't need. Most of the big frameworks have a default database implementation that abstracts atleast some of the differences between different database backends, or atleast implement APIs that are similiar (although maybe different classes) for different backends, which PHP doesn't.
The most common scenario for PHP with a database is accessing MySQL 3.x, and on a shared hosting provider. And in that scenario, PHP does not allow parameterized queries. Yes, you can use someone's database abstraction layer to emulate that functionality for you, but then again the same thing could be said about ANY language. It's a workaround to add a feature that other web frameworks don't suffer from.
ASP.NET supports parameterized queries to SQL Server, which is it's most common database backend (It also supports it for MySQL including 3.x versions, Oracle, and any ADO/ODBC database).
I do believe java has support natively as well.
To be quite honest, I would love to see the baseline PEAR packages moved over to the PHP core. But even that won't solve the problem today in trying to help beginners not make insecure web applications. And you can still circumvent the parameterized query API calls by doing string concatenation for your queries, but that's a different subject.
For those too lazy to read the article, here's what you gotta do to secure your sql:
Principle: Never trust user input
Implementation Validate all textbox entries using validation controls, regular expressions, code, and so on
Principle: Never use dynamic SQL
Implementation: Use parameterized SQL or stored procedures
Principle: Never connect to a database using an admin-level account
Implementation: Use a limited access account to connect to the database
Principle: Don't store secrets in plain text
Implementation: Encrypt or hash passwords and other sensitive data; you should also encrypt connection strings
Principle: Exceptions should divulge minimal information
Implementation: Don't reveal too much information in error messages; display minimal information in the event of unhandled error; set debug to false
I thought there'd be some crazy-mad stuff you'd need to do to protect against SQL injection but it seems that decent programming techniques and the application of sanity is all that's required, panic over then?
http://msdn.microsoft.com/library/default.asp?url