i'm pretty new to Javascript and PHP so please bear with me if i'm asking some really dumbed down questions.
Ok, say i need to use values stored in a PHP $_GET or $_SESSION, is it advisable to just do something like
var something = PHP echo $_SESSION or $_GET
You need to make the data safe for JavaScript to parse. var something = <?php echo $SESSION['foo']; ?> would work if it is a number. If it was a string you need to add quotes. If the string contains special characters then they need to be escaped, etc.
Running the data through json_encode is a good way to make it JavaScript safe.
Since $_GET is user entered data, you can't know that it is a number without checking, so if you don't make things safe then you have a huge XSS hole. Even if you do, then what you do with the data in JavaScript afterward could sill expose you to XSS.
Putting this as an answer for the code formatting, but...
#luhiz: think of what happens you're inserting data into a javascript block that contains javascript "meta characters". Let's say you're passing a person's full name as a query parameter, like this:
http://example.com/index.php?name=John+O'toole
In PHP, you'll have:
$_GET['name'] = "John O'toole";
and when you place it into the javascript block, you'll get:
var name = John O'toole;
Now you've got a few problems:
You've inserted raw user-hackable data into your page
A javascript syntax error as your string is not enclosed in quotes
Another syntax error as the name contains a single quote, which begins a string which is then not terminated with another quote.
Discussion:
This is a classic XSS (cross-site-scripting) attack. You're placing user-provided data into an html page without any safety. The simplest attack example is to use http://example.com/index.php?name=alert("you've been hacked!");. Try it and see what happens.
2&3: By using json_encode, PHP automatically converts whatever you're encoding into syntactically safe Javascript. This doesn't mean it's "safe" code - it can still contain malicious data. But it will not cause a syntax error when the page is loaded by the client browser. So by doing:
var name = <?php echo json_encode($_GET['name']);
you'll get something like:
var name = "John O'toole";
which the javascript interpreter will accept without any complaints.
Related
I have an important question, and I don't know what to search for, so I'm asking you guys for help.
Do I need to escape this kind of code:
<?php if(isset($_GET['hk']) && $_GET['hk'] == "loginerror") { echo "error"; } ?>
(the result will be something like index.php?hk=loginerror)
Or should I leave it un-escaped? Can hackers "hack" if I don't use escape?
Thanks.
You need to escape (or encode, depending on context) special characters in user input when you use it in generated code or data formats (e.g. if you put it in an SQL query, an HTML document, a JSON file, etc).
If you are just comparing it to a string or seeing if it exists, there is no point in escaping it.
It is always good practice to filter or escaping your string when sending information to limit hackers of finding any security flaws.
Furthermore, never use the $_GET method when sending sensitive information over the net, rather use the $_POST method.
Using the $_GET methods shows which variable are being parsed and this information could be very very important and influential to a hacker
NO.
You shouldn't escape not a single $_GET array at all.
I'm trying to find the best way to sanitize requests in PHP.
From what I've read I learned that GET variables should be sanitized only when they're being displayed, not at the beginning of the "request flow". Post variables (which don't come from the database) either.
I can see several problems here:
Of course I can create functions sanitizing these variables, and by calling something like Class::post('name'), or Class::get('name') everything will be safe. But what if a person who will use my code in the future will forget about it and use casual $_POST['name'] instead of my function? Can I provide, or should I provide a bit of security here?
There is never a one-size-fits-all sanitization. "Sanitization" means you manipulate a value to conform to certain properties. For example, you cast something that's supposed to be a number to a number. Or you strip <script> tags out of supposed HTML. What and how exactly to sanitize depends on what the value is supposed to be and whether you need to sanitize at all. Sanitizing HTML for whitelisted tags is really complex, for instance.
Therefore, there's no magic Class::sanitize which fits everything at once. Anybody using your code needs to think about what they're trying to do anyway. If they just blindly use $_POST values as is, they have already failed and need to turn in their programmer card.
What you always need to do is to escape based on the context. But since that depends on the context, you only do it where necessary. You don't blindly escape all all $_POST values, because you have no idea what you're escaping for. See The Great Escapism (Or: What You Need To Know To Work With Text Within Text) for more background information on the whole topic.
The variables are basically "sanitized" when PHP reads them. Meaning if I were to submit
"; exec("some evil command"); $blah="
Then it won't be a problem as far as PHP is concerned - you will get that literal string.
However, when passing it on from PHP to something else, it's important to make sure that "something else" won't misinterpret the string. So, if it's going into a MySQL database then you need to escape it according to MySQL rules (or use prepared statements, which will do this for you). If it's going into HTML, you need to encode < as < as a minimum. If it's going into JavaScript, then you need to JSON-encode it, and so on.
You can do something like this... Not foolproof, but it works..
foreach($_POST as $key => $val)
{
//do sanitization
$val = Class::sanitize($val);
$_POST[$key] = $val;
}
Edit: You'd want to put this as close to the header as you can get. I usually put mine in the controller so it's executed from the __construct() automagically.
Replace the $_POST array with a sanitizer object which is beheaving like an array.
i would like to know if there is a possible injection of code (or any other security risk like reading memory blocks that you weren't supposed to etc...) in the following scenario, where unsanitized data from HTTP GET is used in code of PHP as KEY of array.
This supposed to transform letters to their order in alphabet. a to 1, b to 2, c to 3 .... HTTP GET "letter" variable supposed to have values letters, but as you can understand anything can be send to server:
HTML:
http://www.example.com/index.php?letter=[anything in here, as dirty it can gets]
PHP:
$dirty_data = $_GET['letter'];
echo "Your letter's order in alphabet is:".Letter2Number($dirty_data);
function Letter2Number($my_array_key)
{
$alphabet = array("a" => "1", "b" => "2", "c" => "3");
// And now we will eventually use HTTP GET unsanitized data
// as a KEY for a PHP array... Yikes!
return $alphabet[$my_array_key];
}
Questions:
Do you see any security risks?
How can i sanitize HTTP data to be able use them in code as KEY of an array?
How bad is this practice?
I can't see any problems with this practice. Anything you... errr... get from $_GET is a string. It will not pose any security threat whatsoever unless you call eval() on it. Any string can be used as a PHP array key, and it will have no adverse effects whatsoever (although if you use a really long string, obviously this will impact memory usage).
It's not like SQL, where you are building code to be executed later - your PHP code has already been built and is executing, and the only way you can modify the way in which it executes at runtime is by calling eval() or include()/require().
EDIT
Thinking about it there are a couple of other ways, apart from eval() and include(), that this input could affect the operation of the script, and that is to use the supplied string to dynamically call a function/method, instantiate an object, or in variable variables/properties. So for example:
$userdata = $_GET['userdata'];
$userdata();
// ...or...
$obj->$userdata();
// ...or...
$obj = new $userdata();
// ...or...
$someval = ${'a_var_called_'.$userdata};
// ...or...
$someval = $obj->$userdata;
...would be a very bad idea, if you were to do it with sanitizing $userdata first.
However, for what you are doing, you do not need to worry about it.
Any external received from GET, POST, FILE, etc. should be treated as filthy and sanitized appropriately. How and when you sanitize depends on when the data is going to be used. If you are going to store it to the DB, it needs to be escaped (to avoid SQL Injection. See PDO for example). Escaping is also necessary when running an OS command based on user data such as eval or attempting to read a file (like reading ../../../etc/passwd). If it's going to be displayed back to the user, it needs to be encoded (to avoid html injection. See htmlspecialchars for example).
You don't have to sanitize data for the way you are using it above. In fact, you should only escape for storage and encode for display, but otherwise leave data raw. Of course, you may want to perform your own validation on the data. For example, you may want dirty_data to be in the list of [a, b, c] and if not echo it back to the user. Then you would have to encode it.
Any well-known OS is not going to have a problem even if the user managed to attempt to read an invalid memory address.
Presumably this array's contents are meant to be publicly accessible in this way, so no.
Run it through array_key_exists()
Probably at least a little bad. Maybe there's something that could be done with a malformed multibyte string or something that could trigger some kind of overflow on a poorly-configured server... but that's pure (ignorant) speculation on my part.
I'm using jQuery to check to see if a username is taken. My issue is that $.post seems to escape anything. For example, I use this:
$.post("http://mywebsite.com/check_username.php", {
"username": $("#username_txt").val()
}, function(data, textstatus, xmlhttp){
// do stuff
});
to send the username to the page check_username.php, which is roughly,
$username = mysql_real_escape_string($_POST["username"]);
echo $username; // show the perceived username
echo mysql_query("SELECT * FROM users WHERE username=\"".$username."\";") === false ? 1 : 0;
If the username in the input field is "bob" (with the quotation marks), the return from the data will be \\\"bob\\\"0. Without the mysql_real_escape_string, it reads \"bob\". If I dare to leave it like that, then potential attackers could easily inject SQL code into my application.
I haven't seen anything on the jQuery documentation on get and post about this, so I'm not sure how to stop this. Barring not using jQuery for my ajax, how do I fix this?
You'll have to strip out the magic quotes that PHP automatically adds to $_GET, $_POST, and $_COOKIE data. That deprecated feature can be disabled if all your PHP code properly escapes strings before inserting them into HTML, SQL, command lines, etc.
Have you tried the processData property for $.ajax?
http://api.jquery.com/jQuery.ajax/
Composing SQL directly with user-generated text is suicidal. See here if you don't understand why.
Composing SQL with mysql_real_escape_string applied to user-generated text is a poor idea, as it makes the queries difficult to optimize (although compared to not using mysql_real_escape_string at all it's like jabbing yourself in the neck with a sharp pencil compared to jabbing yourself in the neck with a running chainsaw)
Maybe maghic_quotes_gpc config parameter is set to on in the PHP.ini file.
If you have access to that file change the value to off.
If you don't have access then use get_magic_quotes_gpc function to see if magic_quotes is "on" if it is not then call the mysql_real_escape_string function else bypass it.
I'm wondering if there is a quick and easy function to clean get variables in my url, before I work with them.( or $_POST come to think of it... )
I suppose I could use a regex to replace non-permitted characters, but I'm interested to hear what people use for this sort of thing?
The concept of cleaning input never made much sense to me. It's based on the assumption that some kinds of input are dangerous, but in reality there is no such thing as dangerous input; Just code that handles input wrongly.
The culprit of it is that if you embed a variable inside some kind of string (code), which is then evaluated by any kind of interpreter, you must ensure that the variable is properly escaped. For example, if you embed a string in a SQL-statement, then you must quote and escape certain characters in this string. If you embed values in a URL, then you must escape it with urlencode. If you embed a string within a HTML document, then you must escape with htmlspecialchars. And so on and so forth.
Trying to "clean" data up front is a doomed strategy, because you can't know - at that point - which context the data is going to be used in. The infamous magic_quotes anti-feature of PHP, is a prime example of this misguided idea.
I use the PHP input filters and the function urlencode.
Regular expressions can be helpful, and also PHP 5.2.0 introduced a whole filter extension devoted to filtering input variables in different ways.
It's hard to recommend a single solution, because the nature of input variables is so... variable. :-)
I use the below method to sanitize input for MYSQL database use. To summarize, iterate through the $_POST or $_GET array via foreach, and pass each $_POST or $_GET through the DBSafe function to clean it up. The DBSafe could easily be modified for other uses of the data variables (e.g. HTML output etc..).
// Iterate POST array, pass each to DBSafe function to clean up data
foreach ($_POST as $key => $PostVal) {
// Convert POST Vars into regular vars
$$key=DBSafe($PostVal);
// Use above statement to leave POST or GET array intact, and use new individual vars
// OR, use below to update POST or GET array vars
// Update POST vars
$_POST[$key]=DBSafe($PostVal);
}
function DBSafe($InputVal) {
// Returns MySQL safe values for DB update. unquoted numeric values; NULL for empty input; escaped, 'single-quoted' string-values;
if (is_numeric($InputVal)) {
return $InputVal;
} else {
// escape_string may not be necessary depending on server PHP and MySQL (i.e. magic_quotes) setup. Uncomment below if needed.
// $InputVal=mysql_escape_string($InputVal);
$InputVal=(!$InputVal?'NULL':"'$InputVal'");
return $InputVal;
}
}