Discover the best of the web!
Learn more about Digg by taking the tour.
Basic PHP Security
templora.com — Tutorial on simple prevention of SQL injections and other easy PHP security mistakes.
- 1321 diggs
- digg it
- spargo, on 10/12/2007, -4/+15A very important aspect of PHP programming.
- PureForm, on 10/12/2007, -2/+9This is the first valuable article on this topic I've seen on DIGG. Great coverage and the author knows what he / she is talking about.
- stisaac, on 10/12/2007, -39/+1Spargo, I dugg you down, but I didn't feel it was enough so:
You didn't say anything. Don't comment on articles for commenting sake, comment if you have something to say. - kevin45, on 10/12/2007, -17/+3HAHA wow digg vengeance ftw
- JacNet, on 10/12/2007, -14/+3What is do bad about entering lolno' OR 1=1;-- as a password?
- kevin45, on 10/12/2007, -13/+1learn sql...?
- demea, on 10/12/2007, -9/+5@ stisaac
you commented just to say that? weak.
..and yes, i realize the irony of my own comment. - florin, on 10/12/2007, -1/+2Print Preview looks like crap in Firefox. Anybody knows how to obtain a good printer-friendly version?
- noodlez, on 10/12/2007, -0/+2@spargo
a very important aspect of programming, period.
although this is geared towards php, the underlying concepts apply for any language. validate your input to make sure you're getting what you expect. - Sp4nk, on 10/12/2007, -12/+3Wrong wrong wrong. You can't inject another SQL query into an existing one. Valuable article my ass.
- tzmguitarist, on 10/12/2007, -3/+7Are you a complete douche? Of COURSE you can inject a completely separate statement into an existing SQL statement... end any SQL injection statement with ; and begin a new one. Or see this:
http://www.unixwiz.net/techtips/sql-injection.html - Sp4nk, on 10/12/2007, -9/+4With the mysql_query() command? No, you can't. Go ahead and try it and then come back and call me a douche again, *****.
- MannaPC, on 10/12/2007, -1/+2@sp4nk
You are a dumbass. Go read the MySQL, PorstSQL and whatever variant you want manual. Look up something called UNION SELECT and then come back and say I was right, douchebag. - Sp4nk, on 10/12/2007, -4/+4Did you actually read the article? How are you going to inject a DROP from a UNION SELECT? I'm not talking about general SQL injection techniques. This isn't a discussion forum for various flavors of SQL. I'm talking about THIS article. You CANNOT add another SQL query the way this guy examples in THIS article.
- MrDiaz, on 10/12/2007, -0/+3this design is a ripoff of Pixel2Life.com
And I bet that article is just likely not yours either. - hackajar, on 10/12/2007, -3/+2//Protect against invalid data
//Post your $_GET global into funtion
function chkGet($get) {
//Count how may get vars were sent (not much security but a start)
$count = 2; //how many allowed vars?
if(count($get)>$count)return false;
foreach($get as $key=>$val) {
switch($key) {
case 'page':if(!is_numeric($val))return false; else break; //Assume we expect a numeric page number
case 'id':if(!is_numeric($val))return false; else break; //Assume we expect a numeric id number
default: return false; //If you did not expect that var from GET string, someone was being bad!
}
}
}
if(!chkGet($_GET))die("Invalid GET values!");
Of course, clean this up for your environment ;) - bradleyland, on 10/12/2007, -0/+0Shamelessly stolen from the comments on php.net, I use the following code for inserts, but only if I'm working on small projects that don't warrant full ORM. I consider this the least amount of code required to get the job done without completely exposing your cornhole. I should probably revise my technique to use a sql_escape_int function for int values, this way I can validate my data type. I generally perform this check during my form data validation phase, though it never hurts to check twice.
$query = sprintf("INSERT INTO messages (author, city, state, email) VALUES (%s, %s, %s, %s);",
sql_escape($_REQUEST['author']),
sql_escape($_REQUEST['city']),
sql_escape($_REQUEST['state']),
sql_escape($_REQUEST['email'])
);
mysql_query($query);
// sql_escape function defined as follows
function sql_escape($value)
{
// Stripslashes
if (get_magic_quotes_gpc()) {
$value = stripslashes($value);
}
// Quote if not a number or a numeric string
if (!is_numeric($value)) {
$value = "'" . mysql_real_escape_string($value) . "'";
}
return $value;
} - rspeed, on 10/12/2007, -0/+1@ Sp4nk
I hope you're not a PHP developer. If you were, and I were your boss, I'd kick your ass. - Fatality, on 10/12/2007, -0/+2What's with all the Get usage?
Deny entering of values into the URI and restrict user permissions for things like DROP.
- phjr, on 10/12/2007, -9/+2Yet another basic language security guide. Nothing new. But the article itself is good.
- kevin45, on 10/12/2007, -11/+1A pitfall of open source?
- kden, on 10/12/2007, -2/+3Good read for any beginning PHP programmer.
- SoxFanNH, on 10/12/2007, -1/+3Pretty good basic reading
- Area51mafia, on 10/12/2007, -0/+4For more indepth security practices for PHP, I recommend Pro PHP Security on Apress. It covers a lot more stuff than is listed here.
- zoom1928, on 10/12/2007, -1/+15More incorrect FUD about SQL injection. Is there any database that PHP works with that works like these morons describe? None I've tested work like that. The idiot claims that a query like this:
mysql_query("SELECT * FROM test; DROP DATABASE important_db");
will drop a database. It won't. It will simply give an error message because you can't use more than a single SQL statement. There is no way with SQL injection to get MySQL to process more than one query in a single mysql_query() call.- akinder, on 10/12/2007, -0/+1Exactly, the only thing you can do with most versions of MySQL would be a UNION SELECT to pull, say, a session ID from a table, to hijack the session. I've never seen a DROP DATABASE command work, and if it does, what the hell are you doing allowing your unpriv'd user drop the database?
- trylleklovn, on 11/06/2007, -2/+2You can however DROP TABLE... I tried it once on a.. rather poorly written website.. ;)
- iamnos, on 10/12/2007, -0/+4Exactly, the real vulnerability is that the user input will be such that the query is something like:
SELECT * FROM user_info WHERE id=1 OR 1;
Which, depending on how its coded, could reveal information about everybody in the user_info table. - josho, on 10/12/2007, -0/+3yeah, i really hate it when people don't realize you can't execute ANY two statements in a single mysql_query function call. i believe it's now possible with the mysqli lib, but shrug.
most of the sql injections i've seen/done involve mssql/sqlserver. akinder has it right with being able to bust unions, but even then, the entire process presupposes the programmer has turned off magic_quotes and isn't escaping properly. 90% of the time, the most you can do is pass some messed up parameters that should trigger errors within the sql parser or in the script's attempt to work with null result sets. - gauthierm, on 10/12/2007, -0/+1Both MSSQL and PostgreSQL allow multiple statements in a *_query() function. PostgreSQL will even wrap multiple statements in a transaction for you. PHP does not support multiple statements in mysql_query().
- celestial, on 10/12/2007, -7/+0RIIIIIIIIIIIIIIIIIIIIIDGE RACER!!!
o wait - dotlizard, on 10/12/2007, -0/+3nice -- well written and informative, with clear examples. they have a nice beginning AJAX tutorial too, covers the basics and is also clearly written.
- panic, on 10/12/2007, -0/+1There's more info at http://www.digitalpropulsion.org/Programming
- vonskippy, on 10/12/2007, -10/+2Learn Perl.
- merreborn, on 10/12/2007, -0/+9Perl is just as vulnerable to SQL injection, XSS and CSRF as any other language.
- prammy, on 10/12/2007, -2/+1Considering that the security issues are due to poor programming practices rather than the language used.
- vonskippy, on 10/12/2007, -2/+4Except that Perl is usually written by programmers where PHP is hacked out by anyone that can cut-n-paste.
- disti, on 10/12/2007, -0/+2And DBI docs tell you to use question mark in statements (do and prepare functions) and then use bind variables in do and execute functions.
For example:
$sth = $dbh->prepare("INSERT INTO table(foo,bar,baz) VALUES (?,?,?)");
$sth->execute( $foo, $bar, $baz ); # in following loop maybe
- writh3n, on 10/12/2007, -3/+0zoom1928,
if you are doing a select statement like (SELECT something FROM table WHERE some_id='$some_value') the sql injection will work, because %27%3B%20DROP%20DATABASE%20-- returns '; DROP DATABASE-- which would turn that statement literally into (SELECT something FROM table WHERE some_id=''; DROP DATABASE--'). The ' ; completes the query and it executes, the drop database is the next command that will be executed and will drop the database, the -- is how you can comment in sql so it will clear out anything else that may have been left from the first statement. So it will close the statement, drop the database, and ignore everything after that statement.- willclarke, on 10/12/2007, -0/+4No... it won't work. mysql_query() won't execute more than one sql statement, ever. It will throw an error if you try. There is absolutely no way to make that work.
- iamnos, on 10/12/2007, -0/+2What your missing though is that PHP will only execute one SQL command in a query. It doesn't matter if you have the semicolon to mark the end of a command or not. Well, actually if you don't you'll get a syntax error in your SQL.
- gauthierm, on 10/12/2007, -0/+2lamnos: While this is true for MySQL, it is not true for other databases and is certainly not an excuse to not worry about SQL injections.
- merreborn, on 10/12/2007, -0/+2FTA, RE: CSRF:
"First and foremost, this works only with GET requests, since there is no other sneaky way to issue a hidden call without an image (and without a script, which is solved with XSS protection)"
This is absolutely wrong. CSRF attacks against your site could come from ANYWHERE on the internet -- and not everywhere on the internet is protected from XSS!
Say your site is a forum -- exampleForum.com. You've protected it against XSS. However, a user posts a link to their myspace page. On their myspace page, is some javascript that submits a CSRF POST form back to exampleForum.com in the onload. Viola. Your site has just fallen prey to CSRF, even tough you've switched to POST, and protected it from XSS. - headzoo, on 10/12/2007, -1/+4Not too bad for a crash course in PHP security. There are entire books that can be read on each topic covered, so it's not exactly fleshed out. But if you're new to PHP (and internet security in general), are you've been completely oblivious to these terms, then the article at least gives you a good spring board for some Google searching.
- thecheatah, on 10/12/2007, -1/+1Hmm learned something new. I never thought about causing a request using a get statement in an image.
Good stuff! - nobarcode, on 10/12/2007, -0/+1From the article:
- nobarcode, on 10/12/2007, -0/+7if ($a=1) $somevar="thisorthat";
Should be:
if ($a==1) $somevar="thisorthat";
Because the original code, [if ($a=1)] is assigning the value of 1 to $a, it will always evaluate to true, and thus $somevar will always be assigned a value of "thisorthat" -- rendering the injection the author describes quite useless.
Most likely just a typo. But articles dealing with security should be scrutinized, I think.
- nobarcode, on 10/12/2007, -0/+7if ($a=1) $somevar="thisorthat";
- jalenack, on 10/12/2007, -1/+1There are a couple problems with his XSS suggestions. First, to test yourself against XSS, I wouldn't recommend using something with plain quotes. You might have turned on magic quotes (eek!) and the offending script would get some \"ed text, so it would produce an error, but the threat is still there because you can do anything you want without quotes. The simplest test might be alert(document.cookie), as it contains no quotes and is still interesting.
Also, he recommends htmlentities() for escaping. That's major overkill in my experience, and if you're doing any text-wrapping code things can get complicated rather quickly, not to mention the added bandwidth and processing for escaping all the unimportant entities. All you need is htmlspecialchars(). Really.
But overall, he touched on some good points.. - kayla, on 10/12/2007, -1/+3Finally, a good article on Digg.
- uzytkownik, on 10/12/2007, -0/+1About SQL:
In PHP 5 MySQL can do preprocessed statements(by mysqli). PEAR_DB for all databases I think.
$stmt = $mysqli->prepare("SELECT * FROM table WHERE id=?");
$stmt->bind_param("s", $id);
$stmt->execute(); - daridave, on 10/12/2007, -3/+1Good for beginners, however any average tutorial usually covers this.
If you don't escape, don't code PHP... - championchap, on 10/12/2007, -0/+3Anyone else notice the site had a VERY pixel2life theme to it?
- GrumpySimon, on 10/12/2007, -2/+2This is a stupidly BAD article.
The guy who wrote that obviously didn't know that mysql_query doesn't do multiple queries, so his " ; DROP DATABASE --" example doesn't work. That, and the fact that DROP DATABASE needs a database name too.
As for blindly mysql_real_escape'ing things, what about magic quotes? you need to check if these are on or off first before escaping otherwise you're going to end up with a plague of ' and ' everywhere.
SQL injection is a MAJOR issue and needs to be handled properly - prepared statements if possible, if not, careful m_r_e_s usage after removing magic quotes. I wrote a lengthy post on this here:
http://simon.net.nz/articles/protecting-mysql-sql-injection-attacks-using-php/
As for XSS - please don't use htmlentities, htmlspecialchars is far faster and more efficient as it only escapes the characters you REALLY need to. - Faken, on 10/12/2007, -1/+2Wow good job ripping off the P2L layout at Pixel2life.com.
- donnar, on 10/12/2007, -1/+1I hope your taking action on these Morons
- donnar, on 11/06/2007, -2/+3What kinda moron would get their site on the front page of Digg if it's ripped from Pixel2Life lol
Lets see how long before it goes *kaput* if digg don't get you DMCA will lol - endun, on 10/12/2007, -1/+3nice link, but im sure they have ripped the template! http://www.pixel2life.com/
- mpancha, on 10/12/2007, -0/+2that was useless....
- hackajar, on 10/12/2007, -0/+1Go straight to the source!
Security in PHP
http://www.php.net/manual/en/security.php
Protecting against SQL Injections
http://www.php.net/manual/en/security.database.sql-injection.php - insanesparrow, on 11/06/2007, -1/+0Show this to those guys over at myspace lol!
- championchap, on 10/12/2007, -0/+1mySpace uses Coldfusion, not PHP.
- cope, on 11/06/2007, -2/+1/** Break a string down to add to the database
* @example htmlstring($string, $length);
*/
function safestring($text, $length) {
if(strlen($text) > $length) {
$text = substr($text, 0, $length);
}
$text = html_real_escape_string($text);
$text = "'".$text."'";
return $text;
} - haxx4, on 11/06/2007, -1/+2http://www.duggmirror.com
- havensbreeze, on 11/06/2007, -1/+0good article about PHP and security
Digg is coming to a city (and computer) near you! Check out all the details on our