10

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

12
  • 3
    well some one is confused about what 'compiled' and 'execute' means, and how php is served. When you get your *.php file from a remote site, you get NO php code, only the output it returns. Commented Aug 18, 2015 at 20:55
  • that's what i pointed outed... i want the soucecode itself and not the compiled output Commented Aug 18, 2015 at 21:00
  • well you CAN'T - think about the security implications of that! Commented Aug 18, 2015 at 21:03
  • 1
    @Dagon Letting the code be downloaded from a public URL is no different from letting it be downloaded from a public GitHub repo, for instance. There are probably nicer ways of doing it, but it's not that crazy. Commented Aug 22, 2015 at 14:52
  • 1
    @IMSoP You would be correct if the source was hosted with HTTPS, but since the servers are using unsecured HTTP, a man-in-the-middle would easily be able to create a remote execution exploit. Also, although it might technically be secure, executing code that comes across the internet opens you up to a whole new class of security problems that you need to worry about. TL;DR don't do it. Commented Jan 13, 2016 at 21:39

5 Answers 5

7

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.

Sign up to request clarification or add additional context in comments.

4 Comments

To be fair, there isn't that much of a security hole here - basically it's just publishing part of the source code, which thousands of people do every day when they publish to a public GitHub repo, etc. You're right, though, that grabbing the code off a web URL is an inefficient way to do it, and syncing the code in advance is probably a better idea.
@IMSoP Not all projects can have your code publicly accessible. I agree that yours and OP's approaches have the same visibility as a public Git repository, but for a closed source project it'll be a security hole, indeed.
Sure, you have to be aware that you're making the code public, but calling it "a huge security hole" makes it sound like the operation of the code can be compromised, which is not true. Your first sentence reads like there is some further consequence of opening the scripts to the world, when in fact opening the scripts to the world is the consequence. Of course, if the code in question contained passwords or something like that, that would be a security hole.
@IMSoP There's a difference between publishing your source code and executing code from a remote source across unsecured HTTP. See my comment above.
5

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

Comments

4

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".

Comments

3
+50

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!

Comments

0

To export the source code:

  • Write one script on noexecution that reads the file it gets as argument and output the source code.
  • Protect it so that only execution.tld gets the source code.

To execute it, why take the overhead of writing a file (to disk) and reading it again when there's eval() You'll have to strip start (<?php) and end (?>) tags off of the very end of the input, but that's a simple string operation... that you could do in noexecution's output script already ...

But perhaps the simpler solution is to use some sort of replication or file sharing between the servers.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.