Does this protect against injection attacks? - php

Does this protect against SQL injection attacks?
function sanitize($value) {
// Stripslashes
if (is_array($value)) {
if (get_magic_quotes_gpc()) {
$value = array_map("stripslashes", $value);
}
$value = array_map("mysql_real_escape_string", $value);
} else {
if (get_magic_quotes_gpc()) {
$value = stripslashes($value);
}
$value = mysql_real_escape_string($value);
}
return $value;
}
$_REQUEST = array_map('sanitize', $_REQUEST);
$_GET = array_map('sanitize', $_GET);
$_POST = array_map('sanitize', $_POST);
$_COOKIE = array_map('sanitize', $_COOKIE);
What could I add to sanitize() to protect against cross-site scripting?
What other channels would allow attackers to insert malicious code?

The one-word answer would be "yes". However:
If $value is an array that contains other arrays it won't be handled correctly. You should loop over $value make a recursive call to sanitize for each array you find.
It's preferable to use prepared statements instead of doing this. Of course, if you already have a complete application and are not building from scratch this can be problematic.
Finally, the other ways in which someone can subvert your application are cross-site scripting (aka CSS or XSS) and cross-site request forgeries (CSRF). There are lots of resources here on SO and on the internet you can use to get up to speed. As a starting point, protection against XSS involves calling htmlspecialchars on anything you output, while protection against CSRF involves requiring a session-specific id code for each operation your privileged users are allowed to perform on your site.
Array-safe sanitize version
function sanitize($value) {
if (is_array($value)) {
foreach($value as &$item) {
$item = sanitize($item);
}
} else {
if (get_magic_quotes_gpc()) {
$value = stripslashes($value);
}
$value = mysql_real_escape_string($value);
}
return $value;
}
Update:
For higher visibility: Bjoern's link to this question ( What's the best method for sanitizing user input with PHP? ) is really good.

No.
Use PHP Data Objects Or... Use a Database Abstraction Layer Or... Some framework that does this.
Don't write your own because:
Someone else has
Their code works fine
You can use their code for free
They thought of all the issues you don't know about yet.
It's a lot of work to do this, it's already been done, just spend twenty minutes and figure out someone else's code that does this.

If it is applied after the database connection was established, then it escapes the initial input data correctly.
Now you will have problems using such escaped values for HTML output however. And it does not protect against second order SQL injection (querying the database, then using those values as-is for a second query). And more importantly, most applications work on the input values. If you do any sort of rewriting or string matching, you might undo some of the escaping.
Hencewhy it is often recommended to apply the escaping right before the query is assembled. Nevertheless, the code itself is functional for the general case and advisable if you can't rewrite heaps of legacy code.

You should add html_entities. Most of the time you put $_POST variables into a textbox, like:
<textarea><?php echo $_POST['field']; ?></textarea>
They can mess up your HTML by filling in and do anything they want.

Related

PHP changing post data before use it

I am modifing an open source tool. I can not find all the function in the scripts. So i planned include my own script to all pages by htacces. I want to clean post data for SQL Injections. So i added this code to my own script:
foreach($_POST as $key=>$value)
{
$_POST[$key] = str_replace('bad chars for injections', '', $value);
}
foreach($_GET as $key=>$value)
{
$_GET[$key] = str_replace('bad chars for injections', '', $value);
}
foreach($_REQUEST as $key=>$value)
{
$_REQUEST[$key] = str_replace('bad chars for injections', '', $value);
}
This can change post values. The tool can use only cleaned data. But if the tool use file_get_contents('php://input') function, it can see original post data. So i can not trust the tool if it use some way like this.
Is there a way to change these input before use by the tool? I mean override function actually.
No. This should be completely avoided at all costs.
Use prepared statements instead. From the PHP documentation:
If an application exclusively uses prepared statements, the developer can be sure that no SQL injection will occur.
If you're not sure how to use prepared statements, there are plenty of guides on the web. For example:
https://phpdelusions.net/pdo#prepared
http://www.w3schools.com/php/php_mysql_prepared_statements.asp
http://wiki.hashphp.org/PDO_Tutorial_for_MySQL_Developers

how to clean POST and GET vars in PHP for XSS and SQL injection

In my web app is a config file which includes i.e. database connection settings ans is always loaded at the first line of a PHP script. I would like to include a function which cleans all POST and GET data for maybe existing XSS and SQL Injection risks.
I am not sure if that function is really enough
function make_safe($variable)
{
$variable = strip_tags(mysql_real_escape_string(trim($variable)));
return $variable;
}
foreach ($_POST as $key => $value) {
$_POST[$key] = make_safe($value);
}
//Same for $_GET & $_SESSION
Do you have recommendation for this problem?
This function:
function make_safe($variable)
{
$variable = strip_tags(mysql_real_escape_string(trim($variable)));
return $variable;
}
Will not work
SQL injection and XSS are two different beasts. Because they each require different escaping you need to use each escape function strip_tags and mysql_real_escape_string separatly.
Joining them up will defeat the security of each.
Use the standard mysql_real_escape_string() when inputting data into the database.
Use strip_tags() when querying stuff out of the database before outputting them to the screen.
Why combining the two function is dangerous
From the horses mouth: http://php.net/manual/en/function.strip-tags.php
Because strip_tags() does not actually validate the HTML, partial or broken tags can result in the removal of more text/data than expected.
So by inputting malformed html into a database field a smart attacker can use your naive implementation to defeat mysql_real_escape_string() in your combo.

How to properly check user input in php?

I have a function that checks user input and wanted to know if it prevents against all attacks of this sort. Also, if I wanted to include this function on each page that needed it could I put it in a php page of its own then 'include()' it into them pages where it's required. Thanks.
function secure_data($value)
{
if (get_magic_quotes_gpc()) {
$value = stripslashes($value);
}
if (function_exists("mysql_real_escape_string" )) {
$value = mysql_real_escape_string($value);
} else {
$value = addslashes($value);
}
return $value;
}
Since you're using quotes, I'm assuming that your main question is how to protect against SQL injections, if I'm not mistaken. (Note: securing against SQL-injection is something else then securing against for example Cross Site Scripting!); and will not guarantee you a secure application.
The best solution for SQL injection is not to use this function, but to use prepared statements with either mysqli or PDO.
(See: How can I prevent SQL injection in PHP? )
Other interesting links:
Background information on sql injection:
https://www.owasp.org/index.php/SQL_Injection
Other validation:
http://www.faqs.org/docs/gazette/superglobals.html
Input validation from OWASP:
https://www.owasp.org/index.php/Input_Validation

PHP function to sanitize all data

Is it a good, or stupid idea to sanitize all the data that could be sqlinjected? I wrote a function that should do it, but I've never seen it done and was wondering if it was a poor idea.
The function I wrote:
function sanitizeData()
{
$_SERVER['HTTP_USER_AGENT'] = mysql_real_escape_string($_SERVER['HTTP_USER_AGENT']);
foreach(array_keys($_COOKIE) as $key)
{
$_COOKIE[$key] = mysql_real_escape_string($_COOKIE[$key]);
}
foreach(array_keys($_POST) as $key)
{
$_POST[$key] = mysql_real_escape_string($_POST[$key]);
}
foreach(array_keys($_GET) as $key)
{
$_GET[$key] = mysql_real_escape_string($_GET[$key]);
}
}
A bad idea; this is basically another version of the deprecated magic_quotes. Most of that data probably won't end up going into the database, so you'll end up escaping unnecessarily, and potentially double-escaping.
Instead, use prepared statements as needed. Look at mysqli_stmt (part of mysqli) and PDOStatement (part of PDO).
It is also very important to understand that mysql_real_escape_string do not sanitize anything.
By applying this function you do not make any data safe. That's very widespread misunderstanding.
This function merely escaping string delimiters. So, it works only for strings, quote delimited ones.
Thus, real sanitization could be only like this:
$_GET[$key] = "'".mysql_real_escape_string($_GET[$key])."'";
And even this one isn't suffice.
But as already Matt mentioned it would be very bad practice. And even more: as a matter of fact, not only input data should be properly formatted/paramertized. It's database function, not user input one! It has nothing to do with user input. Some data may come not from user input but from a file or other query or some service - it all should be properly formatted as well. That's very important to understand.
Also you are using an odd way to iterate arrays.
this one is more common:
foreach($_GET as $key => $value)
{
$_GET[$key] = mysql_real_escape_string($value);
}

What risks are there in using extracted PHP superglobals?

There is some risk in using the function extract in the superglobal variables as $_POST and $_GET, I work of the following way.
There is risk of SQL INJECTION or there is an alternative to extract
if(get_magic_quotes_gpc()) {
$_GET = stripslashes($_GET);
$_POST =stripslashes($_POST);
}
function vars_globals($value = '') {
if(is_array($value))
$r = &$value;
else
parse_str($value, $r);
return $r;
}
$r = vars_globals($_GET);
extract($r, EXTR_SKIP);
Yes there is a risk. You don't want to blindly import user input into your symbol table. You should take the time to validate and/or sanitize user input. The filter_var function can help with this.
When inserting into a database, use the driver's escape mechanism to eliminate the possibility of injection. If you're using mysql_* functions, you'd use mysql_real_escape_string. However, it is much better to use PDO and parameterized queries for this.

Categories