REX: Remote Execution Framework for PHP

Contents

Introduction to REX
A First Example
Security and REX
Example Uses of REX
Framework Options
Command Line Interface
Web Interface
Coding REX Files
Using the Framework API


Introduction to REX

REX is a proof-of-concept Remote Execution framework for PHP.

In simple terms the REX framework downloads PHP source code (referred to as REX code owing to the specific markups and commands available) from a location (either from a local filebase or remotely via HTTP/S) and executes it.

This is similar to running any PHP script the difference being the source code is loaded as text from elsewhere and then executed by the client.

User          REX Client           Code Store

Request ----> REX Starts
              Code Request ------> HTTP (or other)
              Code Received <----- HTTP (or other)
Output <----- Code Executes

For example the user, via the CLI or Web interface might request the REX client to run code located at http://codeserver/rex/

The REX client will start and then request the code located at http://codeserver/rex, download the source code into memory and then execute it like any other PHP code. Output generated is then passed back to the user.

About the Documentation

Please note these docs were hammered out quickly and dirtily - they will no doubt contain endless spelling, grammer and sense errors.

Please forgive me.
Back to the top

A First Example

As a first example let's create a Hello World application.

For this example we'll assume the user is sitting at the CLI of a REX enabled Linux client (called rexclient). The code will be uploaded onto the server (called codeserver) and published via apache in the directory http://codeserver/rex/

The REX Code

REX code is simply PHP but usually saved with a .rex extension (to stop it being executed by apache when requested).

Here is the sourcecode for our file index.rex:
<?php
echo "Hello World!"
?>

We save this file to the directory published by our codeserver as /rex/ (usually something like /var/www/html/rex in the codeserver file system).

Two key points:

Executing on the REX-enabled client

Now the code has been created and saved onto the codeserver we can request and execute it on the client:
$ php rex.php http://codeserver/rex/

Will start REX and tell it to download the file from http://codeserver/rex/ (because this is a directory it will try the file index.rex in that directory).

Expected Output

$ php rex.php http://codeserver/rex/
Hello World!
$


And there you have it - your first REX application.

Note a similar example (and others) are available hosted at PurplePixie for you to browse online or request via REX. You can find these on the examples page.
Back to the top

Security and REX

The REX framework offers no built-in security.

Given the whole point of the system is to allow execution of arbitrary code it is potentially a serious security risk unless measures are taken to secure your implementation.

There are two primary risk factors when using REX:

Poisoning of Code Store

As REX downloads code from a store and executes it any unauthorised access to or modification of the code store could lead to malicious adulterated code being run on the client systems.

Of course this is a risk whenever code (or binaries) are downloaded from a remote site but with a traditional method (installing the program on the client) any poisoned code must be present at the point of download.

With REX as the code is loaded "fresh" on each execution the theoretical risks of compromise are higher.

So it is important to keep your code server secure and be careful where you are executing REX code from.

Execution of Arbitrary Code

If the REX executor (or your own implementation using the API) is exposed in a manner allowing filenames for execution to be passed then a malicious agent could simply setup their own "bad" code store and get your clients to download and execute it.

Always ensure your REX executor is secure, at the very least by limiting access to the web interface through HTTP-AUTH or specific HTTP access rules.


Back to the top

Example Uses of REX

A remote execution system can be useful in a number of situations, primarily where you wish to commonly execute the same code over a wide number of client systems or have a specific need to execute code on a client without using alternative methods.

Large Number of Clients

In a network situation with a large number of clients it may be required for them all to execute the same code on a regular basis, for example checking if their installed applications are up-to-date or performing cleanup.

Although you could have the code installed on each and every client this can be problematic for maintenance (any changes must be replicated to all the clients).

Of course you could just store your code on a network-accessible location such as a NFS or CIFS share and have the clients run it from there - or you could use a remote execution framework such as REX to specifically pull down and execute code from a central location.

In this manner any changes made to the centrally stored code will be immediately reflected to all clients the next time they run it.

Execute Code on a Remote Client

If you have some code you wish to execute on one (or more) clients then the "normal" method would be to open an interactive session on the client (using SSH or RDP), copy the code up and then execute.

However if a client has the REX framework installed and web-accessible the code can be run on the client with a single HTTP request to the web interface of the REX executor.

Client-Specific Code

Of course because the code is executed on the actual client itself then you can have selection operations based upon the client - you could get the hostname or scan any type of configuration or files (for example to determine if the client was Win32 or Linux and take action accordingly).
Back to the top

Framework Options

The following options can be set within the client framework either via the CLI, Web or API dependent on how you are calling REX.

Executor Options
The following options are available only if you are using the REX executor (the CLI or Web client). If you are using the framework directly via the API then your code will handle these instead.


Back to the top

Command Line Interface

The REX executor (rex.php) offers a Command-Line Interface (CLI) to fetch and execute remote code.

Example:
$ php rex.php http://rex.purplepixie.org/examples/hello-world/

The above instructs REX to fetch the code from rex.purplepixie.org/examples/hello-world/index.rex and execute it displaying any output to the screen.

In addition to the file (or files) specified there are a number of switches and options you can provide.

These control the settings detailed in the framework options section of the documentation.

CLI Switches and Options


REX Stack and Environment Variables

The CLI can be used to specify REX stack variables and REX environment variables on startup.

Note that both the variable names and values can be quoted strings if required to include data with spaces.

Filename(s)

Anything passed and not prefixed with -- will be treated as a filename to be loaded into the list for execution. These are done in order.

Please note however that the options are set once at runtime and not parsed in order with the filenames so, for example, if you call a filename then set the base and then call another filename both will have the base set when executed.

Examples

$ php rex.php --debug=1 http://codeserver/rex/
Will execute the file http://codeserver/rex/index.rex with debug output

$ php rex.php --base="http://codeserver/my files/" code1.rex code2.rex
Will execute first code1.rex then code2.rex from the directory "http://codeserver/my files/"

$ php rex.php --set somevar="something or other" --default=rexcode.php http://codeserver/rex/
Will set the variable somevar to be "something or other" in the variable stack and then execute http://codeserver/rex/rexcode.php
Back to the top

Web Interface

The REX executor (rex.php) offers the ability to make requests to a REX client via HTTP.

An example script calling REX with the relevant variables is provided in the download package as index.php.

REX options (as detailed in the framework options section of the documentation are set through HTTP variables (using either GET or POST).

If a specific option or variable is not found then it is ignored.

HTTP Option Variables

Filenames to Execute

Pass the variable rex_filename either as a single variable or as an array i.e. rex_filename[0]=file1.rex rex_filename[1]=file2.rex

Stack and Environment Variables

To set stack variables pass an array of rex_set[] for the variable names with the values in rex_val[] corresponding for each entry. For example rex_set[0]=hello and rex_val[0]=world will set the variable hello to equal world.

Environment variables use exactly the same system but with the names rex_env_set[] and rex_env_val[].
Back to the top

Coding REX Files

REX files are simply PHP files with access to a specific framework to support their operation.

PHP code in the files must be prefixed with a <?php and closed with a ?> (like any PHP script).

As the code is executed with a function any PHP variables (other than super-globals) you wish to access or work with must be defined with the global command.

The REX framework object itself is available to REX scripts as $REX and they can access all the the API methods and properties that are available.

Executing Other Files

A REX should make use of the REX::ExecFile() method to call another file. If not prefixed with a protocol (such as http:// or file://) then the file is executed relative to the base directory.

Usually this means the same directory the current REX file is executing from.

<?php
// Do some stuff...
$REX->ExecFile("another.rex");
?>
The above script will "do some stuff" and then execute the file another.rex (if the base directory property is unmodified this will be called from the same directory as the original script.

Variables

REX files can make use of standard PHP variables that are in scope. In effect this means super-globals and anything that is specifically named in a global statement.

Variables persist through the execution of future files so can be used to pass data.

As well as using native PHP variables there are two sets of REX variables; the variable stack and environment variables.

Stack variables are set with REX::Set() and recalled with REX::Get()

<?php
$REX->Set("my_variable","hello");
echo $REX->Get("my_variable");
?>
The above code will set my_variable to be "hello" and then echo it back in the output.

To see more detail on this and also the environment variables please see the API documentation.

A good example showing use of variables is the counter example (available from the examples page.
Back to the top

Using the Framework API

You can access REX and use it directly in your own client-side code via the API.

The executor that ships with REX (rex.php) should provide a fairly good example of how you can use REX from code.

Include the REX Framework and Instantiate the Object

<?php
include("rex.inc.php");
$REX = new REX();
?>
This will include the framework code and create a REX object ($REX).

REX Properties

REX Methods