PHP and SQL Security
An anonymous reader writes "PHP and SQL
Security are being proven more weak every day. Uberhacker.Com is running a PHP
and SQL security research
project to raise awareness of secure scripting. The site hosts guides
to secure PHP programming, forums, and scripting
challenges to see who can create the most secure scripts."
Looks more like "Scripts people write using PHP and SQL without understanding security issues are being proven more weak every day." to me.
PHP and MySQL are not weak; faux programmers are weak. Purification of incoming data is essential, and often ignored by novice script-writers, and that's the problem. SQL injections are common among novice coders, and they can slip past even competent coders, but a strict design engine for passing SQL vars using $_REQUEST, and turning off register_globals, will result in better results.
Essentially, the problem is with those making insecure scripts, not the whole PHP and SQL system.
The dangers of knowledge trigger emotional distress in human beings.
I think a lot of the blame for this can be traced to the ease of getting started with PHP/MySQL. Result: more people learning how to program with php will of course result in less thought about security. Add the ability to have input arguments via the http request be automagically available to the running code shares a lot of the blame too. Put them togeather and thats a disaster.
How about "weaker" :P
The Army reading list
This one is pretty secure...
// Try to break into this script!
<?php
echo "Hello World!";
?>
The problem with socialism is that they always run out of other people's money. - Margaret Thatcher
You could also enable magic_quotes in your php.ini. However, if you\'re too dumb to know the basics of sql, chances are your program won\'t work quite right.
uses MS Comic font for their articles. Sorry.
Your scripts are only as secured as you make them. What this "UBERHACK" website is simply doing is sending a flock of young script junkies out to locate sites which have not implemented a good code structure.
/cgi-bin/ do you feel more secure by doing so? The ScriptAlias which you most probably have set for this directory will in no way prevent malicious intent from remote connections if your php is not properly configured for base_directories, register_globals, and safe_mode.
a b
PHP documentation clearly states the pitfalls of using variables in a global scope. It is for this reason that PHP changed its GLOBAL array structure to read $_POST and $_GET methods, as well as default setting register_globals to off.
I find it a poor use of a developers time to attempt to see whose site they can deface. It is imoral and shows a lack of respect for those whom put countless hours into their site development.
I would challenge "UBERHACKER" to spend more time developing their website which is showing to be in poor syntatical use of HTML, slow loading and poor in URL design. Why run a php scritp in a
http://uberhacker.com/cgi-bin/index.php?page=fl
Pick up any book on programming and learn proper developmental tactics ( Throw / Catch ) before promoting the attack of others because your 'Uber' site thinks it can't be Hax0r3d.
End Rant.
My Thoughts, Kyndig
There is no trully unsecure language, only programmers that practice building unsecure sites. Bugs and security holes can always be patched, but if the site is crap to begin with, then that's just asking for trouble. You should always check user input, esp if you plan to use said input as part of a SQL query or entry. Duh.
Sometimes I doubt your commitment to Sparkle Motion.
I am often amazed that more people aren't working towards programatic ways to express SQL queries and/or regular expressions
They're called stored procedures. They've existed for at least 20 years.
Writing al=execute_query("SELECT access_level FROM user WHERE user=? AND password=?", user, password) is naturally so much more secure than al=execute_query("SELECT access_level FROM user WHERE user='"+user+"' AND password='"+password+"'");
Nowadays, most database products worth their salt (Oracle, Postgresql, and even my Mysql!) support bind variables. And even if you have an old version of Mysql (which doesn't support them), Perl DBI and Php PEAR can emulate bind variables for you.
Of course, if you're stuck with ASP and Sequel Sewer, you're somewhat out of luck, and need to do the proper quote escaping yourself.
When will /. stop posting misinformation?
SQL is a language, defined by ISO. MySQL is not SQL-compliant. Not even Oracle is. IBM DB2, PostgreSQL are SQL compliant, and a lot better than MySQL too. PostgreSQL is even faster and simpler.
Leandro Guimarães Faria Corcete DUTRA
DA, DBA, SysAdmin, Data Modeller
GNU Project, Debian GNU/Lin
Other than the scripting challenge, what's on this site? I've read the guides to hacking, but it's all a bunch of kindergarden material. Seems if you follow the guides you'll certainly have insecure PHP scripts with all kinds of SQL injection. How about posting some real articles on secure PHP scripting...
Or would you blame the workman who cuts off his arm with the buzz saw's totally unprotected blade?
Yes, I would: he was obviously doing something with the saw that was inappropriate; what saw-oriented task [when done correctly] involves waving it at one's own arm?* The fact that the blade was unprotected is irrelevant since he should have known it was unprotected and therefore dangerous. All tools can be used stupidly, and oddly enough the results really can be the fault of the operator. It is also possible for fault to lie in more than one area.
Yes, I know the traditional definition of 'hacking' includes making $ITEM do something it was not intended to do, but there are limits.
* I'm guessing that 'buzz-saw' == 'circular saw'.
I want to drag this out as long as possible. Bring me my protractor.
Maybe someone can write a PHP script to take care of the 404 error that occurs when you click on the "home" link on Uberhacker.com.
Bad Design Überalles.
People! Remember the quotes! Do:
delete from table where id = '$var'
Not:
delete from table where id = $var
Try for $var = "10 and id = 11 and id = 12 ...".
zWhat would an EWOULDBLOCK block, if an EWOULDBLOCK could block would? -- me
AFAIK SQL injection can be prevented by binding the parameters to the SQL statement and not putting them within SQL.
...) using bind_param.
Why is this? Performance? Keeping the code short and simple?
An example:
It's easy to inject some malicious SQL when using the following PHP code:
mysql_query("INSERT INTO FOO('Bar') VALUES('$some_post_param');");
But if you prepare the SQL statement with parameters and bind the variable $some_post_param to the statement, it will be secure.
see mysql manual for mysqli_stmt_bind_param() aka bind_param
$stmt = $mysqli->prepare("INSERT INTO CountryLanguage VALUES (?, ?, ?, ?)"); $stmt->bind_param('sssd', $code, $language, $official, $percent);
I know this concept from Perl DBI, but in PHP I haven't seen anyone (phpBB,
As for general webserver security: use PHP and perl as cgi, use suEXEC, run the webserver as nobody/www, put the users into chroot jails, but by all means, don't use PHP safe_mode On.
It is an economic fact of life. People will always be learning in the job. We will never have a guaranteed level of expertise, let alone competence. Tools will have to start enforcing security. Humble coders have been dealing in overflows, SQL injection, and cross-site scripting forever. Tools that manage buffer/stack overflows are not just for junior programmers. Tools/frameworks that add taint checking and build-in automagic security (like ASP.Net's validaterequest). If we have to rely on all the programmers becoming competent experts we will never have security.
Yes, that guide to secure scripting was very useful - a "hello world" program. Whoopee. To be frank, that site looked... well, less than professional, and with a name like "uberhacker" I expected their tips to be a little more advanced than "look, you can change the values in a query string but don't tell anyone!!!!11"
That being said, I used to write a lot of PHP (I rarely do it anymore at work, but I still try to keep up with the language) and when I first started out I would have loved a comprehensive and easy-to-understand guide to common security holes. The world needs a simple "how to write security-conscious code" for beginners! The sooner you get to see stuff like SQL injection or XSS in action, the better.
and turning off register_globals, will result in better results.
One of the problems is that PHP has kept changing the way it handles session variables such that if you move your site you may encounter problems (it takes some sites a while to upgrade their PHP interpreter). One solution is to make your own set of session var functions (scalar only) to wrap the changes or per-site differences, or simply live with register_globals on.
Maybe in a few years it will settle down, but the recent changes have gummed things up for the near future. Every language has had some stupid progressions, and session handling is high on PHP's Stupid List.
Table-ized A.I.
- David A. Wheeler (see my Secure Programming HOWTO)
> If you're going to make that argument (which, BTW, I think is accurate), then you'd better be prepared to say that Windows isn't inherantly insecure as well.
No, not really. If you're arguing that Windows isn't insecure (which is slightly off-topic) I would have to disagree. The security flaws in Windows are due to over-complication of a proprietary system, leading to gaping holes that keep springing up on a systemic level; these holes are compounded by closed source, financial rationale (lacking in motivation for corrections) and corporate belligerence on a systemic level. Fewer eyes have seen Windows source code than PHP source code, and those that have are swimming from confusing and conflicting design models.
Windows is insecure because the people involved are xenophobic. Plus PHP isn't an operating system, so we're really talking about penguins, apples and windows.
The dangers of knowledge trigger emotional distress in human beings.
Think it was just a "look at my cool site, try to slashdot that one!" kindof 'article'.
So far the most "unsafe" aspect with PHP / SQL setups is poor input validation;
If you allow direct writing to your SQL and don't do sufficient checks on the input, well.. you'll get in probs with that.
Proof of concept;
Hello.. enter your email for free porn: sucker@hotmail.com '; DROP TABLE 'emails';
Or you have those pages who mess up or display info which can be abused (and / or shouldn't be on that particular page) after there's a "<blockquote>" injected and redisplayed without checking..
Same with <input type=text>
Then.. there's JS, and htmlentities, and, and..
All caffeine intense, and headache inducing subjects you should keep in mind if you plan on bringing something on wire.
"Nah.. you don't have to do that.. Who's going to know how to do that?"
"Trust me.. You want me to put in that extra code.."
"If you really say so.."
You also have stupid defaults, and uninspired coding which gets abused, ofcourse...
I actually like the PHP / SQL combination and believe it to be safe enough for what I do with it.
I think we can keep recursing like this until someone returns 1
This is not an issue dealing with PHP and MySQL, this is an issue with weak programmers writing bad code, and I'm sorry to say, you find it in every language. As a regular in #php on freenode, we are constantly correcting bad coding practices.
In fact, it's not uncommon to find people using GET and POST variables straight out of the box without any kind of validation whatsoever. Many people do not learn the de-facto first rule of web programming: the user can not, and should never be trusted.
To make matters worse, applications like PHP-Nuke spring up which are notorious for sloppy coding practices, and people tend to see them as reflect on the PHP community as a whole. That's like blaming the C language because someone, one day, wrote some bad code in it that got someone else hacked. This happens all the time, but we don't make claims like "C security is weak". Instead, we worry about the truth of it, that the programmer in question did a bad job, or just flat out missed something.
One of the key points that seems to trip most novices up (and granted, this is one of the stupider moves presented by the PHP Core Development team) was a thing called magic_quotes_gpc, which attempts to auto-escape incoming GET, POST and COOKIE variables in an attempt to sanitize user input. This is usually a double-edge sword because newbies are typicly not aware if it is, or isn't on. In later versions, this is on by default, and does prevent many SQL injections from occuring. However, for the more experienced user, having your input auto-munged can be something of a pain. Unfortunatly, to write truely portable code one must test this value and normalize data accordingly.
The issues don't stop there though. I've seen many a more serious faux pas committed by the newbie. Another more serious flaw that I see happen on a regular basis is the use of user data within include statements without proper path checking. This is probably one of the more disasterous errors I see occuring because it typicly exposes sensitive data. There has been more than one occasion where i've shown a user their own passwd file in a browser to make my point.
Anyhow, to the newbies: we, the more experienced people of PHP are on our own quest to educate people, many times in a one-on-one basis on Freenode. If you're not sure about a particular issue, grab an IRC client and ASK US (irc://irc.freenode.net). We're there to help!
BeauHD. Worst editor since kdawson.
Sh!t PHP coding is as old as the hills.
.inc file under htdocs!
... not so much as an HTTP_AUTH to secure it with and would handily chmod 777 all uploaded files and put them under htdocs for ease in execution.
Some of my favorite things I see _ALL_ the time:
Something bad happens while executing the code?
Let's <? die("here's my database connection info in case you wanted it"); ?>
Then there was the client who's previous developer was some moron who stored the database connection info into a
The web "design" group who's MySQL database was wide open without authorizing with a password.
The arsehole developers who built themselves little backdoor webpages during development to exec shell commands and upload/exec files
I've seen about 3 websites store credit card numbers unencrypted into a MySQL database.
I could go on and on and on, being a development gun for hire since 98, I've seen some things that defy all logic and explanation. In fact, I still wonder why they call it Computer Science. Now, Computational Arts I could buy into.
Anyone have suggestions for a bit more uh, quality sites on the topics? Seen plenty of coding sites, but none particular to security of this combo.
PHP hasn't executed more than one query per mysql_query() for quite some time. Your exploit example might have worked a few years ago, but not for some time.
PHP/MySQL is not really that unsecure. If you don't do stupid things, you won't (generally) get hacked.
In the law there is no overlap between theft and copyright infringement whatsoever.
Why worry about security when your site's been slashdotted? No one can get to it so no one can hack it!!!
So I think a new approach is needed. One where you don't mix instructions and data so easily, or flag them more readily.
With SQL, this has been around for a while: bind variables. Your SQL queries tend to be static with ? thrown in (or :foo for named bind variables). In Perl, it looks like:
Not everyone is using bind variables, and I don't know why. One reason may be that positional bind variables can be confusing: they require you to correlate two lists in your head to position the correct variables in the correct spots. Not all language/database combos support named bind variables. (JDBC doesn't!) But they can be emulated - that's one reason I made xmldb.
For HTML, it's more rare to find something that does this. Apache Cocoon does, but it's grotesquely complex. I'm working on a simpler system, though it's not ready for production. Here's the idea: my files (XFP) are to a SAX ContentHandler as JSP is to a byte stream.
I like SAX because it's a way of making XML that does things right. Instead of doing something like:
you write something like:it's nice in that you don't do any of the escaping yourself - you just tell it how you're using each string, so it can do the escaping right. But that's six ugly lines instead of one, and it's worse with real SAX because you need extra arguments for namespaces and things. So I looked at JSP. It sticks Java code inside the text to produce. I stick Java code inside the XML to produce. I write something like this:...and it turns it into the code above when it makes aMy code is all Java. But the concepts should apply to PHP, Perl, Python, anything.
Anyone else working on a system to solve this problem? I'd be interested to share ideas.
Interesting topic, but I don't think the problem lies with PHP or MySQL. You can create insecure apps in any development environment. Yes, some are more problem-prone than others, but I'd rank Perl much higher than PHP/MySQL in terms of being conducive to allowing vulnerabilities.
I attribute much of this problem to something I call "fuzzy developing". It's the latest trend. The crux of this problem involves Web designers, who know very little about programming who are deploying more and more complicated applications in a cut-and-paste manner. These fuzzy developers have no concept of proper programming skills. Many of them can't program at all, but they can snarf someone else's "free" code online, change a few config parameters, whine to an admin for access, and compromise entire servers.
This new breed of developer relies on existing code, following the fallacy that if it's on the net, it must work. They use sites like experts-exchange to get other people to code for them when they get in a snag, and don't contemplate the priorities involved when you put something on a public system.
PHP and SQL Security are being proven more weak every day.
:)
Where does this guy get his facts? Tell me, what exactly is insecure about SQL or PHP? If you know what you're doing and write your scripts to prevent any SQL injections and you set adequite permissions on the database, you're not going to have any problems (assuming there isn't some huge flaw in the database server, itself).
By the way, I don't trust anyone who puts up a research project in Comic font. What is this guy, a 12 year old boy, or a 60 year old grandma? Either way, it's ugly and a Windows-specific font and I don't trust one word this llama says.
One more rant - he doesn't talk about SQL in general, he talks about MySQL. There is a difference.
(OK, I'll stop being a troll now
> Security does not belong in the database because it removes context of action.
aha
Well, rather than debate whether or not the data should be persisted in the context of its rules and actions (which doesn't work in reporting, btw), lets get down to what simply works.
You need to plan on including security awareness within each layer and component of your architecture. Since we've moved beyond client-server we seldom now authenticate & authorize individual users in the database. That's fine, but locking down the data should still be done in any database, even if the granularity is now at the application level rather than the individual.
The difference between today and ten years ago is that we're now mostly implementing database security at the application level of granularity.
Here's a trivial example:
- 20 users are in ldap group finance
- all are also in ldap group report
- 10 are also in ldap group invoice
- 4 userids are used by the database:
- userid invoice has ownership privs on invoice schema
- userid gl has ownership privs on general ledger schema
- userid fa has ownership privs on fixed-asset schema
- userid report has read privs on above schemas
- The invoice application will authenticate users via ldap service
- The invoice application will use ldap service to authorize users using either report or invoice group depending on what the user attempts to do
- The application(s) will connect to the database using either appropriate database userid. This will be used by database to ensure that invoice application does not attempt to write to general-ledger schema, etc.
This isn't the end of your security concerns in the database. You've also got to lock down all your file systems, ensure that no users can create new database objects, etc, etc. That's also fairly straight-forward.
Anyhow, don't get all hung up about where security must go - or in the interests of some kind of misguided purity you'll end up leaving giant gaping holes in your defenses. Implementing security at the application level of granularity is both simple and effective. Take advantage of it.
Being a low-level programmer, and specifically working on advanced CGI, awhile back I bowed to pressure to offer some of my web clients scripting abilities on their servers. I went with PHP/MySQL and started the process of learning about the language and its caveats.
.htaccess restrictions in code lib directories and careful consideration over other virtualhosts that might have php disabled in a higher-level directory.
The first thing that completely freaked me out was the register_globals setting in PHP. I invited a PHP programming friend to come hang out and give me a little intro-tutorial into how he developed so that I could understand where these guys were coming from when developing apps. He proceeded to show me this "neat feature" called register_globals that makes it super easy to access passed parameters from the outside world. Of course it also makes it super easy for anyone on the planet to overload internal variables that could be used just about anywhere in the scripts. I've never seen such a dangerous "feature" [in a non-Microsoft product].
And this all ties into the number one rule of programming. When you're coming from C/C++, 80% of your job involves data/input validation, so it's second nature to cover your ass. I found myself very confused at first over the dozens of different functions available to escape, unescape, tokenize and otherwise mangle input from/to various forms. No wonder developers are confused.
But above all, there are basic tenets that the server admin should enforce that have the most impact on security. First off, NOBODY should be enabling register_globals - it's just a crutch for crappy programmers IMO. Second, safe_mode is a must. If you have an app that needs safe_mode to be disabled, then you are better off isolating that app to its own private server. Third, every application should have its own private database work area. I am amazed at developers who run multiple applications in a single database space. Fourth, the configuration of the web server needs to be such that PHP code is properly protected, with
Safe_mode is a good tool. It also creates annoyances for the customers, especially those who are writing apps that create files in their work area... this requires the admin's intervention to set up the proper permissions (and gives them a chance to give the client code a once-over for glaring errors).
One thing I haven't quite figured out, and maybe I just need the proper Apache mod, but when a PHP app creates a file, it's owned by the web process and not the script user process, so in safe_mode, to get things working you either have to change permissions or give liberal directory permissions in order for things to work with user-uploaded code.
Ultimately, the server admin should bit the bullet and refuse to give users access to certain dangerous "features" such as register_globals or non-safe_mode. It's just too easy to open a Pandora's box.
>>Or would you blame the workman who cuts off his arm with the buzz saw's totally unprotected blade?
> Yes, I would: he was obviously doing something with the saw that was inappropriate
Yeah, that's pretty much the line of the discredited 19th century factory-owners. They all insisted that worker injureries were due to carelessness on the part of the worker. Then people began to noticed that eventually almost all workers became completely disabled. About that time folks began to realize that a tool that requires you to be perfect 100% of the time is a flawed tool. Or a self-mutilation device, you pick.
And the same arguement keeps resurfacing, btw. Not just among factory owners trying to preserve maximum profitability. But also amoung techies trying to defend crappy products:
- RTFM
- can't get a printer to work with cups? must be a newbie
blah, blah, blah
Then in the late 90s Usability and Information Architecture really took off. These guys saw a a few patterns:
- the jack-assed argument that difficulty with a tool was the user's fault - resulted in lost users, lost sales, lost revenue. Those who insisted on blaming the workman rather than the tool - thankfully went out of business.
- usability challenges also caused security vulnerabilities - when users couldn't figure out how to secure a device it became a liability to everyone. So, in this case the tool harmed the entire community not just one workman.
The only interesting thing in the above comment is that you actually got modded-up for repeating a completely discredited notion. Sigh, probably just a clever troll and I fell for it...
to maintain consistancy, you can also use {} when interpolating complex variable types.
ex: echo "blah blah {$array['key']} blah blah";
it's bad to use $array[key]; outside of interpolation though, because PHP will first look for a constant called 'key' before it decides you're using a string. if you have a defined constant named 'key' it will use that first, which may not be desierable.
BeauHD. Worst editor since kdawson.