Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Defer compiling from one php script to another

Tags:

php

What i'd like to achieve

  1. my php-script is running on: http://execute.tld
  2. while running i'd like to get content (also scripts) from another website: http://noexecution.tld without execution (compiling) but defer the execution
  3. now i'd like to execute the content from http://noexecution.tld on http://execute.tld

It's a bit like grabbing global script snippets and compile after putting them together on a different server.

Files

main.php | http://execute.tld/main.php

<?php
$var = 'main.php';
file_put_contents("local_sub.php", file_get_contents("http://noexecution.tld/sub.php") );
include "local_sub.php";
echo $var;
?>

sub.php | http://noexecution.tld/sub.php

sub.php | line 1 notcompiled<br>
<?php $var = 'sub.php | line 2 compiled later<br>'; ?>
sub.php | line 3 notcompiled<br>

Result after running main.php

sub.php | line 1 notcompiled
sub.php | line 3 notcompiled
main.php

Wanted result

sub.php | line 1 notcompiled
sub.php | line 3 notcompiled
line 2 compiled later

My own workaround

My own workaround is to simply switch the extension from sub.php to sub.whatever and rename it "on the fly".

Files

main.php | http://execute.tld/main.php

The sourcecode is the same but changed

file_get_contents("http://noexecution.tld/sub.php") to

file_get_contents("http://noexecution.tld/sub.DontCompileAsPhp").

<?php
$var = 'main.php';
file_put_contents("local_sub.php", file_get_contents("http://noexecution.tld/sub.DontCompileAsPhp"));
include "local_sub.php";
echo $var;
?>

sub.DontCompileAsPhp | http://noexecution.tld/sub.DontCompileAsPhp

The sourcecode is the same but without php extension it will not be compiled as php as well.

sub.php | line 1 notcompiled<br>
<?php $var = 'sub.php | line 2 compiled later<br>'; ?>
sub.php | line 3 notcompiled<br>

Result after running main.php (matches exactly my needs)

sub.php | line 1 notcompiled
sub.php | line 3 notcompiled
line 2 compiled later

Why am I not satisfied with my workaround?

I want to have a clean way to defer the compiling without playing around with extensions...

Things I also tried

  1. __halt_compiler(); [...]
  2. ob_start(); [...]

any help is very welcome - thanx in advance | BTW: it's my very first question

like image 447
Axel Avatar asked Aug 18 '15 20:08

Axel


4 Answers

As @Dagon stated in the comments, you'll create a huge security hole in your application when simply open your scripts to the world.

Since what you want to achieve is to share the scripts between several applications/servers, I can think in at least 2 ways to do that:

  • Access the main server directly, using a secure connection, via SSH for instance, and grab the scripts from there.
  • Use a Git repository to keep all your shared scripts, and auto deploy it to your servers.

The second is the better option, both due security and performance. Doing that you don't need to access another server during execution to fetch the scripts, and you'll have a local copy of all shared scripts.

You can also use a dependency manager, like Composer (https://getcomposer.org/), to easily add your scripts to new applications.

like image 141
Gustavo Straube Avatar answered Nov 03 '22 13:11

Gustavo Straube


First, and correct me if I am wrong, php is an interpreted language not a compiled one.

Well as for your question, I would highly unrecommend putting your code at plain sight. It is true a hacker would need to know the exact file name of the file to be able to access it, but still it is a security risk I wouldn't take. So, the fastest and easiest solution I can think of is :

  1. Protect your scripts folder in noexecution.tld/scripts with a .htaccess file that should look like this :

    AuthType Basic
    AuthName "Do you have security clearance for this ?"
    AuthUserFile /path/to/.htpasswd
    Require valid-user
    

    and a .htpasswd that should look like this (for admin:admin authentication):

    admin:$apr1$kO7YWurq$QHrgAbwXAyNZJfBd/gEc71
    

    You can use this link to generate the .htpasswd file for any user:password you like

  2. You can either continue changing your php scripts extensions, or just append this to your .htaccess to have your php files in the underlying folders treated as binary files :

    AddType application/octet-stream .php
    
  3. As for how to access the files in noexecution.tld/scripts now from PHP on execution.tld/*.php you need to setup basic authentication with curl. If you do not know how to implement that, check out this tutorial

like image 43
Younes Regaieg Avatar answered Nov 03 '22 12:11

Younes Regaieg


You could use a warpper script (e.g. download.php) on the noexecution.tld Server which delivers the plaintext of your php files, as I suggested at Update local php file from remote php file

<?php
$file = $_SERVER['DOCUMENT_ROOT'] . $_GET['file'];

// @TODO: Add security check if file is of type php and below document root. Use realpath() to check this.
header("Content-Type: text/plain");
header("Content-Disposition: attachment; filename=\"$file\"");
readfile($file);
?>

This would be called like http://noexecition.tld/download.php?file=sub.php

But: You have to add security precautions to this script as it would delivery any file to the calling script even sensible files like configuration files.

Possible checks:

  1. Only offer .php files for download
  2. Only allow download of files within a specific folder, e.g. /downloadable-script
  3. Use authentication, at least something like a required get param like key=whatEverPassword
  4. Use a timestamped hash to allow access of a file for a given period of time
  5. Be creative!
like image 24
maxhb Avatar answered Nov 03 '22 14:11

maxhb


The "workaround" you have come up with is the only solution, although there are some variants. What you are doing is not really "delaying execution of a script", you are just serving some text on a (presumably public) web page which happens to be PHP source code.

The server hosting that text file has no control of what you do when you download it, so the code that later executes it is basically irrelevant (as is the name of the temporary file you save it to - include doesn't check the file extension).

Looking at it from that point of view, there are a few ways of doing basically the same thing:

  • don't end the file name with .php, so the server doesn't try to execute it
  • don't install PHP on that server
  • configure that server, or that vhost, or that directory, not to execute files ending in .php

Or, of course, you could write a PHP script which echoes the PHP source code, rather than just putting the code in a text file. This would make sense if the code dynamically changes in some way, which would be closer to your description of "delaying some code execution".

like image 35
IMSoP Avatar answered Nov 03 '22 13:11

IMSoP