Security - Die or replace on invalid value for include - php

I would like to know which of the following solutions is more secure.
if(!ctype_alpha($_GET['a'])){
//another string can be put here if necessary
die('No Hacking!');
}
or
if(!ctype_alpha($_GET['a'])){
//Changed for security in depth, in-case I accidently use $_GET['a'] elsewhere. Designed to simulate header('Location: ./?a=default_value');
$_GET['a'] = 'default_value';
}
something similar to the following happens later in the script:
//make_safe is defined elsewhere, it is security in depth (redundancy) to remove slashes if they get past ctype_alpha using some unknown bug
$var = make_safe($_GET['a']);
require_once("./data/include/$var.php");
In a book I am currently reading, it says that it is best to stop all input not following my rules, instead of correcting. Therefore, my question boils down to does replacing the $_GET['a'] with a default parameter count as stopping the input, or must die() be used?

Die('fu') is a dirty thing.
I prefer your way of sanitizing inputs with default values if needed.
By the way, that's what does major companies (check at google, search something, go to page 2, now change start parameter in the url to something not numeric, you'll be back to page 1).
Plus, when hacking stuff, you'll try to have the application acting in a singular way.
If yours acts always the same, it's very frustrating for hackers, they'll hopefully feel bored quite quickly.

Related

In php, using GET command for same parameter multiple times and php tags

First of all, I heard some web-servers allow you to reach parameter with $a instead of $_GET[a], this is not the case here.
Anyway, I have to reach a multiple times, so instead of doing $a = $_GET[a], I instead use $_GET[a] everytime. In single php tag as in <?php ?>, is that an issue, should I absolutely use variables? does it matter?
Another thing is my php file is really scrambled in my html, I wonder if does it matter with multiple gets?(should not, im just worried)
Thanks.
What you refer of using just $a instead of $_GET['a'] (or $_POST['a'] too) is an old feature known as register_globals. This feature was dangerous and leading to messy code, so it was considered deprecated in PHP 5.3 and finally removed in PHP 5.4.
Then, using $_GET['a'] everywhere in your scripts may lead to problems, because you should never trust user input (all things coming from $_GET, $_POST, $_REQUEST, $_COOKIE and some from $_FILES or $_SERVER). It is recommended to do something like $a = sanitize($_GET['a']); (the sanitize function does not exist, depending on what type of value are you expecting, you should check that what you get is an integer, or a valid date, or whatever, depending on your needs). From now on you should stop referencing $_GET['a'] and use instead the new sanitized variable you have just created $a. Because if you were using always $_GET['a'], chances are that you forget to sanitize it someplace.
Also, before sending this sanitized variable into a SQL query, you should escape it or use it inside a prepared statement to avoid SQL injections. Before outputting it to an html for the user to see, use htmlspecialchars to avoid XSS attacks.
And finally, about having multiple php blocks mixed with html blocks, this is only bad for maintenance reasons, because in the long run it will be a complete mess. Try to separate the html you send the user from the php code. Try to read something about the MVC pattern (Model-View-Controller) (this link is probably too complicated or maybe you don't see the utility right now for you that are just beginning with php (at least I didn't see how it was way better than mixing html with php, for all the complexity needed), but try to grasp the idea behind it) .
First of all, I heard some web-servers allow you to reach parameter with $a instead of $_GET[a], this is not the case here.
This is a PHP config setting called register_globals. It is insecure and should NOT be used. See this question for more information.
You can access an element in the $_GET array as many times as you like, it will not cause problems. However if you are printing an element of the $_GET array (or any other user submitted data) to the page, you should run it through htmlspecialchars() or the like before printing it out to prevent XSS vulnerabilities.
using a variable is a preference for you to decide it does not matter. but variable is the way forward if you use the same one multiple times.
<?php echo htmlspecialchars($_GET['a']);?>
using a variable means that it reusable again especially if you have added extra code, which mean just editing one variable for all instances.
<?php $a = htmlspecialchars($_GET['a']);
echo $a;
echo $a;
echo $a;
echo $a;
?>

Is it a bad practice to use a GET parameter (in URL) with no value?

I'm in a little argument with my boss about URLs using GET parameters without value. E.g.
http://www.example.com/?logout
I see this kind of link fairly often on the web, but of course, this doesn't mean it's a good thing. He fears that this is not standard and could lead to unexpected errors, so he'd rather like me to use something like:
http://www.example.com/?logout=yes
In my experience, I've never encountered any problem using empty parameters, and they sometimes make more sense to me (like in this case, where ?logout=no wouldn't make any sense, so the value of "logout" is irrelevant and I would only test for the presence of the parameter server-side, not for its value). (It also looks cleaner.)
However I can't find confirmation that this kind of usage is actually valid and therefore really can't cause any problem ever.
Do you have any link about this?
RFC 2396, "Uniform Resource Identifiers (URI): Generic Syntax", §3.4, "Query Component" is the authoritative source of information on the query string, and states:
The query component is a string of information to be interpreted by
the resource.
[...]
Within a query component, the characters ";", "/", "?", ":", "#",
"&", "=", "+", ",", and "$" are reserved.
RFC 2616, "Hypertext Transfer Protocol -- HTTP/1.1", §3.2.2, "http URL", does not redefine this.
In short, the query string you give ("logout") is perfectly valid.
A value is not required for the key to have any effect. It doesn't make the URL any less valid either, the URL RFC1738 does not list it as required part of the URL.
If you don't really need a value, it's just a matter of preference.
http://example.com/?logout
Is just as much a valid URL as
http://example.com/?logout=yes
All difference that it makes is that if you want to make sure that the "yes" bit was absolutely set, you can check for it's value. Like:
if(isset($_GET['logout']) && $_GET['logout'] == "yes") {
// Only proceed if the value is explicitly set to yes
If you just want to know if the logout key was set somewhere in the URL, it would suffice to just list the key with no value assigned to it. You can then check it like this:
if(isset($_GET['logout'])) {
// Continue regardless of what the value is set to (or if it's left empty)
It's perfectly fine, and won't cause any error. Though, nowadays most frameworks are MVC based, so in the URL you need to mention a controller and an action, so it looks more like /users/logout (BTW, also StackOverflow uses that URL to log users out ;).
The statement that it may cause errors to me sounds like your applications manually access the raw $_GET, and I definitely think that building apps without a framework (which usually provides an MVC stack and a router/dispatcher) is the real dangerous thing here.

Sanitizing global arrays in PHP

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.

PHP Injection from HTTP GET data used as PHP array key value

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.

Should you verify parameter types in PHP functions?

I'm used to the habit of checking the type of my parameters when writing functions. Is there a reason for or against this? As an example, would it be good practice to keep the string verification in this code or remove it, and why?
function rmstr($string, $remove) {
if (is_string($string) && is_string($remove)) {
return str_replace($remove, '', $string);
}
return '';
}
rmstr('some text', 'text');
There are times when you may expect different parameter types and run different code for them, in which case the verification is essential, but my question is if we should explicitly check for a type and avoid an error.
Yes, it's fine. However, php is not strongly typed to begin with, so I think this is not very useful in practice.
Additionally, if one uses an object other than string, an exception is a more informative; therefore, I'd try to avoid just returning an empty string at the end, because it's not semantically explaining that calling rmstr(array, object) returns an empty string.
My opinion is that you should perform such verification if you are accepting input from the user. If those strings were not accepted from the user or are sanitized input from the user, then doing verification there is excessive.
As for me, type checking actual to data, getted from user on top level of abstraction, but after that, when You call most of your functions you already should now their type, and don't check it out in every method. It affects performance and readability.
Note: you can add info, which types is allowed to arguments for your functions by phpDoc
It seems local folks understood this question as "Should you verify parameters" where it was "Should you verify parameter types", and made nonsense answers and comments out of it.
Personally I am never checking operand types and never experienced any trouble of it.
It depends which code you produce. If it's actually production code, you should ensure that your function is working properly under any circumstances. This includes checking that parameters contain the data you expect. Otherwise throw an exception or have another form of error handling (which your example is totally missing).
If it's not for production use and you don't need to code defensively, you can ignore anything and follow the garbage-in-garbage-out principle (or the three shit principle: code shit, process shit, get shit).
In the end it is all about matching expectations: If you don't need your function to work properly, you don't need to code it properly. If you are actually relying on your code to work precisely, you even need to validate input data per each unit (function, class).

Categories