http://news.netcraft.com/archives/2005/07/04/php_blogging_apps_vulnerable_to_xmlrpc_exploits.html
single quotes? whodathunkit?
I wouldn't be so inclined to say that all PHP users are dumb. There are a lot of PHP utilities out there that are very secure. PHPNuke is not one of them.
It's not a flaw in a PHP utility, it's a flaw in a PHP library that's fairly widely used. Furthermore, it's a really, really idiotic mistake that any decent programmer should have understood not to make.
Snarky!
It's so cute how he blames it on the programming language instead of the crap libraries and crap code that uses the crap libraries. Nothing wrong with the language (other than a bad case of the ugly stick)
The language was just following orders!
>>6 The guy who wrote it (a friend of mine) and his wife are both programmers and have many bad experiences with PHP. Now they are both very much fans of Python, and little else.
The bug was eval() being used inappropriately, but on a deeper level it had to do with the way that in php, string interpolation is done via the grammar of the language.
For the purposes of the example, I'll illustrate a non-stupid usage in PHP of string interpolation, SQL.
execute("UPDATE foo SET age = '$age' WHERE id = '$id'"); seems perfectly reasonable, except that in this instance, we have a situation where an attacker could 'inject' data into the sql query by crafting a string
?age=14',access_level='admin
Giving the attacker's user account admin access.
The solution is to use mysql_quote_string, making the code more verbose, i.e.
mysql_query("UPDATE foo SET age='".mysql_escape_string($age)."' WHERE id='$id'");
But this isn't right yet, there's a possibility that gpc_magic_quotes is on, in which case you have to remove those quotes before you do this, otherwise you\'ll get that nasty bug where \' quotes get a \\ infront of them when they\' retrieved from the database. (bash.org suffers this at the moment).
so:
if (get_magic_quotes_gpc())
$age = stripslashes($age);
mysql_query("UPDATE foo SET age='".mysql_escape_string($age)."' WHERE id='$id'");
But! that's wrong again. This can be attacked based on what combination of mysql character encoding is being used, so we have to change this again:
if (get_magic_quotes_gpc())
$age = stripslashes($age);
mysql_query("UPDATE foo SET age='".mysql_real_escape_string($age)."' WHERE id='$id'");
Okay, now that's all over, lets look at how a real language handles it. Instead of using string interpolation that requires the above series of backflips to escape each untrusted argument, and very_long_function_names and string concatenation to break the very feature that makes php string interpolation easy, this is how to do the same kind of thing in perl or python, two other scripting languages.
$db->execute("UPDATE foo SET age=? WHERE id=?", $age, $id);
and
db.execute("UPDATE foo SET age=%s WHERE id=%d", (age, id))
By doing string interpolation via a library call that is aware of the specific needs of the database, it's possible to moot the entire issue.
PHP is stupid, and so are its users for putting up with this crap.
/me applauses in the background.
And here I used to wonder why Perl's DBI did that. Great post.