PHP: Known Vulnerabilites with 'Notice: Undefined index: VARIABLE' [duplicate] - php

This question already has answers here:
Why should I fix E_NOTICE errors?
(5 answers)
Closed 8 years ago.
Sorry if already been explained elsewhere, I have searched and searched and not found the answer.
Initially, seeing this Notice makes me want to fix it, but upon reflection - what harm can come from it?
In the example below, how could someone Maliciously take advantage?
If they couldn't perhaps someone could give me an example where this 'Undefined index' notice may cause problems?
if($_GET['action']=="update"){ ~code~ }
I know the above example could be fixed with as simple as using 'isset', but I have other areas with Notices such as the below revolving around a form with the code similar to:
print "<input value='".$_POST['value']."'>";
Is there any possibility of an advanced user to use a vulnerability?

A notice isn't a warning about a security issue. It helps preventing an error in your logic. You're asking for this index, but it does not exist :
Should it exist ? Why haven't you set it before ?
Has it been deleted ? Why ? Should you still be able of accessing it ?
Has the key changed ? Why haven't you
taken that change into account when calling action ?
This is just PHP being nice : this doesn't exist, I'll initialise it, but weren't you expecting me to find something ?
Keep in mind that PHP is a very lax. It's meant to create applications quickly, keeping the programmer focused on the logic, not the details. Notices (recently implemented) are a way to make the logic cleaner, without stopping the whole program at the first little mistake.
Of course, this is a very good habit : fix all your warnings, errors and notices, to make sure your logic acts exactly how you want it to. Computers are stupid, that's a fact. They will always do as you ask, even when you ask them silly things.

In general: if somebody can see your PHP messages (no matter notices/warnings) - he will know then some information about your script: possibly, it's structure, used variables and parameters names e t.c. - i.e. such kind of information that in normal case should not be seen. With that information it's much more easier to perform some harmful actions.
However, it's not only about security. Having notices in any case indicates that something possibly went wrong - and your attention should be at that points. My suggestion is: you should write code, which will not produce notices/warnings with any error level.

An undefined index error is not related to security issues. What it means is that you have not properly initialized a variable before using it in an expression. Regardless of the security implications you should fix it because it means your code is incorrect.
Now back to your initial concern, any data that comes from user input should be sanitized before storing in a database. There are various techniques you can employ. These range from type casting to escaping data with functions like mysqli_real_escape_string() and strip_tags() to using prepared statements. You should read up on this topic. Data sanitization isn't a "one-size-fits-all" kind of thing. Different strategies can be used depending upon the nature of the data and how you're using it.

Related

"Do not Access Superglobal $_REQUEST Array Directly." Netbeans 8.0 PHP

This questions is being asked after having read a few others.
Do not access superglobal $_GET array directly
“Do not Access Superglobal $_SERVER Array Directly” on Netbeans 7.4 for PHP
Why is filter_input() incomplete?
I have loaded up the latest version Netbeans 8.0 and I have seen a warning
Do not Access Superglobal $_REQUEST Array Directly.
Great, I am happy to be shown when I am doing something which can be improved upon, so I look at the hints.
The suggestion is quite simple.
Use some filtering functions instead (e.g. filter_input(), conditions
with is_*() functions, etc.).
So I start looking into fliter_input() however it is not yet implemented for $_REQUEST. This seems like a little bit of a dead end.
Then I read something which was quite helpful from (#bobince) "At the start of your script when you're filtering, you don't know where your input is going to end up, so you don't know how to escape it."
It reminded me, I know exactly where my input is going to end up, and exactly what it will be used for. So, I wanted to ask everyone if the approach I am going to take is essentially safe.
I am designing a REST-ish API and I am using $_SERVER['REQUEST_METHOD']; to determine the resource which needs to be returned. I am also using $_REQUEST['resource']; which should contain everything on the URI after /api/ following the .htaccess rewrite.
The questions I have about my approach are:
If I always validate $_SERVER['REQUEST_METHOD']; to be within the required GET PUT POST DELETE (which i will need to do anyway), is there really a problem not filteing the input?
Should I be accessing the $_REQUEST['resource']; by using filter_input (INPUT_GET, 'resource');? When this will only be used to determine a resource, and where the resource can not be determined (say someone attempts to add malicious code) we will simply not find a resource and return a 404 Not Found status.
Are there any other considerations I need to take into account and have I missed anything critical in my understanding?
I realise, this may seem like a lot of concern for what is only considered a warning however, in my experience, fixing just the errors will give you working code, but fixing the warnings will help you understand why the code works.
So I start looking into fliter_input() however it is not yet implemented for $_REQUEST. This seems like a little bit of a dead end.
I'd say it is not a dead end but on purpose. filter_input() requires you to clearly specify the input type. $_REQUEST is not clear about it, it contains input from various sources, allowing one source overwriting another.
Next to that this is also not what the warning precisely wants to tell you. Swapping a superglobal like $_GET with an equally superglobal function like filter_input(INPUT_GET, ...) shows the same design flaw. But Netbeans can't warn you as easily about it.
And getting rid of superglobals is already a good idea.
Instead, inject input data to your application at a low-level place, e.g. bootstrapping the request information and do not use any superglobals nor the filter_input function in the rest of your code.
That will allow you to easily simulate any request method without even having an actual request.

Simulated Ruby symbols in PHP

Ruby and some other languages have a very convenient feature: symbols. They look like in-place constants. Now I wonder if the following approach by simulating symbols in PHP with an at sign before an unquoted string is a valid approach.
$array = [#key => "value"];
echo sprintf("%s PHP symbols with a %s\n", #testing, $array[#key]);
I understand there are certain drawbacks against formal constants and the like, which are same as for Ruby's symbols: consider typing errors. Are there any other considerations against using this approach?
If by "valid" you mean "can be run", then yes, it is a valid approach (but by that standard, it is also valid to make all of your strings into HEREDOC's). But simply because PHP will accept the syntax, does not mean that the syntax is without problems.
The first I can think of are that
You are actively suppressing an error, which costs processing time
Your co-workers will need an explanation as to what is going on, which costs developer time
You are working against the natural definitions of the language (PHP simply isn't Ruby)
Since you have to use a sigil for variables anyway, you're not actually cleaning the code.
You are suppressing an error (a notice, to be exact). not only this costs processing time as mentioned in cwallenpoole's answer, but also the error is there for a reason. The reason is:
Notice: Use of undefined constant hello - assumed 'hello' in ...
You are relying on some constant being undefined - which is exactly what the notice is trying to tell you. If a constant of that name is defined, you will grab its value instead.
In Ruby, :__LINE__ is something quite different from __LINE__. The former is a symbol - it equals itself no matter where you use it. The latter is a number, and a magical variable that changes its value on every line. In PHP, #__LINE__ is the same as __LINE__, because there is no error to suppress. Oh, and there's one special "symbol" that is extra-fun to debug: #exit, AKA #die.
In Ruby, you can use all sorts of symbols including operators and keywords. These (and many more) are all valid: :+ :* :< :<< :[] :[]= :while :case :x=. With a pair of parentheses, you can even use symbols like :case= and :while=. In PHP, none of these work. You'll end up with a parse error. It won't even be suppressed. The only exception is #[] in PHP 5.4, which produces an empty array. On the other hand, lots of PHP expressions are not valid Ruby symbols: #(1+1) === #2 #1 == #'1'
Ruby's symbols are not equal to anything else. This is the purpose of their existence. Sure, they have some nice properites like to_s and to_proc, but their original purpose is to serve as identifiers separate from any possible user input. This is sorta nice for example if you are using symbols to represent tokens in a lexer stream, such as [:lparen, 1, :plus, "rparen", :rparen]. In PHP, undefined constants are strings. In Ruby, ?test != "test". In PHP #test === "test" (assuming you dindn't define a constant named "test" to equal something else).
you can't even assume non-magic constants won't change. You can't even attribute to malice what can be explained with bad coding. Nothing like that is of worry in Ruby:
//in library code:
$this->status = #done; // bad
//outside library code:
define('done', "no"); // very bad
define(#done, "yes"); // even worse
echo #no; // prints "yes"
//in library code:
if($this->status == #done){
//won't execute
}
echo #die;
echo "this won't get printed!";
You shouldn't rely on constants being undefined, and you shouldn't use error suppressing to hide the error messages telling you that. You shouldn't use special notation to pretend two things are not equal when they are. Also, can you trust the users of your library to not redefine constants at runtime?
Warning:
The following answer contains analogies that are meant, purely to illustrate a point. Under no circumstances do I mean to even suggest you contemplate the possibility of someone (you or anyone else) actually sitting down and doing the things I mention. That way madness lies
Though other answers have explained the main issue with using #<str>, It supressing a notice, it's important to stress this a bit more.
When using the supressing # (of death) the notice does not magically dissapear it is still being issued. After a while logs will get clogged with notices, making it harder to find that one fatal error that could be in there. Even if there is no fatal error, it still slows the code down.
Why encourage people to write code that throws notices? Just because you like the ruby syntax? come on, if you don't like a language, don't use it. I know: legacy code, you have to... well then, do it, don't try to make it feel and look like Ruby. They're not the same language. Everything that reminds you of the fact that you're working with a different language should be seen like a tool. Different languages require different mindsets, and different ways of thinking about a problem.
Imagine writing Lisp, but change the syntax to SQL queries. How much bad code will that generate. The syntax forces you into an SQL mindset, whereas you should be thinking in functions.
But for God's sake, don't that way madness lies!! It's a fools errand, it's even worse than parsing HTML with regex. It'll make even Cthulhu cry like a little girl
Oh, and # not being used to supress errors once it's in common usage? Do you really believe that? So you expect a lot of people to write bad code, until some IDE plugin is released that doesn't complain about the abuse of the # sign. And then, you expect the PHP contributors to take notice, and find a new operator to supress errors?
Honestly. I don't want to be rude, but that's like expecting Microsoft to release the source of windows8, because some people have gotten used to linux being open source.
Another thing: As I said, suppressing notices isn't going to help you when debugging the code. It's well known that PHP has way to many functions (and reserved keywords) in its core/global namespace. If you, and your co-workers get in the habit of abusing the # operator, you could just end up with code like this:
$foo[#die] = [#exit, #constant];
Have fun debugging that onholy mess of unclear errors. Honestly...
The key in your code would be seen by PHP as an unknown constant.
In most languages this would halt the compiler, but PHP mutates it into a string in an effort to keep running. It throws a warning, but keeps going anyway. This is just bad, and you really don't want to be doing it, much less doing it deliberately.
# in PHP is for suppressing errors. It does nothing else.
Your #key will still be bad practice just as key would be and would function in exactly the same way, but the # will hide the error message that would normally be generated.
Using # error suppression in PHP is bad practice for a whole bunch of reasons (‡ see note below), but using it as a way to hide deliberately bad code is terrible. Please don't do this.
The fundamental point here is that you're using PHP, so you should write PHP code. Trying to write Ruby code in PHP is never going to work.
You should work with the language you're using, not against it.
‡ For some thoughts on why error suppression is bad practice, you may want to read this: Suppress error with # operator in PHP
One final thought: This thing of PHP converting unknown constants to a string exists in the language purely for legacy compatibility reasons; it's one of the really awful bits of bad language design that date back to the early days. A lot of the other bad stuff from early PHP has been deprecated in recent versions; this hasn't yet, but there's no good reason for it still to exist, so I kinda hope they find a way to deprecate this "feature" too. If they do, that will instantly stop your idea from working, regardless of any merits it may have.

When PHP code should really be treated as unsafe?

Yesterday I took a part in interview for PHP developer postion. My job was to solve 15 questions quite simple test. One of the questions was to decide wether code similar to below should be treated as unsafe. I gave a wrong (as it turned out) answer and the argumentation from the other person on that interview was quite surprising (at least to me).
Code was something like that:
function someFunction($a)
{
echo $a * 4;
}
someFunction($_GET['value']);
Possible answers were:
always,
only when register_globals is enabled,
never.
You could get one point for correct answer and second one for giving good explanation (argumentation) on answer chosen answer.
My answer was third: this code is never unsafe. Plus argumentation: Because, this is just a simple equation. There are no file or database operations here, no streams, protocols, no nothing. It's just an equation. Nothing else. Attacker is unable to do anything wrong with PHP script, not matter how malformed URL query he or she will try to execute. No chance.
I've got zero points. Neither my answer was correct, nor my argumentation was accepted. The correct answer was: this code is always unsafe -- you should always escape, what you got from URL query.
My question is: Is this really good point of view? Do we really have to always use a rule of thumb, that anything taken directly from query is unsafe, if not filtered, escaped or secured in any other way? Does this means, that I teach my students an unsefe coding methodologies, becuase on very first PHP lecture they write a script for calculating a triangle area and they're using unescaped, unfiltered params from URL in their task?
I understand, that security and writing safe code should be a matter of highest priority. But, on the other hand, isn't that a little bit of safe-code-fascism (forgive me, if I offended someone) to threat any code unsafe, even it no one is able to do any harm with it?
Or maybe I'm completely wrong and you can do some harm on function that echoes times four, what you gave to it?
The issue is that later someone may change the function 'somefunction' and do more than simply multiply it by 4.
The function in itself is not unsafe, but the line:
someFunction($_GET['value']);
Is completely unsafe. Maybe someFunction gets refactored into another file or is way down in the code.
You should alway check and scrub user supplied data to protect yourself and others working on a library or function somewhere not caught not expecting you to pass them pure $_GET array data.
This is especially true when working with others and is why it's being asked in the interview--to see if your looking ahead at future potential issues, not to see that you understand that currently someFunction is harmless when pass possibly dangerous GET data. It's becomes an issue when your coworker refactors someFunction to query a DB table.
Having not spent much time playing with your code example, I won't say that it could be used to 'do harm' however, your function will not work properly unless it is passed some form of number. In the long run, it is better to escape your code, and handle erroneous data then wait for the day when an unsuspecting user puts the wrong type of value in your box and breaks things.
I'm sure that the company you were interviewing for was just looking for someone with a solid habit of making sure their code is complete and unbreakable.
NEVER trust anything that originates from a user. Just dont. Even when you cannot fathom a possibility of your code/class/package being misused, cover your own ass by ensuring the input to your product is exactly what you're expecting, no surprises. At the barest minimum, someone may supply bad input to that method just to screw with your app, to cause it to show an error or give the white screen of death. The code that does basic multiplication is a prime candidate for that kind of malevolence. It applies not just in PHP, but programming/design in general.

PHP 4 to PHP 5 - isset checks on boolean if statements

Scenario:
We are in the process of converting an application from PHP 4 to PHP 5. The application needs to be able to work on PHP 4 for a little while, which means no PHP 5 specific elements can be used, yet. We are simply trying to make sure the application works on both platforms.
There are a lot of conditionals that look like this in the application:
if ($variable) { // do something }
Some of these variables end up not being defined at all and we are trying to reduce the number of errors (there's a lot of them).
To solve these errors, we are adding checks in various areas like this:
if (!isset($variable)) $variable = "";
or
if (!empty($variable)) { // do something }
Question:
Does anyone know of a simpler approach to fixing these errors. The problem is that these variables are being used across files (via includes) and defining the variable may change the logical flow in that file if its doing a check like (if (!isset($variable)) { // do something }).
The point of this question is to reduce errors and time consumption of tracking each individual use of these variables. Currently, we are having to either examine thoroughly what the variable is doing (which may take a good chunk of time), or we are doing a "fire and forget" / hope-its-fixed method of correcting.
-- Edit --
Does anyone know of a program like cppcheck for php that could somehow reference these variables or create some kind of chaining that could find errors and link possible references? (I hope that makes sense.)
AFAIK there is a code-checker that looks for uninitialized variables which works OK. You can work through it's messages, it's called PHP Mess Detector and one of it's rule covers uninitialized variables. However this can never be perfect.
Another method is to track the error messages and use them to locate the places within in the code. I've done that in the past and it worked very well, just do it in iterations and keep log of the warnings.
You can also work with a whitelist and import whitelisted variables when the request starts. Non-whitelisted submissions need to cause an access violation error to have this properly working, so this way is more work than tracking warnings albeit it might make your application more secure.
Please see as well:
PHP Syntax checking pre-source control
E_NOTICE ?== E_DEBUG, avoiding isset() and # with more sophisticated error_handler
isset() and empty() make code ugly

Why should I check that an array key exists before trying to access it?

I have turned on error_reporting(E_ALL) and run this code:
$topic_id = (int) safe_query($_GET['top_id']);
if($topic_id > 0)
include("topic.php");
And get this error: Notice: Undefined index: top_id. Is it that bad what I do? If yes then why? Should I check if $_GET['top_id'] isn't empty before I give its value to $topic_id? Why? Thank you.
One of the reasons why I do it is to prevent unexpected behaviours.
Code should always reflect the intention of the programmer. If a behaviour depends on some mysterious process in the background, eventually it will come and bite you in the ass when you are knee deep within bugs and debugging.
Traditionally, attempt to access an array with a key that doesn't exist causes a crash (probably in unmanaged environment) or an error. PHP silently 'fixing' this in background is great for beginners, but bad for debugging. Your code will work, but may give you unexpected result.
Take for example, your code. Say the calling page forget to specify the top_id, or misspelt it as topid, and PHP goes on its merry way. It didn't include topic.php, and nothing happens. The code works fine. PHP doesn't complain. What's wrong?
Now, your code is short. What happens when it is longer? Nested deep within many lines, between different functionalities? For your case it isn't a big deal, but when doing complex array manipulation it will make debugging harder.
I understand the question now. I'd suggest using isset just to be safe. I'm assuming you don't have a topic_id that is 0.
It's not really a problem here, since you only take action on it if it's set anyway. However, you're just lucky that the unset value evaluates to false. Also, it'd be annoying to continue having it give you the warning. You'd probably be best suited by doing what others have suggested, checking if it's set before using it. It might be easiest to just set up a function that does that, especially if you're going to be checking a lot of GET parameters.
Whatever you do, don't just turn the warning level down to suppress the warning; in this case, it doesn't hurt to assign from the unset variable, but in the future it could indicate an actual error.
"And get this error ... Is it that bad what I do?"
Well, it's not giving you an Error. It's giving you a Notice. Notices are "ignored" (that is, not echoed) on production servers.
Essentially, PHP is telling you what Extrakun is saying in his answer. You should take notice to a potential mistake that could lead to a real error later.
So, "Is it that bad what I do?" ... maybe not. But, then again, PHP is also not giving you an error. It is giving you the right amount attention that the code segment deserves - a Notice.

Categories