i am implementing a simple closed area on a website.
The access is granted upon entering the right password. The password is shared so no real accounts are in place.
I am trying to understand if i am missing some variable filtering and if i should sanitize the data. I'm pretty sure i must do it, but i don't know what is the best approach.
In my code i have two places where i use the data from the $_POST variable:
if(isset($_POST)&&$_POST['the_password']!="")
{
$my_password = $_POST['the_password'];
//Should i use something like this?
//$my_password = filter_input(INPUT_POST, 'the_password', FILTER_SANITIZE_STRING);
}
The second place is where i use the variable, in an if statement:
if($a_password == $my_password)
{
//Query using the $a_password variable
}
In this part of code $a_password comes from a hard coded query.
Is the filter_input function the right one? Am i missing something?
The short answer is no; for an if statement, your code is safe.
However, if you edit the code later, you should use prepared statements in you database queries.
Related
Stupid question here, Should I be sanitizing every $_POST / $_GET variable even if it is just being used for something like a comparison?
Example:
if ( $_POST[ 'example' ] === 1 ){ // Do Something }
I understand the idea of using prepared statements for databases, etc, but I am curious / worried about a user placing some PHP code or something else and it running during that check.
You only need to worry about sanitizing your inputs if they could be used in a context where they would be evaluated - in a database script, for example, or as HTML on a web page.
I am using MySQLConverterTool to convert my web application,
first issue i faced is code getting to big i dont even understand what that means? It was very small code before and now i see this is too big.
//old code
$ask_id = mysql_real_escape_string($_POST['ask_id']);
//after convert
$ask_id = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $_POST['ask_id']) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
Its working fine but i want to know if its correct way of mysqli_* or is there some issue or bug i need to fix in line?
I also want to know how i can make this part secure
if (isset($_POST['asking-money'])) {
$dailyBonus = 10000;
$update = mysqli_query($GLOBALS["___mysqli_ston"], "UPDATE users SET ask_time='$newtime', bonus='dailyBonus' WHERE id='$userid'");
// some more calculation
}
The first bit of code looks like it (grossly) added a giant ternary statement to check that the variables you were using were at least set, but other than that you should just be able to use:
mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $_POST['ask_id'])
As for security with the SQL query, try using Prepared Statements instead of directly querying with variables
mysqli_prepare
for the mysqli_* part, most of the things that used to be done with mysql_* remained almost the same with a new prefix, so, most likely there is no problem
and for the how to make it secure, just evaluate and prepare all the parameters being passed from the user before using them in the query, in other words, NEVER under any case, use the user input directly in a query. other than that the code seems very fine to me.
The first code is a ternary statement (short way for if/else). Way too much, my opinion.
I recommend PDO and it's prepared statements, if you're able to use it. It's very secure and easy to handle.
By the way: try to avoid the MySQLConverterTool. It's hard to get into this code after months. K eep i t s mart and s imple! :-)
Good luck!
might be a silly question nonetheless:
I'm playing around with the following code:
$a='a';
if ($_GET['a'] == $a)
echo 'true';
else
echo 'false';
Now, is there any way to send data to break the verification? Obviously the way it could've been done in an SQL injection won't go.
Just wondering how secure this way of validation is.
Thanks in advance.
EDIT:
My question was, is there anything that can be passed thorugh $_GET that could 'break' the comparison and always output 'true'.
If you are looking to validate that $_GET['a'] really in face equals to "a" and nothing else, than yes, that's the code.
However, if you're expecting "a" and only "a" it probably shouldn't be a user input.
Validation (or sanitation), means to take whatever string they might throw at you, and make sure it's valid for whatever purpose you want it to. If it's sent to the database, pass it through mysql_escape_string() or use prepared statements. If it's to be displayed as HTML make sure there aren't any harmful tags by using html_entities() or strip_tags().
Your verification isn't very good for anything else other than saying the user has inputted "a". But yes, nothing other than "a" would be able to get through.
Well, if you knew exactly what was coming in, you could compare without type coercion and check for an empty parameter:
$a = 'a';
if( !empty( $_GET['a'] ) && $_GET['a'] === $a )
{
//do more validation using your data model
}
else
{
//output error msg
}
You could use Prepared-Statements from the mysqli extension this already prevents every possible injection.
If you don't want to use such mysql and mysqli also have "real_escape_string"-methods which you can use in your Query when putting in Userinput
Example
$sql = "SELECT `name` FROM `example` WHERE `id` = '".mysql_real_escape_string($YOURVAR)."'";
real_escape_string method from standart mysql extension
mysqli real_escape_string
I have a lot of user inputs from $_GET and $_POST... At the moment I always write mysql_real_escape_string($_GET['var'])..
I would like to know whether you could make a function that secures, escapes and cleans the $_GET/$_POST arrays right away, so you won't have to deal with it each time you are working with user inputs and such.
I was thinking of an function, e.g cleanMe($input), and inside it, it should do mysql_real_escape_string, htmlspecialchars, strip_tags, stripslashes (I think that would be all to make it clean & secure) and then return the $input.
So is this possible? Making a function that works for all $_GET and $_POST, so you would do only this:
$_GET = cleanMe($_GET);
$_POST = cleanMe($_POST);
So in your code later, when you work with e.g $_GET['blabla'] or $_POST['haha'] , they are secured, stripped and so on?
Tried myself a little:
function cleanMe($input) {
$input = mysql_real_escape_string($input);
$input = htmlspecialchars($input, ENT_IGNORE, 'utf-8');
$input = strip_tags($input);
$input = stripslashes($input);
return $input;
}
The idea of a generic sanitation function is a broken concept.
There is one right sanitation method for every purpose. Running them all indiscriminately on a string will often break it - escaping a piece of HTML code for a SQL query will break it for use in a web page, and vice versa. Sanitation should be applied right before using the data:
before running a database query. The right sanitation method depends on the library you use; they are listed in How can I prevent SQL injection in PHP?
htmlspecialchars() for safe HTML output
preg_quote() for use in a regular expression
escapeshellarg() / escapeshellcmd() for use in an external command
etc. etc.
Using a "one size fits all" sanitation function is like using five kinds of highly toxic insecticide on a plant that can by definition only contain one kind of bug - only to find out that your plants are infested by a sixth kind, on which none of the insecticides work.
Always use that one right method, ideally straight before passing the data to the function. Never mix methods unless you need to.
There is no point in simply passing the input through all these functions. All these functions have different meanings. Data doesn't get "cleaner" by calling more escape-functions.
If you want to store user input in MySQL you need to use only mysql_real_escape_string. It is then fully escaped to store safely in the database.
EDIT
Also note the problems that arise with using the other functions. If the client sends for instance a username to the server, and the username contains an ampersand (&), you don;t want to have called htmlentities before storing it in the database because then the username in the database will contain &.
You're looking for filter_input_array().
However, I suggest only using that for business-style validation/sanitisation and not SQL input filtering.
For protection against SQL injection, use parametrised queries with mysqli or PDO.
The problem is, something clean or secure for one use, won't be for another : cleaning for part of a path, for part of a mysql query, for html output (as html, or in javascript or in an input's value), for xml may require different things which contradicts.
But, some global things can be done.
Try to use filter_input to get your user's input. And use prepared statements for your SQL queries.
Although, instead of a do-it-all function, you can create some class which manages your inputs. Something like that :
class inputManager{
static function toHTML($field){
$data = filter_input(INPUT_GET, $field, FILTER_SANITIZE_SPECIAL_CHARS);
return $data;
}
static function toSQL($field, $dbType = 'mysql'){
$data = filter_input(INPUT_GET, $field);
if($dbType == 'mysql'){
return mysql_real_escape_string($data);
}
}
}
With this kind of things, if you see any $_POST, $GET, $_REQUEST or $_COOKIE in your code, you know you have to change it. And if one day you have to change how you filter your inputs, just change the class you've made.
May I suggest to install "mod_security" if you're using apache and have full access to server?!
It did solve most of my problems. However don't rely in just one or two solutions, always write secure code ;)
UPDATE
Found this PHP IDS (http://php-ids.org/); seems nice :)
if(get_magic_quotes_gpc())
{
$location_name = trim(mysql_real_escape_string(trim(stripslashes($_GET['location_name']))));
}
else
{
$location_name = trim(mysql_real_escape_string(trim($_GET['location_name'])));
}
That's the code I have so far. seems to me this code is fundamentally ... OK. Do you think I can safely remove the inner trim(). Please try not a spam me with endless version of this, I want to try to learn how to do this better.
UPDATE
So after reading some of the responses, I think I have come to understand a good method for safely getting data from a user, storing it and then displaying it back.
When you first load the page
$foo = trim($_GET['foo']);
if(get_magic_quotes_gpc())
{
$foo = stripslashes($foo);
}
Then when you come to use this variable as part of a SQL string, even if not storing the data in the database, you should escape it.
mysql_real_escape_string($foo);
And finally, if reading data from the database and wanting to display it as HTML, such a post on a blog or forum, you should pass the variable using htmlspecialchars
echo(htmlspecialchars($bar));
Would any one like to suggest a better set of functions to use? other then obviously wrapping these functions to make them simpler to call.
Here:
$location_name = trim($_GET['location_name']);
if(get_magic_quotes_gpc()) $location_name=stripslashes($location_name);
Then there is also the SQL injection protection, but don't do this until the very last moment before sticking this var in an SQL query. And even then don't apply the changes to the var itself, but rather a copy. You might want to show $location_name to the user afterwards (for example if the form fails). So
$sql="UPDATE whatever(location) VALUES('" . mysql_real_escape_string($location_name) . "')"
I'm assuming of course that $location_name will end up in the database; otherwise you don't need mysql_real_escape_string.
Finally you want to use htmlspecialchars if you're going to display $location_name on your page somewhere.
Edit: You want to use htmlspecialchars() just before displaying the data (definately don't save data that has already been transformed via htmlspecialchars in your database). In general you want to use escaping functions at the last moment and then on a copy of your var. That way you know that at any point during the script the var is the original one and is not carrying some random escape characters from a transformation that happened somewhere before.
You also know where your escape functions are/should be. sql escaping is near/at your sql query. XSS escaping (htmlspecialchars) is near the part where you display data in a web page.
Finally once you get the grip of things, you could always forego SQL escaping by using PHP's PDO functions. Also in the future you might want to take at look at this: Do htmlspecialchars and mysql_real_escape_string keep my PHP code safe from injection?
I am sorry to say but everything in your question is wrong.
First, it has nothing to do with performance, by any means. these functions never become a bottleneck and never cause any performance issue.
Next, You've choose wrong place to get rid of magic quotes. Magic quotes is input data related, not database related. It it is better to make a distinct function and place it in your configuration file, being included into every script. You can use one from here
So, the code become like this:
$location_name = mysql_real_escape_string(trim($_GET['location_name']));
But i strongly advise you not to mix database escaping with anything else, as anything else is optional while database escaping is strict and unconditional.