LuaSandbox

This page is a translated version of the page LuaSandbox and the translation is 64% complete.
Outdated translations are marked like this.
Für die MediaWiki-Erweiterung, die es erlaubt, Sandbox-Lua-Code zu verwenden siehe: Extension:Scribunto.

LuaSandbox is an extension for PHP 7 and PHP 8 to allow safely running untrusted Lua 5.1 code from within PHP, which will generally be faster than shelling out to a Lua binary and using inter-process communication.

Installation

Vorverpackt

LuaSandbox ist in Debian 10 und Ubuntu 18.04 und neuer verfügbar. Installiere mit den folgenden Befehl:

sudo apt-get install php-luasandbox

PECL

LuaSandbox is now available in PECL, which also provides pre-built Windows DLLs. Siehe unsere Paketseite. Lade erstmal die richtige Lua 5.1-Bibliothek herunter, wie unten bei "Manuelle Installation" beschrieben. Führe dann folgendes aus:

sudo pecl install luasandbox

Manuelle Installation

Voraussetzungen

Installiere die Header- und Bibliothekdateien für PHP und Lua 5.1.

  • Für Debian-derivative Linux-Distributionen wie Ubuntu:
    sudo apt-get install php-dev liblua5.1-0-dev
    
  • Für CentOS/Redhat-derivative Linux-Distributionen:
    sudo yum install php-devel lua5.1 lua5.1-devel
    
  • Für macOS
    brew install lua
    


Herunterladen

Lade den Quellcode in ein geeignetes Verzeichnis von git herunter:

git clone https://gerrit.wikimedia.org/r/mediawiki/php/luasandbox.git

Oder lade einen Snapshot herunter und entpacke es.

Build

luasandbox here is the directory that LuaSandbox Git repository was cloned to.

cd luasandbox
phpize && ./configure && make && sudo make install

Then add extension=luasandbox.so to the PHP configuration in an appropriate place. For example, in modern Debian-derived distributions you would add a file to /etc/php/$version/mods-available (where $version is the version of PHP for which you complied LuaSandbox) and use the phpenmod command to enable it.

If you are using LuaSandbox with a web application such as MediaWiki, you will need to restart your web server or php-fpm for PHP to load the extension. After such reload, you should see LuaSandbox in the output of phpinfo() and get_loaded_extensions() (and, for MediaWiki with Scribunto installed, Special:Version).


Beispiele

$sandbox = new LuaSandbox;
$sandbox->setMemoryLimit( 50 * 1024 * 1024 );
$sandbox->setCPULimit( 10 );

// Registriere ein paar Funktionen in der Lua-Umgebung

function frobnosticate( $v ) {
    return [ $v + 42 ];
}

$sandbox->registerLibrary( 'php', [
    'frobnosticate' => 'frobnosticate',
    'output' => function ( $string ) {
        echo "$string\n";
    },
    'error' => function () {
        throw new LuaSandboxRuntimeError( "Something is wrong" );
    }
] );

// Execute some Lua code, including callbacks into PHP and into Lua

$luaCode = <<<EOF
php.output( "Hello, world" );

return "Hi", function ( v )
    return php.frobnosticate( v + 200 )
end
EOF;

list( $hi, $frob ) = $sandbox->loadString( $luaCode )->call();
assert( $frob->call( 4000 ) === [ 4242 ] );

// PHP-thrown LuaSandboxRuntimeError exceptions can be caught inside Lua

list( $ok, $message ) = $sandbox->loadString( 'return pcall( php.error )' )->call();
assert( !$ok );
assert( $message === 'Something is wrong' );

Dokumentation

Diese Erweiterung wird nun im PHP-Handbuch dokumentiert.

If you want to change the manual, you can either submit a pull request against the PHP manual repository in GitHub, or you can change our mirror of the LuaSandbox chapter in the extension's Gerrit project.

Unterschiede zum Standard-Lua

LuaSandbox provides a sandboxed environment which differs in some ways from standard Lua 5.1.

Die folgenden Funktionen und Pakete sind nicht verfügbar:

  • dofile(), loadfile() und das io-Paket, da sie direkten Zugriff auf das Dateisystem erlauben. Falls nötig, sollte der Dateisystemzugriff durch PHP-Callbacks erfolgen.
  • Das package-Paket, inklusive require() und module(), da es sehr auf direkten Dateisystemzugriff angewiesen ist. Eine rein-Lua-Umschreibung, wie dies in Scribunto verwendet wird, kann stattdessen verwendet werden.
  • load() und loadstring(), um eine statische Analyse von Lua-Code zu erlauben.
  • print(), da dies zur Standardausgabe ausgibt. Falls nötig, sollte die Ausgabe durch PHP-Callbacks erfolgen.
  • Der Großteil des os-Pakets, da es die Manipulation des Prozesses und das Ausführen von anderen Prozessen erlaubt.
    • os.clock(), os.date(), os.difftime() und os.time() bleiben verfügbar.
  • Der Großteil des debug-Pakets, da es die Manipulation des Lua-Status und der Metadaten auf Weisen ermöglicht, die das Sandboxing brechen kann.
    • debug.traceback() bleibt verfügbar.
  • string.dump(), da es möglicherweise interne Daten offenlegt.
  • collectgarbage(), gcinfo() und das coroutine-Paket wurden nicht auf Sicherheit überprüft.

Die folgenden Funktionen wurden modifiziert:

  • pcall() und xpcall() können bestimmte Fehler nicht fangen, insbesondere Zeitüberschreitungsfehler.
  • tostring() enthält keine Zeigeradressen.
  • string.match() has been patched to limit the recursion depth and to periodically check for a timeout.
  • math.random() and math.randomseed() are replaced with versions that don't share state with PHP's rand().
  • The Lua 5.2 __pairs and __ipairs metamethods are supported by pairs() and ipairs().


Geschichte

Over the years, MediaWiki's wikitext template language gained more features and grew more complicated. As early as 2009, MediaWiki developers began discussing the idea of embedding a real scripting language instead of continuing to make wikitext more complex.

Requirements for such a project included a strong sandbox and strict limitations on memory and CPU time usage, since it would be executing untrusted user code on production servers. It would need to be usable by shelling out to a standalone binary, with the ability to be run in-process via a PHP extension for better performance being a major benefit.

When development started in earnest circa 2011, four candidate languages were identified: Lua, JavaScript, PHP, or a hypothetical "WikiScript" language to be developed. Lua hatte verschiedene Vorteile:

  • Klein (eigenständig 170K) und schnell. Auch die Existenz von LuaJIT wurde als Vorteil betrachtet.
  • Konzipiert für die Einbettung, einschließlich einfacher Hooks für CPU- und Arbeitsspeicherbegrenzung.
  • Einfaches Sandboxing, keine internen Globals.
  • Detaliertes Referenzhandbuch, inklusive Anweisungen zum Einbetten.

Der Hauptnachteil war, dass es nicht so bekannt war wie JavaScript.

JavaScript hatte in der damaligen Form der V8-Engine mehrere Nachteile:

  • Minimale Dokumentation zur Einbettung.
  • Continued support for embedding unclear.
  • No allocation hook.
  • Huge standalone binary.

The Rhino engine was worse, as being written in Java it couldn't sanely be embedded in PHP at all. PHP itself was rejected since proper embedding and sandboxing would have been extremely difficult and pre-parsing would have been slow, and "WikiScript" would have been a much larger project in that it would have required developing an interpreter (or two) from scratch.

Thus, Lua was chosen, specifically version 5.1 that was available at the time, and this PHP extension was developed. The changes made to function environment handling in 5.2 have prevented a simple upgrade since, see phab:T178146 for details.

Externe Links