PHP eval in eval cannot read predifined variables - php

Before I explain the issue, I know the risks of using eval, but there is no realy other way to do it on how my system is build, and it also is for a personal project only. (its a custom cms which when I publish it makes the physical files for me, I just made it though db so I don't need to upload files when not working remote and it is just easy).
Lets explain my issue, I have a main php file which handles all pages, all pages are stored in the db with code and all and is being executed through eval.
And the system also has a function include_db which basicly does the same as include from php normaly just from the db.
But when I access a variable defined in the first eval (main page) it can not be read out in the included eval from the db.
Weird thing is that functions can be read out though the second eval.
Any way to access variables normaly from the included eval that is being generated in the eval of the main page?
(I think it has to do because those variables are not global and its being executed in a function but I do not know a way to make every variable global :( )
Thanks in advance!
The code that is being evalled on the main page:
$skill = isset($_REQUEST['skill']) && is_string($_REQUEST['skill']) && isValidSkill($_REQUEST['skill']) ? $_REQUEST['skill'] : 'overall';
if(!isset($_REQUEST['player']))
include_db('highscore_overview');
else
include_db('highscore_player');
And inside the include of overview I dump the get_defined_vars() and that doesn't return the $skill I set before the include only the variables that are declared in the main index.php (database and such)

First of all a disclaimer: You should never ever execute code from a database. That is a big security risk. It means that whenever someone is successful in gaining access to your database (using sql-injection for example) is now also capable of executing arbitrary code in php by changing the code in your database. You really should not do that!
If you are using code from the database to implement custom (email-)templates, please consider using a templating-engine for that like twig. Most syntaxes of template-engines are built in a way that you cannot break out of them and execute arbitrary code like you could with raw php code.
That said, i now try to answer the original question (because i cannot stop you doing things you should not do anyways). In terms of variable-scope, eval behaves like a function. If you want the variables defined inside it global, you have to manually make every variable defined inside the eval global.
You can do that by append a code-snippet to every code executed in eval that takes every local (in eval defined) variable and writes it into global scope.
<?php
function include_db() {
# ... get $code from db here ...
# get's executed after code from db, globalizes all variables
$code .= ';foreach (get_defined_vars()) as $newGlobalName) {';
$code .= ' $GLOBALS[$newGlobalName] = $$newGlobalName;';
$code .= '}';
eval($code);
}

Related

How to know if a script was included inside another script

I am new to PHP and very likely I am using the incorrect approach because I am not used to think like a PHP programmer.
I have some files that include other files as dependencies, these files need to have global code that will be executed if $_POST contains certain values, something like this
if (isset($_POST["SomeValue"]))
{
/* code goes here */
}
All the files will contain this code section, each one it's own code of course.
The problem is that since the files can be included in another one of these files, then the code section I describe is executed in every included file, even when I post trhough AJAX and explicitly use the URL of the script I want to POST to.
I tried using the $_SERVER array to try and guess which script was used for the post request, and even though it worked because it was the right script, it was the same script for every included file.
Question is:
Is there a way to know if the file was included into another file so I can test for that and skip the code that only execute if $_POST contains the required values?
Note: The files are generated using a python script which itself uses a c library that scans a database for it's tables and constraints, the c library is mine as well as the python script, they work very well and if there is a fix for a single file, obviously it only needs to be performed to the python script.
I tell the reader (potential answerer) about this because I think it makes it clear that I don't need a solution that works over the already existant files, because they can be re-generated.
From the sounds of it you could make some improvements on your code structure to completely avoid this problem. However, with the information given a simple flag variable should do the trick:
if (!isset($postCodeExecuted) && isset($_POST["SomeValue"]))
{
/* code goes here */
$postCodeExecuted = true;
}
This variable will be set in the global namespace and therefore it will be available from everywhere.
I solved the problem by doing this
$caller = str_replace($_SERVER["DOCUMENT_ROOT"], "", __FILE__);
if ($_SERVER["REQUEST_METHOD"] === "POST" and $caller === $_SERVER["PHP_SELF"])
performThisAction();

Does putting an include inside a function slow down execution?

I have a PHP function which requires authorization for a SOAP request to get the data and processes it. I like to keep the username/password outside of the program in auth.php and use an include statement like this:
include 'auth.php'; // Contains $username and $password.
I normally use include statement at the top of PHP programs. But I don't want to have to pass the values to the function so I put the include statement inside the function.
Does this slow down the program because it's reading auth.php each time the function gets called or does PHP read in all include files and keep the resident in the program, therefore not reading in the same auth.php file each time this function is called?
I have considered using DEFINE instead of setting the variables for username/password so they would be accessible through-out the program, but wasn't sure if this was necessary or not. Thanks!
While I really agree with what #Twisted1919 wrote in the comments, and I think you should listen to his advice, I'd also like to answer your question (does it slow down the execution?).
I'd say "not significantly", for a very simple reason: SOAP, even if done locally, hides XML encoding and parsing. Add to that the "processing of data" that you've mentioned, and you see that the overall work done by the function should amount to far more work than reading and parsing a PHP file that (presumably) only defines a few variables. Hence, that part is really insignificant.

Using require_once inside a method

From what I understand using something like require_once will essentially copy and paste the code from one file into another, as if it was in the first file originally.
Meaning if I was to do something like this it would be valid
foo.php
<?php
require_once("bar.php");
?>
bar.php
<?php
print "Hello World!"
?>
running php foo.php will just output "Hello World!"
Now my question is, if I include require_once inside a method, will the file that is included be loaded when the script is loaded, or only when the method is called?.
And if it is only when the method is called, is there any benefit performance wise. Or would it be the same as if I had kept all the code into one big file.
I'm mainly asking as I've created an API file, which handles a large amount of calls, and I wan't to simplify the file. (I know I can do this just be creating separate classes, but I thought this would be good to know)
(Sorry if this has already been asked, I wasn't sure what to search for)
It will only include when the method is called, but have you looked at autoloading?
1) Only when the method is called.
2) I would imagine there's an intangible benefit to loading on the fly so the PHP interpreter doesn't have to parse extra code if it's not being used.
I usually use the include('bar.php'); i use it for when i use databvase information, i have a file called database.php with login info and when the file loads it calls it right up. I don't need to call up the function. It may not be the most effective and efficient but it works for me. You can also use include_once... include basically does what you want it to, it copies the code essencially..
As others have mentioned, yes, it's included just-in-time.
However, watch out for variable definitions (require()ing from a method will only allow access to local variables in that method's scope).
Keep in mind you can also return values (i.e. strings) from the included file, as well as buffer output with ob_start() etc.

How can I reference variables from another included file in PHP?

So I'm working on a PHP app and trying to make everything moduler. I have an index.php file that includes other php files. The first file included is settings.php which has my postgres credentials defined so they can be accessed elsewhere. The second file is connect.php that has a function you can pass sql to and it will return $result. The third file has functions that call the sql function and receive $result and parse it. In the third file, I can read the results of the $result however if I try if($result) it breaks and isset/empty have no effect.
Anyone have any ideas on a way to make this work, or is my structure just terrible?
Thanks so much!
Mike
let's say you have the following three files:
inc1.php
<?php
$foo = 'hello';
?>
inc2.php
<?php
echo $foo;
?>
main.php
include('inc1.php');
include('inc2.php');
it should echo "hello". however, passing variables around among files is a bad idea, and can lead to a lot of confusing, hard-to-follow code. If you need to pass variables around, use functions and/or objects so that you can at least see where they are coming from.
beyond that though, it's difficult to tell exactly what your problem is without seeing the code in question.
I would really try to switch to OOP. This makes things a lot of easier. If you just have to deal with classes, their methods and attributes you only have to include the classes and not this choas of functions. So I would recommend, give it a go ...

passing URL variables to exec() with php

I have a dedicated server that I use to crunch lots of data. The way I have it now, I can open a script with a process ID like example.php?ex_pid=123 and just let it go. It downloads a small portion of data, processes it, then uploads it into a database then starts again.
Ideally, I would like to call example.php?ex_pid=123 directly and not by passing a variable to example.php like exec('./example.php'.' '.EscapeShellArg($variable)); to keep it from acting globally.
I don't care about the output, if it could execute in the background, that would be brilliant. The server is an Ubuntu distribution btw.
Is this even possible? If so, any help and examples would be more then appreciated.
You could do something like:
exec("./example.php '".addslashes(serialize($_GET))."');
And then in example.php do something like this:
count($_GET) == 0 && $_GET = unserialize(stripslashes($_SERVER['argv'][1]))
The main issue with that is that ?ex_pid is GET data which is generally associated with either including the file or accessing it through a browser. If you were including the file or accessing it from a web browser this would be trivial, but running it as CLI, your only option would be to pass it as an argument, unfortunately. You can pass it as ex_pid=123 and just parse that data, but it would still need to be passed as an argument but doing that you could use parse_str() to parse it.
Depending on what the script does, you could call lynx to call the actual page with the get data attached and generate a hash for an apikey required to make it run. Not sure if that is an option, but it is another way to do it how you want.
Hope that helps!
I had a real problem with this and couldn't get it to work running something like example.php?variable=1.
I could however get an individual file to run using the exec command, without the ?variable=1 at the end.
What I decided to do was dynamically change the contents of a template file , depending on the variables I wanted to send. This file is called template.php and contains all the code you would normally run as a $_GET. Instead of using $_GET, set the value of the variable right at the top. This line of code is then searched and replaced with any value you choose.
I then saved this new file and ran that instead.
In the following example I needed to change an SQL query - the template file has the line $sql="ENTER SQL CODE HERE";. I also needed to change the value of a a variable at the top.
The line in template.php is $myvar=999999; The code below changes these line in template.php to the new values.
//Get the base file to modify - template.php
$contents=file_get_contents("template.php");
$sql="SELECT * FROM mytable WHERE foo='".$bar."'";
$contents=str_replace("ENTER SQL CODE HERE",$sql,$contents);
//Another search
$contents=str_replace("999999",$bar,$contents);
$filename="run_standalone_code".$bar.".php";
//If the file doesnt't exist, create it
if(!file_exists($filename)){
file_put_contents($filename, $contents);
}
//Now run this file
$cmd="/usr/local/bin/php ".$filename." >/dev/null &";
exec($cmd);
I had completely forgotten about this question until #Andrew Waugh commented on it (and I got an email reminder).
Anyways, this question stemmed from a misunderstanding as to how the $argv array is communicated to the script when using CLI. You can pretty much use as many arguments as you need. The way I accomplish this now is like:
if (isset($argv)) {
switch ($argv[1]) {
case "a_distinguishing_name_goes_here":
$pid = $argv[2];
sample_function($pid);
break;
case "another_name_goes_here":
do_something_else($argv[2]);
break;
}
}

Categories