PHP and SQL Security 305
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."
Re:A bad workman blames his tools (Score:3, Informative)
Yes, of course. A good workman would never willingly use such a dangerous tool!
That being said, as far as SQL security goes, PHP fares far better than its competitor, ASP.
Indeed, by default, PHP comes with gpc_magic_quotes enabled, which prevents the more obvious SQL injection attacks. Of course, nothing is 100% foolproof, but we're nowhere near the sieve that ASP+Sequel Sewer is.
Blame should be shared between coder and language (Score:2, Informative)
SQL is probably the most widespread example of this, closely followed by regular expressions in Perl. I am often amazed that more people aren't working towards programatic ways to express SQL queries and/or regular expressions (attempts exist for both, but rarely make much progress).
Guides to Secure Programming? (Score:5, Informative)
Re:magic_quotes (Score:1, Informative)
Once our novice gets more knowledgeable, he can convince his admin to remove gpc_magic_quotes setting from his VirtualHost, and use addslashes [php.net] , instead, which allows finer grained operation.
That way, Peter O'Neill can register with his true name in his Php app.
SQL Injection in PHP (Score:5, Informative)
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 [php.net]
$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.
Re:magic_quotes (Score:2, Informative)
That's why you can enable/disable this setting on a per virtual host or per directory base.
Leave it enabled from the numbnuts who come straight from the Windows world and can't be bothered about security, and disable it for the more experienced programmers.
<Directory "/home/site/numbnut">
php_flag magic_quotes_gpc on
</Directory>
<Directory "/home/site/leet_penguin_master">
php_flag magic_quotes_gpc off
</Directory>
Hoppity Hop (Score:3, Informative)
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.
Secure Programming HOWTO (Score:5, Informative)
Re:Guides to Secure Programming? (Score:5, Informative)
I have a few articles on my Web site that might be informative: http://shiflett.org/articles [shiflett.org]
I'm also writing a monthly PHP security column in php|architect [phparch.com], and these articles will be available for free six months after publication.
Lastly, I am writing PHP Security for O'Reilly, which is due out in the fall.
Re:SQL injection 101 ... (Score:3, Informative)
Re:No. (Score:4, Informative)
I've got a couple of rules I try to abide by - can anyone confirm if they're good programming practice? If they are, then they might prove useful to other people.
Re:SQL Injection in PHP (Score:3, Informative)
The reason is that the function you reference is only available in ext/mysqli [php.net], and this requires MySQL 4.1 or greater. There was previously no way to bind parameters like this using PHP and MySQL.
Also, phpBB is not a good example to use with regard to secure programming practices. It is one of the applications that give people this silly notion that the language is to blame for poor programming.
Re:No. (Score:5, Informative)
every thing that comes from the user needs to be scrubbed, bleached, hammered and then finally used when you know it is 100% safe. and it must be used in a safe manner.
what blows my mind is those that use the DB column name in a webform to be passed.. Oh nice. select from that drop down item_number and simply change it to start playing corrupt the database games.
Nothing that is ever given to the user, or recieved from the user should be trusted... EVER. that is the first rule and needs to be pounded into everyone in every book about any programming language for the first 5 chapters.
start there and you will heve very little security issues.
Re:Crap site (Score:1, Informative)
Re:No. (Score:5, Informative)
Good. You are off to the right start, but with better function programming, you will find yourself writing more feature code than purification code.
Things to look for:
Protects against SELECT SQL injection attacks.
> becomes >
< becomes <
$data = base64_encode(gzdeflate($data));
This will prevent the problems with escaping quotes and apostrophes for SQL, and it will kill any SQL injections in your data.
if($this) {perform action}... will limit your chances of having to cope with scipt injections because you are only testing for the existence of a condition, and not the value of the data.
> Always escape text which is going into an SQL query
/tmp/, because that narrows down hack attempts, making it all the more harder to compromise the system.
I prefer to write my own SQL text, based on input values. That way you are never using data submitted for the SQL query. The only time they would really submit values would be when they are sending in a username and password, but in that case, you should be extremely stringent in purification by only accepting alphanumeric usernames and passwords (ie: run the alphabet function above, but erase all non-alphanumeric chars from the $ALPHABET var).
> Use htmlspecialchars() on any text that's being output, to stop users putting rogue HTML
htmlspecialchars() doesn't always work. I prefer using the example above, by limiting the characters allowed and disallowing HTML in the form of post body/subject data. Converting everything to base64 will make it nearly impossible to script attack the database, too.
> Put database usernames, passwords, pathnames and other similarly important but site-specific data in a define()
I disagree, because I use the $_SESSION array instead, which can not be changed by a user if the session cookie is server-side. Sessions can be scooped by sniffers, but that can be managed by your host's security, to prevent it. Certainly change the locale for session data from
> Never include() or require() something that isn't a hard-coded string
To me, this isn't totally required if you have suitable purification, but that extra bit of paranoia is welcomed, because it shows true fear and that is acceptable in any kind of programming. That sort of humility is welcomed because it demonstrates a compassion for the task at hand.
> Be hugely care
This was modded up? (Score:3, Informative)
PHP/MySQL is not really that unsecure. If you don't do stupid things, you won't (generally) get hacked.
Re:A bad workman blames his tools (Score:4, Informative)
No, no, no, no, no!
magic_quotes_gpc is totally broken. For those unfamiliar, it escapes all HTTP GET and POST strings MySQL-style. But this is stupid. How you want your strings escaped (if you do at all!) depends on where you are sending them to, not where you are getting them from. Consider these things you might be doing with the strings:
PHP has a shiny red button that you never want to press. This is one of many reasons that I say PHP is a broken tool.
A new approach is needed (Score:4, Informative)
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 [slamb.org].
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 [slamb.org], though it's not ready for production. Here's the idea: my files (XFP) are to a SAX ContentHandler [sun.com] 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.
Re:Crap site (Score:2, Informative)
There is a good guide available not specifically for PHP, but general secure web developement. I'm not the author and don't know where to link to his site or the latest guide but here's a mirror of it.
Best Practices for Secure Web Development [mkaz.com] By Razvan Peteanu
From C to PHP & Admin Responsibilities (Score:4, Informative)
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.
Re:array[key] (Score:2, Informative)
Re:Bind variables (Score:3, Informative)
Bind variables permit databases to match a query with cached queries even if parameters are different. It will then be able to fetch the appropriate execution plan instead of making a new one for each similar request.
SafeSQL will certainly help (Score:1, Informative)
Re:array[key] (Score:2, Informative)
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.