xmlhttp.open() for external php file - php

I have the line
xmlhttp.open("GET","file.php?id=4",true);
This does not work since file.php is not in the same folder but rather in a different private folder not visible to the public.
Is there a way to use the open function to open a file in a different folder?

That's fundamentally impossible.
If you want to send an HTTP request to it, it must be visible to the public over HTTP.

You can only request files from within the public webspace. To access files outside the public webspace you need a script in the public webspace that can fetch the contents from the private folder, e.g.
<?php // file.php in the public webspace
$allowedFiles = array(
1 => '/path/to/private/space/on/server/file1.txt',
2 => '/path/to/private/space/on/server/file2.txt',
3 => '/path/to/private/space/on/server/file3.txt',
4 => '/path/to/private/space/on/server/file4.txt',
);
$id = filter_var($_GET['id'], FILTER_VALIDATE_INT);
if (isset($allowedFiles[$id])) {
readfile($allowedFiles[$id]);
}
Now when you do
xmlhttp.open("GET","file.php?id=4",true);
the script will send the content of
/path/to/private/space/on/server/file4.txt
to the client.
Edit regarding some comments:
Note that readfile will not execute the file contents. If you need to send the results of a PHP script, you have to use include instead of readfile. Please refer to the Manual for details.
The above approach is effectively the same as most of the frameworks nowadays use. You have one single script that acts as a gateway into your application (kind of like a Front Controller pattern). This script accepts any and all requests (think mod_rewrite) to your application and is the only publicly accessible PHP file. It will bootstrap your application and then determine from the URL (or whatever you seem fit) what file, usually a controller when using MVC, in the private space should be instantiated and called.

Related

How to safely evaluate a file's contents before including it in PHP

I am using PHP files returning arrays as a means of configuration.
To process these configuration files I made a class to search the provided configuration directories for PHP files and store their values in a configuration container using include().
Now I was just wondering about the safety of this method.
What if somebody puts malicious code inside one of these files?
What would be the safest way to evaluate these files before including them and potentially triggering unwanted side effects?
I was thinking about using file_get_contents() to load the file as a string and look for any function calls, but I don't want to restrict users from using functions to resolve, for instance, conditional configuration values.
This is the current code, just for an idea of the workings:
public function load(): void
{
$iterator = $this->createFinder()->getIterator();
foreach ($iterator as $file) {
$config = include $file;
if (! is_array($config)) {
throw new \RuntimeException("Invalid config \"{$file->getRealPath()}\", Config files should return an array.");
}
$this->config[$file->getBasename()] = $config;
}
}
private function createFinder(): Finder
{
$this->finder = (new Finder())
->in($this->directories)
->files()
->name('*.php');
return $this->finder;
}
Don't bother with any kind of "security" checks. Simply, you should never, ever include, require or eval the contents of a non-trusted file.
Configuration files are not something where "somebody could put malicious code into". If they are, something is seriously broken with the application setup; and that's what needs fixing, not trying to add half-baked "security" checks to account for this glaring security problem.
Configuration should only be performed by someone with the appropriate security clearance. If the person or persons responsible for deploying/configuring the application are your antagonists, then it's already too late too worry about security.
If you want to have a "friendly" configuration format and not worry about the security implications of third party users providing this configuration, provide a way to configure the application with non-runnable code. E.g. parsing text files, XML, ini files, etc.
Configuration still should be performed by trusted application users, but at least they won't be able to execute arbitrary code on the server (without resorting to an exploit).

Can I include a class file from another server

I have a class in a server1.
FILE1 in server1
<?php
class myObject
{
public function __construct()
{
echo 'Hello, World';
}
}
?>
FILE 2 in server2
$section = require('http://xx.xxx.xxx.x/plugins/myObject.php');
$intance = new myObject();
When file2 is called from a php file in server1 itself, Object is created. I can see 'Hello World' in browser.
But it fails when file2 is called from server2. I get fatal error class not found. I have tried include/file_get_contents/read/ __autoload /spl_autoload_register methods also. Nothing helps to invoke my class from another server.
Is this possible? Can anyone please suggest an alternative? Please help
UPDATE:
i have fopen and include url on in server2 from where iam trying to include file. Actually I needed the class and my website to be two servers.
SCENARIO:
I am tring to build a wallet website in server2. I have necessary plugins in another server [s1]. I have written a class file interacting with plugins in server 1 itself. Iam planning to have wallet websites in more servers. but all of these websites will interact with class in server1. If I could somehow get the code in that class to my website, then i could create objects and call class methods from other servers also. Please suggest other way to implement this.
UPDATE 2:
Can I build somthing like API where all my websites will send request to main class in S1 and get get response. An example would be helpful
Is this possible?
No. PHP code never leaves the server. That's why there are dependency management tools like Composer.
If you want to run code on server 2 from server 1 you need to implement a webservice that does that. So server 2 "calls" the php file on server 1 it does not "require" it. Try something like this:
File 1 Server 1
<?php
class myObject
{
public function __construct()
{
echo json_encode(['result'=>'really cool data result'])
}
}
new myObject();
?>
File 2 Server 2:
<?php
set_time_limit(0);
$url = "http://xx.xxx.xxx.x/plugins/myObject.php";
$ch = curl_init();
// Disable SSL verification
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
// Will return the response, if false it print the response
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// Set the url
curl_setopt($ch, CURLOPT_URL,$url);
// Execute
$result_json=curl_exec($ch);
// Closing
curl_close($ch);
$result_obj = json_decode($result_json);
$result = $result_obj->result
If you want to run code on server 1 you have to do it like this and then use the result from server 1 and do something with it on server 2. You cannot run code on server 2 using software that exists on server 1 because by definition you cannot run something on one machine that exists on another machine.
You may need to first download the file and then requireing it.
No you can't do that. And even if there are really bad work arounds to do that, you should NEVER do that.
It makes your code very vulnerable, if you care about security.
Can you require from remote file? No. Can you include from remote file? Yes. This is known as Remote File Inclusion and usually it is considered a security risk. From PHP's documentation of include:
If "URL include wrappers" are enabled in PHP, you can specify the file to be included using a URL (via HTTP or other supported wrapper - see Supported Protocols and Wrappers for a list of protocols) instead of a local pathname. If the target server interprets the target file as PHP code, variables may be passed to the included file using a URL request string as used with HTTP GET. This is not strictly speaking the same thing as including the file and having it inherit the parent file's variable scope; the script is actually being run on the remote server and the result is then being included into the local script.
To use this feature, open your php.ini file and set the allow_url_include as 1 or "On".
After that, you can now do
$section = include('http://xx.xxx.xxx.x/plugins/myObject.php');
$intance = new myObject();
Be warned though, if you allow a user to manipulate the argument to include, he would be able to inject arbitrary PHP code.

How can I pass an argument to a script as GET method? [duplicate]

This question already has an answer here:
Why file_get_contents() doesn't work without protocol? [duplicate]
(1 answer)
Closed 6 years ago.
I have this folder-structure:
\out
\MakeAvatar.php
\root
\include
\Calculator.php
\img
\avatar
What's MakeAvatar.php? That's a script which gets a parameter (like id) and makes a avatar based on that parameter. Now I need to pass a argument ($id) from Calculator.php to MakeAvatar.php. How can I do that?
Here is my code:
$_GET['id'] = $id; // passing
file_put_contents("../img/avatar/".$id.".jpg", file_get_contents("../out/MakeAvatar.php"));
But it doesn't work. I mean the result is a unknown-image (unclear).
When I open that image by a editor, it is containing the content of MakeAvatar.php (all its codes). So it seems the problem is passing.
Note1: If I put MakeAvatar.php into root and pass that argument like this then if works:
... file_get_contents("http://example.com/MakeAvatar.php?id=$id")
But as you see MakeAatar.php is out of root and I cannot use http. So how can I pass an argument without http?
Your file_get_contents is actually reading the file contents, rather than executing it.
You'll either have to include your file from Calculator.php or expose it to the HTTP server and do a local http request (eg. like file_get_contents('http://localhost/path/to/your/MakeAvatar.php') )
I'd recommend wrapping your important logic in the MakeAvatar file into a function, then includeing it and executing the function.
If your public Web server directory is root, then you should make an entry point, e.g. root/avatar.php. Let's call it controller. In the controller you should use a class(let's call it a model) which has a method generating avatars.
Thus, your structure might look like the following:
root/avatar.php
<?php
require_once __DIR__ . '/../out/MakeAvatar.php';
MakeAvatar::printPng($_GET);
out/MakeAvatar.php
<?php
class MakeAvatar {
public static function printPng(array $input) {
$id = $input['id'];
echo '... PNG data for $id here...';
}
}
Also, I'd keep models in a directory like classes or lib; controllers - in public/something, and views in different directory such as templates.

Is it possible to dynamically reload PHP code while script is running?

I'm having a multiplayer server that's using PHPSockets, and thus is written entirely in PHP.
Currently, whenever I'm making any changes to the PHP server-script I have to kill the script and then start it over again. This means that any users online is disconnected (normally not a problem because there aren't so many at the moment).
Now I am rewriting the server-script to use custom PHP classes and sorten things up a little bit (you don't want to know how nasty it looks today). Today I was thinking: "Shouldn't it be possible to make changes to the php source without having to restart the whole script?".
For example, I'm planning on having a main.php file that is including user.php which contains the class MyUser and game.php which contains the class MyGame. Now let's say that I would like to make a change to user.php and "reload" the server so that the changes to user.php goes into effect, without disconnecting any online users?
I tried to find other questions that answered this, the closest I got is this question: Modifying a running script and having it reload without killing it (php) , which however doesn't seem to solve the disconnection of online users.
UPDATE
My own solutions to this were:
At special occations, include the file external.php, which can access a few variables and use them however it'd like. When doing this, I had to make sure that there were no errors in the code as the whole server would crash if I tried accessing a method that did not exist.
Rewrite the whole thing to Java, which gave me the possibility of adding a plugin system using dynamic class reloading. Works like a charm. Bye bye PHP.
Shouldn't it be possible to make changes to the php source without having to restart the whole script?
[...]
I'm planning on having a main.php file that is including user.php
which contains the class MyUser
In your case, you can't. Classes can only be defined once within a running script. You would need to restart the script to have those classes redefined.
I am not too familiar with PHP but I would assume that a process is created to run the script, in doing so it copies the instructions needed to run the program and begins execution on the CPU, during this, if you were to "update" the instructions, you'd need to kill the process ultimate and restart it. Includes are a fancy way of linking your classes and files together but ultimately the processor will have that information separate from where the file of them are stored and it is ultimately different until you restart the process.
I do not know of any system in which you can create code and actively edit it and see the changes while that code is being run. Most active programs require restart to reload new source code.
Runkit will allow you to add, remove, and redefine methods (among other things) at runtime. While you cannot change the defined properties of a class or its existing instances, it would allow you to change the behavior of those objects.
I don't recommend this as a permanent solution, but it might be useful during development. Eventually you'll want to store the game state to files, a database, Memcache, etc.
How about storing your User object into APC cache while your main script loads from the cache and checks every so often for new opcode.
To include a function in the cache, you must include the SuperClosure Class. An example would be:
if (!apc_exists('area')) {
// simple closure
// calculates area given length and width
$area = new SuperClosure(
function($length, $width) {
return $length * $width;
}
);
apc_store('area', $area);
echo 'Added closure to cache.';
} else {
$func = apc_fetch('area');
echo 'Retrieved closure from cache. ';
echo 'The area of a 6x5 polygon is: ' . $func(6,5);
}
See here for a tutorial on APC.
Simple solution use $MyUser instead of MyUser
require MyUserV1.php;
$MyUser = 'MyUserV1';
$oldUser = new $MyUser('your name');
//Some time after
require MyUserV2.php;
$MyUser = 'MyUserV2';
$newUser = new $MyUser('your name');
Every declared class stay in memory but become unused when the last MyUserV1 logout
you can make them inherit from an abstract class MyUser for using is_a
You cannot include again a file with the same class, but you can do so with an array. You can also convert from array to class, if you really need to do so. This only applies to data, though, not to behavior (methods).
I don't know much about these things with the games on PC but you can try to get all the variables from your database for the user and then update the text fields or buttons using those variables
In web is using AJAX (change data without refreshing the page).Isn't one for programming?

How to know if php script is called via require_once()? [duplicate]

This question already has answers here:
Check if a file was included or loaded
(12 answers)
Closed 2 years ago.
My webapp has a buch of modules. Each module has a 'main' php script which loads submodules based on a query sent to the main module:
//file: clientes.php
//check for valid user...
//import CSS and JS...
switch( $_GET["action"] )
{
case "lista" : require_once("clientes.lista.php"); break;
case "listaDeudores" : require_once("clientes.listaDeudores.php"); break;
case "nuevo" : require_once("clientes.nuevo.php"); break;
case "detalles" : require_once("clientes.detalles.php"); break;
case "editar" : require_once("clientes.editar.php"); break;
default : echo "<h1>Error</h1><p>El sitio ha encontrado un error.</p>";
}
This main module deals with security and imports many resources all submodules need. The big problem shows up when a user asks for any of the submodules, bypassing all the security measures on the main module! My idea was to add a line on every submodule to test if it was being called directly and deny access or if its been called via another script, and continue. The least thing I would like to do is redo the security checking on every single file, since it does a bunch of query's to the database.
Does a php script know if its been called via a require_once() or a direct call ? I've been trying to implement some sort of $_SERVER['REQUEST_URI'] and $_SERVER['PHP_SELF'] pitfall but I was wondering if there was some sort of an elegant way of doing this.
I was looking for a way to determine if a file have been included or called directly, all from within the file. At some point in my quest I passed through this thread. Checking various other threads on this and other sites and pages from the PHP manual I got enlightened and came up with this piece of code:
if ( basename(__FILE__) == basename($_SERVER["SCRIPT_FILENAME"]) ) {
echo "called directly";
}
else {
echo "included/required"
}
In essence it compares if the name of the current file (the one that could be included) is the same as the file that is beeing executed.
EXPLANATION:
__FILE__ is a PHP magic constant that stores the full path and filename of the file, the beauty of it is that if the file has been included or required it still returns the full path and filename of such file (the included file).
(Magic Constants Manual: http://php.net/manual/en/language.constants.predefined.php)
$_SERVER["SCRIPT_FILENAME"] returns the absolute pathname of the currently executing script. As when a file is included/required it's not executed (just included) it returns the path name of the (let's say) "parent" file (the one that includs the other file and the one that gets executed).
basename(string $path) is a function that returns the trailing name component of path, that in this case is the file name. You could also just compare the full path and filename, that would be indeed better, it isn't really neceseary to use this function but it feels cleaner this way, jajaj.
(basename(): http://php.net/manual/en/function.basename.php)
I know it's a "bit" late to be answering the main question but I guessed that it could be useful to anyone who's on the same situation that I was and that also passes by.
One elegant way is putting all your files which should only be accessed via include outside the web directory.
Say your web directory is /foo/www/, make an include directory /foo/includes and set this in your include_path:
$root = '/foo';
$webroot = $root.'/www'; // in case you need it on day
$lib = $root.'/includes';
// this add your library at the end of the current include_path
set_include_path(get_include_path() . PATH_SEPARATOR . $lib);
Then nobody will be able to access your libraries directly.
There's a lot of other things you could do (test a global variable is set, use only classes in libraries, etc) but this one is the most secure one. Every file which is not in your DocumentRoot cannot be accessed via an url,. But that does not mean PHP cannot get access to this file (check as well your open_basedir configuration if you have it not empty, to allow your include dir in it).
The only file you really need in your web directory is what we call the bootstrap (index.php), with a nice rewrite rule or a nice url managment you can limit all your requests on the application to this file, this will be a good starting point for security.
One popular method to make sure modules are not called directly is defining a constant in the main script, and checking for that constant in the module.
// index.php
define("LEGIT_REQUEST", true);
// in each module
if (!defined("LEGIT_REQUEST"))
die ("This module cannot be called directly.");
For the sake of completeness, the other possibility is to move such files to a directory that's not publicly available. However, some control panels used by hosting providers make this impossible. In such case, if you are using Apache you can place an .htaccess file inside the directory:
#
# Private directory
#
Order allow,deny
Deny from all
A common technique is to add this to the main module (before the includes)
define('TEST', true);
and to add something like that at the first line of every submodule
if (!defined('TEST')) {
die('Do not cheat.');
}
An alternative to defining a constant and checking it is to simply put the files that index.php includes outside of the document root area. That way the user can't directly access them via your web server at all. This is also obviously the most secure way, in case your web server has a configuration error in future that eg. displays PHP files as plain text.
You can define('SOMETHING', null) in clientes.php and then check if (!defined('SOMETHING')) die; in the modules.
global.php
if(!defined("in_myscript"))
{
die("Direct access forbidden.");
}
module.php
define("in_myscript", 1);
include("global.php");
A generic way that works without having to define a constant or use htaccess or use a specific directory structure or depend on the $_SERVER array that could theoretically be modified is to start each include-only (no direct access) file with this code:
<?php $inc = get_included_files(); if(basename(__FILE__) == basename($inc[0])) exit();
As practice of habit I have a console class built to send messages, errors, etc. to console with FirePHP. Inside the Console class write() method I have a check to see if a $_REQUEST[debug] == 1, that way I'm not exposing errors to users if something pops up on production and they would have to know what the request variable is to access the debug information.
At the top of every file I add:
Console::debug('fileName.php is loaded.');
here is a snippit from it to give you the right idea:
class Console{
public static function write($msg,$msg_type='info',$msg_label=''){
if(isset($_REQUEST['debug']) && $_REQUEST['debug'] == 'PANCAKE!'){
ob_start();
switch($msg_type){
case 'info':
FB::info($msg, $msg_label);
break;
case 'debug':
FB::info($msg, 'DEBUG')
break;
...
}
}
}
public static function debug($msg){
Console::write($msg, '');
}
}
Short and simple (for CLI):
if (__FILE__ == realpath($argv[0]))
main();

Categories