Wright Posted January 22, 2010 Share Posted January 22, 2010 Hello people, I’m new here to PHPFreaks. You know how information out there can be misleading, outdated or not consistent between sources, so I decided to stop by and ask you guys personally. I’m making a file-hosting game related website which will have a user system. I’m currently creating user related functions (and saving them into my little library folder) but I’m stuck on the user input part. As you know you have to take some precautions with user inputted data before allowing it to pass to a MySQL server. As I intend to make a safe community for all, I would like to know how I should sanitize/clean user data before allowing it any further to MySQL queries. Here goes a couple questions: 1. I heard about many filtering options. Which should be ideal to filter user input such as username? 2. What should I allow in username and passwords? Just a-Z and 0-9 characters? And how do I do that? 3. What encryption should I use for my fellow users passwords? Md5()? I think that’s for now. Please don’t bother answering if you are in a rush or something (take no offense), this is a delicate question and any professional feedback would be greatly appreciated. As for my skills, let’s say I’m between novice and medium user of PHP (more for medium really). Sincerely, Wright Quote Link to comment https://forums.phpfreaks.com/topic/189482-security/ Share on other sites More sharing options...
lemmin Posted January 22, 2010 Share Posted January 22, 2010 The function mysql_real_escape_string() pretty much takes care of any risk of injection. The usernames really shouldn't matter as long as you escape them. As for your passwords, MD5 is fine, but I would suggest salting them with your own string to prevent any possible reverse look-ups. $salt = "%4$@"; $pass = MD5($_POST['pass'] . $salt); Good luck! Quote Link to comment https://forums.phpfreaks.com/topic/189482-security/#findComment-1000152 Share on other sites More sharing options...
Wright Posted January 22, 2010 Author Share Posted January 22, 2010 The function mysql_real_escape_string() pretty much takes care of any risk of injection. The usernames really shouldn't matter as long as you escape them. As for your passwords, MD5 is fine, but I would suggest salting them with your own string to prevent any possible reverse look-ups. $salt = "%4$@"; $pass = MD5($_POST['pass'] . $salt); Good luck! Thanks for your answer! Though wikipedia says at http://en.wikipedia.org/wiki/SQL_injection "A straight-forward, though error-prone way to prevent injections is to escape dangerous characters. One of the reasons for it being error prone is that it is a type of blacklist which is less robust than a whitelist. For instance, every occurrence of a single quote (') in a parameter must be replaced by two single quotes ('') to form a valid SQL string literal." What does this mean? Is it hack-able after all? Quote Link to comment https://forums.phpfreaks.com/topic/189482-security/#findComment-1000161 Share on other sites More sharing options...
roopurt18 Posted January 23, 2010 Share Posted January 23, 2010 If you want to protect your users, then you must perform the following and in the correct order. 1) Whenever inserting or updating database data, you must escape the data properly to prevent injection. 2) Whenever selecting data from the database and displaying in HTML, you must use htmlentities() to prevent malicious markup-based attacks. As far as escaping data when inserting / updating, you can use mysql_real_escape_string() and be safe. Personally, I prefer to use PDO for my database interaction because it allows the user of placeholders and will escape data without my having to do so. You can also configure PDO to throw exceptions on errors, which I prefer as it generally results in less error-handling code. I can not stress enough that you must, absolutely must, call htmlentities() on the data after you've retrieved it from the database. Many programmers insist on calling htmlentities() before inserting data into the database thinking that will save them from calling htmlentities() after retrieving data. The problem with this approach is if the database is attacked directly, the attacker will insert malicious markup that will not pass through htmlentities(). Since the application assumes all data in the database has had htmlentities() applied to it, the application will blindly pass the harmful markup to your users. As far as validating data, it's best to ensure that every piece of user input is in the correct format. Regular expressions are helpful for this in addition to some functions (like http://www.php.net/manual/en/ref.ctype.php). As stated, it doesn't really matter what you accept for input as long as you escape before inserting / updating and escape before displaying to a browser. You will have to be wary of any user input that causes access to the file system. There are plenty of exploits where sites expect something like: showfile.php?filename=foo.txt A malicious user might try: showfile.php?filename=../../../../../etc/passwd If your site doesn't watch out for that type of input, users might gain access to files you don't want them to see. 3. What encryption should I use for my fellow users passwords? Md5()? You need to understand the difference between encryption and hashing. Encryption is two-way, meaning you can turn data into junk and then back into the same data. Hashing completely trashes the data in a way you can never, ever, not in a million years know what the original piece of data was again. Password hashing is quite common. md5() is considered a weaker hashing algorithm by today's standards. You should move on to sha1() or sha256(). As mentioned you should salt your hashed data before hashing it; do some research to see why. Never, ever hash a hashed value. Quote Link to comment https://forums.phpfreaks.com/topic/189482-security/#findComment-1000253 Share on other sites More sharing options...
Wright Posted January 23, 2010 Author Share Posted January 23, 2010 Thanks for your insight roopurt18, it will be very helpful. Oh and yes, I meant hashing hehe. Interesting function that ctype_.... Quote Link to comment https://forums.phpfreaks.com/topic/189482-security/#findComment-1000343 Share on other sites More sharing options...
Daniel0 Posted January 23, 2010 Share Posted January 23, 2010 Also take a look at filter_input and filter_var. Quote Link to comment https://forums.phpfreaks.com/topic/189482-security/#findComment-1000351 Share on other sites More sharing options...
Wright Posted January 23, 2010 Author Share Posted January 23, 2010 Yeh Daniel0 though filter_var is not good for emails. I discovered this one at some linux website and made some modifications so it doesn't check for the domain anymore: function validateEmail($email) { /** Validate an email address. Provide email address (raw input) Returns true if the email address has the email address format and the domain exists. */ $isValid = true; $atIndex = strrpos($email, "@"); if (is_bool($atIndex) && !$atIndex) { $isValid = false; } else { $domain = substr($email, $atIndex+1); $local = substr($email, 0, $atIndex); $localLen = strlen($local); $domainLen = strlen($domain); if ($localLen < 1 || $localLen > 64) { // local part length exceeded $isValid = false; } else if ($domainLen < 1 || $domainLen > 255) { // domain part length exceeded $isValid = false; } else if ($local[0] == '.' || $local[$localLen-1] == '.') { // local part starts or ends with '.' $isValid = false; } else if (preg_match('/\\.\\./', $local)) { // local part has two consecutive dots $isValid = false; } else if (!preg_match('/^[A-Za-z0-9\\-\\.]+$/', $domain)) { // character not valid in domain part $isValid = false; } else if (preg_match('/\\.\\./', $domain)) { // domain part has two consecutive dots $isValid = false; } else if (!preg_match('/^(\\\\.|[A-Za-z0-9!#%&`_=\\/$\'*+?^{}|~.-])+$/', str_replace("\\\\","",$local))) { // character not valid in local part unless // local part is quoted if (!preg_match('/^"(\\\\"|[^"])+"$/', str_replace("\\\\","",$local))) { $isValid = false; } } } return $isValid; } What you guys think of this function to check email upon registration? Don't need to escape anything here, since it doesn't accept unusual/suspicious emails. Where can I learn about PDO? I always used mysql_connect and mysql_query etc for my stuff. Any good professional tutorials out there? Quote Link to comment https://forums.phpfreaks.com/topic/189482-security/#findComment-1000379 Share on other sites More sharing options...
Daniel0 Posted January 23, 2010 Share Posted January 23, 2010 Yeh Daniel0 though filter_var is not good for emails. How does filter_var() not work for emails? if (!filter_var('[email protected]', FILTER_VALIDATE_EMAIL)) { echo 'invalid email'; } if (!filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL)) { echo 'invalid email'; } Where can I learn about PDO? Have you checked out the manual? http://php.net/pdo http://php.net/pdo.connections http://php.net/pdo.prepared-statements Quote Link to comment https://forums.phpfreaks.com/topic/189482-security/#findComment-1000387 Share on other sites More sharing options...
Wright Posted January 23, 2010 Author Share Posted January 23, 2010 Yeh Daniel0 though filter_var is not good for emails. How does filter_var() not work for emails? if (!filter_var('[email protected]', FILTER_VALIDATE_EMAIL)) { echo 'invalid email'; } if (!filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL)) { echo 'invalid email'; } Where can I learn about PDO? Have you checked out the manual? http://php.net/pdo http://php.net/pdo.connections http://php.net/pdo.prepared-statements I made some testing myself and read about it, it says it's false for some valid emails. Thanks for the PDO links, didn't know PHP.net had those. Quote Link to comment https://forums.phpfreaks.com/topic/189482-security/#findComment-1000407 Share on other sites More sharing options...
Daniel0 Posted January 23, 2010 Share Posted January 23, 2010 I made some testing myself and read about it, it says it's false for some valid emails. Could you please submit a bug report at http://bugs.php.net then? Quote Link to comment https://forums.phpfreaks.com/topic/189482-security/#findComment-1000412 Share on other sites More sharing options...
Wright Posted January 23, 2010 Author Share Posted January 23, 2010 I made some testing myself and read about it, it says it's false for some valid emails. Could you please submit a bug report at http://bugs.php.net then? Really? Try it yourself, things like something@localhost are accepted. I never thought of it as a bug But sure... I'll take a look at that bug website. I kinda wish it worked for all compliant emails out there, now that you mention it... EDIT: Wow, wait a moment! if (!filter_var('something@localhost', FILTER_VALIDATE_EMAIL)) { echo 'invalid email'; } ^ With this it doesn't recognize as invalid.. if (!filter_input(INPUT_POST, 'something@localhost', FILTER_VALIDATE_EMAIL)) { echo 'invalid email'; } ^ But here it says it is. What might be the reason? This changes alot. should i mysql_real_escape_string("email") and then apply this filter and then allow it to go through MySQL query? Is it safe? Quote Link to comment https://forums.phpfreaks.com/topic/189482-security/#findComment-1000414 Share on other sites More sharing options...
Andy-H Posted January 23, 2010 Share Posted January 23, 2010 I made some testing myself and read about it, it says it's false for some valid emails. Could you please submit a bug report at http://bugs.php.net then? Really? Try it yourself, things like something@localhost are accepted. I never thought of it as a bug But sure... I'll take a look at that bug website. I kinda wish it worked for all compliant emails out there, now that you mention it... EDIT: Wow, wait a moment! if (!filter_var('something@localhost', FILTER_VALIDATE_EMAIL)) { echo 'invalid email'; } ^ With this it doesn't recognize as invalid.. if (!filter_input(INPUT_POST, 'something@localhost', FILTER_VALIDATE_EMAIL)) { echo 'invalid email'; } ^ But here it says it is. What might be the reason? This changes alot. should i mysql_real_escape_string("email") and then apply this filter and then allow it to go through MySQL query? Is it safe? Thats is because you are not using filter_input correctly, when using input POST/GET the 2nd parameter should be the key for the data in the POST/GET array (The name of the HTML input field.) Quote Link to comment https://forums.phpfreaks.com/topic/189482-security/#findComment-1000417 Share on other sites More sharing options...
Wright Posted January 23, 2010 Author Share Posted January 23, 2010 I made some testing myself and read about it, it says it's false for some valid emails. Could you please submit a bug report at http://bugs.php.net then? Really? Try it yourself, things like something@localhost are accepted. I never thought of it as a bug But sure... I'll take a look at that bug website. I kinda wish it worked for all compliant emails out there, now that you mention it... EDIT: Wow, wait a moment! if (!filter_var('something@localhost', FILTER_VALIDATE_EMAIL)) { echo 'invalid email'; } ^ With this it doesn't recognize as invalid.. if (!filter_input(INPUT_POST, 'something@localhost', FILTER_VALIDATE_EMAIL)) { echo 'invalid email'; } ^ But here it says it is. What might be the reason? This changes alot. should i mysql_real_escape_string("email") and then apply this filter and then allow it to go through MySQL query? Is it safe? Thats is because you are not using filter_input correctly, when using input POST/GET the 2nd parameter should be the key for the data in the POST/GET array (The name of the HTML input field.) This isn't the problem i'm talking about it's more like this, take this page for example: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Untitled Document</title> </head> <body> <?php if (!filter_var($_GET["email"], FILTER_VALIDATE_EMAIL)) { echo 'invalid email on filter_var'; } echo "<br />"; if (!filter_input(INPUT_GET, 'email', FILTER_VALIDATE_EMAIL)) { echo 'invalid email on filter_input'; } ?> </body> </html> Now if I do thatpage.php?email=peace@mylocalhostisniceandsmellslikechocolate it doesn't say it's invalid, when, and I think you agree, it should. I'm sure there are other examples, but I can't be bothered to look for more haha. Quote Link to comment https://forums.phpfreaks.com/topic/189482-security/#findComment-1000426 Share on other sites More sharing options...
Daniel0 Posted January 23, 2010 Share Posted January 23, 2010 should i mysql_real_escape_string("email") and then apply this filter and then allow it to go through MySQL query? Is it safe? You should use prepared statements if you are using PDO or MySQLi. Rough, untested example: <?php $db = new PDO('mysql:host=localhost;dbname=test', 'user', 'password'); if ($_SERVER['REQUEST_METHOD'] == 'POST') { $errors = array(); if (!($name = filter_input(INPUT_POST, 'name'))) { $errors[] = 'Missing name.'; } if (!($email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL))) { $errors[] = 'Invalid email address.'; } if (count($errors)) { echo 'Errors:<br>' . join('<br>', $errors); // make this better of course } else { $stmt = $db->prepare('INSERT INTO people (name, email) VALUES (?, ?)'); $stmt->execute(array($name, $email)); } } else { // show form } Now if I do thatpage.php?email=peace@mylocalhostisniceandsmellslikechocolate it doesn't say it's invalid, when, and I think you agree, it should. I'm sure there are other examples, but I can't be bothered to look for more haha. No, that's a perfectly valid email address. The validity does not refer to its existence, but its potential existence, i.e. is the format valid. Quote Link to comment https://forums.phpfreaks.com/topic/189482-security/#findComment-1000429 Share on other sites More sharing options...
Wright Posted January 23, 2010 Author Share Posted January 23, 2010 But hmmm, I'm not going to allow emails that don't have any use... at least they should make it have a country code (.pt, .pl .co.uk, etc) or general ones (.com, etc), and not ones like that, that I can't send anything to (even to activate account or send reminders or whatever else!). What kind of validation is that? :S It's very confusing. EDIT: I'm still researching on PDO, thanks for the example though! Quote Link to comment https://forums.phpfreaks.com/topic/189482-security/#findComment-1000432 Share on other sites More sharing options...
Daniel0 Posted January 23, 2010 Share Posted January 23, 2010 Well, you cannot send an email to [email protected]. How do you imagine your script should catch that? That's why the typical way of checking the existence of an email address (as opposed to its validity) is to send an email to the user and have them follow a link with a unique, random code. If they got the code, they must have gotten the email. Quote Link to comment https://forums.phpfreaks.com/topic/189482-security/#findComment-1000433 Share on other sites More sharing options...
Wright Posted January 23, 2010 Author Share Posted January 23, 2010 Well, you cannot send an email to [email protected]. How do you imagine your script should catch that? That's why the typical way of checking the existence of an email address (as opposed to its validity) is to send an email to the user and have them follow a link with a unique, random code. If they got the code, they must have gotten the email. Yeh I better not worry about it much right? Quote Link to comment https://forums.phpfreaks.com/topic/189482-security/#findComment-1000435 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.