PHP + MYsql new security npractice - php

I filter the input from user in every submission or i have create function which manipulates the get/post values and call it in every submission of form.
But now i kept the below functions in main include file following:
foreach ($_POST as $key => $value) {
$_POST[$key] = mysql_real_escape_string(trim($value));
}
foreach ($_GET as $key => $value) {
$_GET[$key] = mysql_real_escape_string(trim($value));
}
It works well, but is there any downsides of doing this for EVERY single post/get?
P.S. Well except performance of script.

Validate user inputs rather than escaping first, after validating
and before insertion into db u can escape.
Answer for your question: Doing it in a proper manner is to use
function and place those function in a separate file and including
that file before calling the function.. your furst way is also fine
but if the form and its fields are big in count then the script will
be messy and would be hard to maintain by other developers hence
using the second way of using a file containing your filtering functions is
a good idea in any case....

This isn't a logical way to solve this. As mentioned, this won't handle multidimensional arrays and will be an annoyance if you all of a sudden might need to work with the original value. For instance someone maybe wants to save a textarea field and wants a couple of rows at the bottom to continue the work later on. These rows will vanish upon saving then.
Form validation may get a bit messy aswell.
Your solution isn't a 100% secure method either. You're still vurnerable against XXS.
Apart from that I know no framework which does this automaticly, and they probably aint doing it for a reason.

mysql_real_escape_string does not fully prevent SQL Injection. Lets see the following example:
$input = mysql_real_escape_string($_POST['id']);
$query = "DELETE FROM user WHERE id={$input};";
Lets say $_POST['id'] equal to 1 OR TRUE

Related

Sanitize user input in laravel

I've got a simple question:
When is it best to sanitize user input?
And which one of these is considered the best practice:
Sanitize data before writing to database.
Save raw data and sanitize it in the view.
For example use HTML::entities() and save result to database.
Or by using HTML methods in the views because in this case laravel by default uses HTML::entities().
Or maybe by using the both.
EDIT: I found interesting example http://forums.laravel.com/viewtopic.php?id=1789. Are there other ways to solve this?
I would say you need both locations but for different reasons. When data comes in you should validate the data according to the domain, and reject requests that do not comply. As an example, there is no point in allowing a tag (or text for that matter) if you expect a number. For a parameter representing.a year, you may even want to check that it is within some range.
Sanitization kicks in for free text fields. You can still do simple validation for unexpected characters like 0-bytes. IMHO it's best to store raw through safe sql (parameterized queries) and then correctly encode for output. There are two reasons. The first is that if your sanitizer has a bug, what do you do with all the data in your database? Resanitizing can have unwanted consequences. Secondly you want to do contextual escaping, for whichever output you are using (JSON, HTML, HTML attributes etc.)
I have a full article on input filtering in Laravel, you might find it useful http://usman.it/xss-filter-laravel/, here is the excerpt from this article:
You can do a global XSS clean yourself, if you don’t have a library to write common methods you may need frequently then I ask you to create a new library Common in application/library. Put this two methods in your Common library:
/*
* Method to strip tags globally.
*/
public static function global_xss_clean()
{
// Recursive cleaning for array [] inputs, not just strings.
$sanitized = static::array_strip_tags(Input::get());
Input::merge($sanitized);
}
public static function array_strip_tags($array)
{
$result = array();
foreach ($array as $key => $value) {
// Don't allow tags on key either, maybe useful for dynamic forms.
$key = strip_tags($key);
// If the value is an array, we will just recurse back into the
// function to keep stripping the tags out of the array,
// otherwise we will set the stripped value.
if (is_array($value)) {
$result[$key] = static::array_strip_tags($value);
} else {
// I am using strip_tags(), you may use htmlentities(),
// also I am doing trim() here, you may remove it, if you wish.
$result[$key] = trim(strip_tags($value));
}
}
return $result;
}
Then put this code in the beginning of your before filter (in application/routes.php):
//Our own method to defend XSS attacks globally.
Common::global_xss_clean();
I just found this question. Another way to do it is to enclose dynamic output in triple brackets like this {{{ $var }}} and blade will escape the string for you. That way you can keep the potentially dangerous characters in case they are important somewhere else in the code and display them as escaped strings.
i'd found this because i was worried about xss in laravel, so this is the packages gvlatko
it is easy:
To Clear Inputs = $cleaned = Xss::clean(Input::get('comment');
To Use in views = $cleaned = Xss::clean(Input::file('profile'), TRUE);
It depends on the user input. If you're generally going to be outputting code they may provide (for example maybe it's a site that provides code snippets), then you'd sanitize on output. It depends on the context. If you're asking for a username, and they're entering HTML tags, your validation should be picking this up and going "no, this is not cool, man!"
If it's like the example I stated earlier (code snippets), then let it through as RAW (but be sure to make sure your database doesn't break), and sanitize on output. When using PHP, you can use htmlentities($string).

Efficient if statement / for loop

2 short questions based on trying to make my code more efficient (I think my ultimate quest is to make my entire (fairly complex) website based on some sort of MVC framework, but not being a professional programmer, I think that's going to be a long and steep learning curve..)
In this code, is there a way to merge the if statement and for loop, to avoid the nesting:
if($fileatt['name']!=null)
{
$attachedFiles = "You uploaded the following file(s)\n";
for($i=0;$i<count($docNames);$i++)
{
$attachedFiles = $attachedFiles. " - " . $docNames[$i] . "\n";
}
}
At the moment, I do the fairly standard thing of splitting my $_POST array from a form submission, 'clean' the contents and store the elements in individual variables:
$name = cleanInput($_POST['name']);
$phone = cleanInput($_POST['phone']);
$message = cleanInput($_POST['message']);
...
(where cleanInput() contains striptags() and mysql_real_escape_string())
I had thought that keeping all the information in an array might my code more efficient, but is there a way to apply a function to all (or selected) elements of an array? For example, in R, this is what the apply() function does.
Alternatively, given that all my variables have the same name as in the $_POST array, is there a way to generate all the variables dynamically in a foreach loop? (I know the standard answer when people ask if they can dynamically generate variables is to use a hashmap or similar, but I was interested to see if there's a technique I've missed)
You can use extract and combine it with array_map
extract(array_map('cleanInput', $_POST), EXTR_SKIP);
echo $name; // outputs name
Be warned that $_POST could be anything and user can then submit anything to your server and it becomes a variable in your code, thus if you have things like
if(empty($varName)) { } // assumes $varName is empty initially
Could easily bypassed by user submitting $_POST['varName'] = 1
To avoid mishaps like this, you can have a whitelist of array and filter out only those you need:
$whitelist = array('name', 'phone', 'message');
$fields = array();
foreach($_POST as $k => $v) {
if(in_array($k, $whitelist)) $fields[$k] = $v;
}
extract(array_map('cleanInput', $fields));
1) To the first question, how to merge the if and the for loop:
Why would you want to merge this, it will only make the code more difficult to read. If your code requires an if and afterwards a for loop, then show this fact, there is nothing bad with that. If you want to make the code more readable, then you can write a function, with a fitting name, e.g. listAttachedFiles().
2) To the question about cleaning the user input:
There is a difference between input validation and escaping. It's a good thing to validate the input, e.g. if you expect a number, then only accept numbers as input. But escaping should not be done until you know the target system. So leave the input as it is and before writing to the db use the mysql_real_escape_string() function, before writing to an HTML page use the function htmlspecialchars().
Combining escape functions before needed, can lead to invalid data. It can become impossible to give it out correctly, on a certain target system.
Personally I think that the performance cost of using an "If" statement is worth the benefit of having easily readable code. Also you have to be sure that you actually use fewer cycles by combining, if there is such a way.
I'm not sure I follow your second question, but have you looked at extract() and array_walk() yet?
Point 1 is premature optimization. And you want get any better performance / readability by doing so. (similar for using arrays for everything).
Point 2 - AaaarrgghhH! You should only change the representation of data at the point where it leaves PHP, using a method approporiate to the destination - not where it arrives in PHP.
To make your for loop more efficient don't use Count() within the condition of your loops.
It's the first thing they teach in school. As the For loops are reevaluating the conditions at each iterations.
$nbOfDocs = count($docNames); //will be much faster
for($i=0;$i<$nbOfDocs;$i++)
{
$attachedFiles = $attachedFiles. " - " . $docNames[$i] . "\n";
}

How can I get all submitted form values in PHP and automatically assign them to variables?

I'm trying to migrate a website from one host to another. On the first host, when you submit a form, all of the form values are automatically stuck into variables with the input name (this is PHP). On the new host, these values are all null unless I do this:
$data = $_GET['data'];
Is there a PHP configuration setting that is causing this? If there isn't, is there an easy way to loop through all of the $_GET variables and automatically assign their values to a variable with the same name?
Thanks!
The setting is register_globals, but it is now deprecated and strongly advised against using it because it is a security risk. Anyone can set variables in your script which might interact in a negative or unexpected way with your code.
If you absolutely must, you can do it like this:
foreach ($_GET as $key=>$value) {
$$key = $value;
}
or, more simply:
import_request_variables("g");
or, to make it a little safer:
import_request_variables("g", "myprefix_"); // This way forces you to use "myprefix_"
// in front of the variables, better ensuring you are not unaware
// of the fact that this can come from a user
extract($_GET) could also work, as someone else pointed out, and it also allows specification (via extra arguments) of adding a prefix or what to do if your extraction conflicts with an already existing variable (e.g., if you extracted after you defined some other variables).
Look at the extract function : http://www.php.net/manual/en/function.extract.php
You could do something like this:
foreach ($_GET["data"] as $name => $value){
$$name = $value;
}
The issue with this is that it makes it easy for people to fiddle with the variables in your script. I could visit http://yoursite.com/?sql=DELETE+FROM...
I'd advise against doing this and just sticking to using $_GET.
Your question infers you are not doing any filtering or validation when assigning $_GET['data'] to $data, unless you are doing these kind of checks further down your script.
From what I have seen most programmers would do this first, in an effort to fail early if expected data did not match expectations, so that the above assignment in the case of expecting a positive int would become something like:
if( isset($_GET['data']) && (int)$_GET['data'] === 0){
//fail
}else{
$data = $_GET['data'];
}
So seeing just plain
$data = $_GET['data']
makes me wince.

Easiest and most efficient way to get data from URL using php?

Solution?
Apparently there isn't a faster way, I'm okay with that.
I am just learning php and I am trying to figure out some good tips and tricks so I don't get into a bad habit and waste time.
I am passing in values into a php script. I am using $_GET so the URL looks like this:
/poll_results.php?Sports=tennis&cat=Sports&question=Pick+your+favorite+sports
Now I know how to accept those values and place them into variables like so:
$sports = $_GET['Sports'];
$cat = $_GET['cat'];
$question = $_GET['question'];
Super simple yet if I am passing 5 - 6 things it can get bothersome and I don't like typing things out for every single variable, that's the only reason. I know there is a better way of doing this. I have tried list($var, $var, $var) = $_GET but that doesn't work with an associative array just indexed ones (i think).
I also tried variable variables like so:
foreach($_GET as $value) {
$$values = $value;
echo $$values;
}
But that gave me a Notice: Undefined variable: values in poll_results.php on line 14. Line 14 is the $$values = $value. I don't know if that's a big deal or not... but I'm not turning off error reporting as I am still in the process of building the script. It does do what I want it to do though...
Any answers will be copied and pasted into my question so the next person knows :D
Thanks guys!
Your second bit of code is wrong. It ought to be like
foreach ($_GET as $key => $value) {
$$key = $value;
}
if i understand your intent. However, you're basically reinventing register_globals, which....eh. That'll get ya hacked.
If you have certain variables you want to get, you could do like
foreach (array('Sports', 'cat', 'question') as $key)
{
$$key = $_GET[$key];
}
which is less likely to overwrite some important variable (whether by accident or because someone was messing around with URLs).
Use parse_url() to extract the query string from a URL you've got in a string, then parse_str() to extract the individual arguments of the query string.
If you want to pollute your script with the contents of the superglobals, then you can use extract(). however, be aware that this is basically replicating the hideous monstrosity known as "register_globals", and opens all kinds of security vulnerabilities.
For instant, what if one of the original query arguments was _GET=haha. You've now trashed the $_GET superglobal by overwriting it via extract().
I am just learning php and I am trying to figure out some good tips and tricks so I don't get into a bad habit and waste time.
If I am passing 5 - 6 things it can get bothersome and I don't like typing things out for every single variable, that's the only reason.
What you are trying to do will, unless curbed, become a bad habit and even before then is a waste of time.
Type out the variables: your digits like exercise and your brain can take it easy when it doesn't have to figure out which variables are available (or not, or maybe; which would be the case when you use variable variables).
You can use
foreach($_GET as $key => $value)
To preserve the key and value associativity.
Variable variables (the $$value) are a bad idea. With your loop above say you had a variable named $password that is already defined from some other source. Now I can send $_GET['password'] and overwrite your variable! All sorts of nastiness can result from this. It's the same reason why PHP abandoned register_globals which essentially does the same thing.
My advice: use $_POST when possible. It keeps your URLs much cleaner for one thing. Secondly there's no real reason to assign the array to variables anyway, just use them where you need them in the program.
One good reason for this, especially in a large program, is that you'll instantly know where they came from, and that their data should not be trusted.

A nice function to escape $_POST // what do you think about it

I'm using $_POST and aware about mysql exploit, I decided to use this function on the top of my page, therefore all POST will be safe:
Can you tell me if I miss something and this function will really do the job as I think it will?
function clean_post(){
if ( $_POST){
foreach ($_POST as $k => $v) {
$_POST[$k]=stripslashes($v);
$_POST[$k]=mysql_real_escape_string($v);
$_POST[$k]=preg_replace('/<.*>/', "", "$v");
}
}
if ( $_COOKIE){
foreach ($_COOKIE as $k => $v) {
$_COOKIE[$k]=stripslashes($v);
$_COOKIE[$k]=mysql_real_escape_string($v);
$_COOKIE[$k]=preg_replace('/<.*>/', "", "$v");
}
}
}
It will also remove all html tag, a safest option to output the result might be to use:
<pre>
$foo
</pre>
Cheers!
Cheers!
I think it's a bad idea to do this. It will corrupt the data your users enter even before it hits the database. This approach will also encourage you to use lazy coding where you consistently don't escape data because you believe that all your data is already "clean". This will come back to bite you one day when you do need to output some unsafe characters and you either forget to escape them or you aren't really sure which function you need to call so you just try something and hope that it works.
To do it properly you should ensure that magic quotes is disabled and only escape data when necessary, using precisely the correct escaping method - no more, no less.
There are some problems with it.
First you apply functions on types that doesn't need them, your integers for example needs only a (int) cast to be secure.
Second you do not secure lenght, when you're requesting a '12 chars string' it would be a good idea to ensure you've got only 12 chars, and not 2048. Limiting size is really something your attackers will not like.
Third in your foreach loop you have a $v variable, you assign 3 times a function on $v to $_POST[$k]. So the 1st two assignements are lost when the 3rd occurs...
Then all the things previous people said are right :-)
The rule is apply the filter at the right moment for the right output. HTML output need an html filter (htmlspecialchars), but the database doesn't need it, it need a database escaping. Let's say you want to extract data from your database to build a CSV or a PDF, HTML escaping will make you life harder. You'll need CSV escaping at this time, or PDF escaping.
Finally it is effectively hard to remember if you are manipulating a data which is already well escaped for your output. And I recommend you an excellent read on Joel on Software about Apps Hungarian. The text is quite long, but very good, and the web escaping sequence is used as an example on why Apps Hungarian is good (even if System Hungarain is bad).
Hi this is my first answer for any question asked on web so please review it.
Put this code in top of your script and no need to assign these posted values to any variables for doing the same job of making the input data safe for database. Just use $_POST values as it is in your query statements.
foreach ($_POST as $k => $v) {
if(!is_array($_POST[$k]) ) { //checks for a checkbox array & so if present do not escape it to protect data from being corrupted.
if (ini_get('magic_quotes_gpc')) {
$v = stripslashes($v);
}
$v = preg_replace('/<.*>/', "", "$v"); //replaces html chars
$_POST[$k]= mysql_real_escape_string(trim($v));
}
}
Don't forget $_GET[]
if ($_POST OR $_GET)
Also you can add strip_tags()
I don't know whether your function is correct or not, but the principle is certainly incorrect. You want to escape only where you need to, i.e. just before you pass things into MySQL (in fact you don't even want to do that, ideally; use bound parameters).
There are plenty of situations where you might want the raw data as passed in over the HTTP request. With your approach, there's no ability to do so.
In general, I don't think it's that good of an idea.
Not all post data necessarily goes into MySQL, so there is no need to escape it if it doesn't. That said, using something like PDO and prepared statements is a better way, mysql_* functions are deprecated.
The regular expression could destroy a lot of potentially valid text. You should worry about things like HTML when outputting, not inputting. Furthermore, use a function like strip_tags or htmlspecilchars to handle this.
stripslashes is only necessary if magic quotes are enabled (which they shouldn't be, but always is possible)
When working with stripslashes I'd use get_magic_quotes_gpc():
if (get_magic_quotes_gpc()) {
$_POST[$k]=stripslashes($v);
}
Otherwise you'll over-strip.

Categories