
CalderaForms 1.5.9.1 XSS (WordPress-Plugin) - Tutorial
CalderaForms 1.5.9.1 XSS (WordPress-Plugin) - Tutorial
CalderaForm ist ein WordPress-Plugin, mit dem sich einfach per Drag & Drop Formulare erstellen lassen. Im Rahmen einer aktuellen Tätigkeit habe ich einige Portale getestet, auf denen genau ein solches, mit diesem Plugin erstelltes Kontaktformular gehostet wurde. Die benutzerdefinierte Konfiguration der betreffenden Instanz ermöglichte es mir, eine Sicherheitslücke zu finden: Aufgrund ihrer einfachen, lehrbuchhaften Natur denke ich, dass sie ein guter Anlass ist, um Einsteigern einige Mechanismen zu veranschaulichen.
Ausschließlich zu Lehrzwecken – diese Informationen nicht zum Testen von Zielen ohne ausdrückliche Genehmigung oder für illegale Zwecke verwenden – nicht nach dem Essen in kaltes Wasser springen – sich bei Hitze zwiebelartig anziehen
Für den vollständigen Exploit:
https://www.exploit-db.com/exploits/44489/
Für die CVE:
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-7747
In der untersuchten Konfiguration war das Formular so eingestellt, dass es dem Benutzer mit einer Dankesnachricht antwortet, die ihn mit dem gerade eingegebenen Namen anspricht.
Um die Testumgebung nachzubauen, installieren Sie lokal eine WordPress-Instanz und das Plugin CalderaForms Version 1.5.9.1 (verfügbar hier oder hier).
Nach der Installation: Über die WordPress-Administrationskonsole > linke Spalte > „Caldera Forms“ > obere Buttons > „New Form“ > Contact Form auswählen, umbenennen und „Create Form“

Nach der Erstellung kann die Konfiguration geändert werden: Obere Buttons > „Form Settings“ > Die Erfolgsmeldung (Success Message) so ändern, dass sie einen der vom Benutzer eingegebenen Daten enthält. Klicken Sie auf das Feld, es erscheint eine Dropdown-Liste mit Vorschlägen. Fügen Sie %first_name% hinzu

Obere Buttons > „Save Form“
Um das Formular in eine Seite einzufügen: Linke Spalte > „Pages“ > „Sample Page“ > „Edit“ > „Caldera Form“ > das gerade erstellte Formular auswählen > „Insert Form“ > rechte Spalte > „Update“

Erledigt.
Lassen Sie uns Schritt für Schritt die notwendigen Schritte zur Durchführung dieser Art von Angriff nach dem Prinzip „Teile und herrsche“ durchgehen.
Während des Tests, wenn man mit einer Komponente interagiert, muss man stets auf ihre Reaktionen auf die gegebenen Reize achten; insbesondere konzentrieren wir uns auf den „Weg“ der von uns eingegebenen Daten und etwaige Veränderungen, die sie durchlaufen.
Ein konkretes Beispiel für unseren Fall ist das Folgende:
Wir besuchen die Seite mit dem Formular: http://127.0.0.1/wordpress/sample-page/
Wir füllen das Formular mit den folgenden Daten aus
"First Name": myName
"Last Name": myLast
"Email Address": my@e.mail
"Comments": myComm
Die Daten werden gemäß der Plugin-Logik verarbeitet
Die erhaltene Dankesnachricht enthält die von uns im Feld First Name eingegebene Zeichenfolge
"Thank you myName, form has been successfully submitted."

Die von uns im Feld „First Name“ eingegebene Zeichenfolge wird in der Dankesnachricht zurückgegeben.
Insbesondere ist die Zeichenfolge in einem HTML-div-Tag enthalten.
Unsere Eingabe landet im HTML der Seite.
Bemerkung: „Gefällt uns. Wir haben einen Berührungspunkt.“
Machen wir einen Schritt vorwärts. Wie wird unsere Eingabe während der Phase, die wir „Verarbeitung“ (Punkt 2) genannt haben, behandelt? Insbesondere wollen wir wissen: Gibt es Einschränkungen bei den Zeichen (und deren Kombinationen), die wir verwenden können? Das Ziel ist natürlich, „Zeug“ injizieren zu können. Bei dem Versuch einer Injektion muss man im Hinterkopf behalten, wo unsere Eingabe landet, und die entsprechende „Sprache“ verwenden.
Daher interessiert uns, ob wir die typischen HTML-Zeichen und -Konstrukte verwenden können, und insbesondere, ob wir angesichts der Fähigkeit dieser Sprache, JavaScript zu enthalten/interpretieren, eine Strategie finden, um unseren Code in der „Landezone“, also dem zuvor bemerkten div-Tag, zu platzieren.
Dazu fügen wir im Feld „First Name“ ein einfaches HTML-Tag ein und beobachten, ob es „bereinigt“ (sanitized) wird, also so modifiziert, dass es harmlos/nicht interpretierbar gemacht wird, oder ob es uns unverändert zurückgegeben wird. Wir verwenden zu diesem Zweck ein <br>-Tag, das zum Einfügen eines Zeilenumbruchs im Text verwendet wird.
Unter Bezugnahme auf die vorherige Nummerierung:
Wir füllen das Formular mit den folgenden Daten aus
"First Name": m<br>yName
"Last Name": myLast
"Email Address": my@e.mail
"Comments": myComm
Die Dankesnachricht enthält unser HTML-Tag, das nicht verändert wurde, und es wird korrekt interpretiert, indem ein Zeilenumbruch in der Mitte der Nachricht eingefügt wird
"Thank you m
yName, form has been successfully submitted."

Bemerkung: „Gefällt uns. Wir können die Zeichen < und > verwenden, wir können HTML-Tags einfügen, die nicht bereinigt und interpretiert werden.“
Schritt weiter. Ersetzen wir das Formatierungstag durch etwas Nützlicheres, wie ein <script>-Tag, mit dem wir JavaScript-Code innerhalb der Seite einfügen und ausführen können.
Wir füllen das Formular mit den folgenden Daten aus
"First Name": m<script>alert(1);</script>yName
"Last Name": myLast
"Email Address": my@e.mail
"Comments": myComm
Die Dankesnachricht enthält unser HTML-Tag, das nicht verändert wurde und korrekt interpretiert wird, und zeigt uns eine Alert-Box an

Bemerkung 1: „Gefällt uns. Wir können beliebigen JavaScript-Code im Kontext des Benutzerbrowsers ausführen.“
Bemerkung 2: „Gefällt uns nicht. Der Benutzer, der das JavaScript ausführt, sind wir selbst.“
Die Situation ist folgende: Wir können JavaScript über eine von uns nicht kontrollierte Website im Kontext des Browsers eines Benutzers ausführen, aber dieser Benutzer ist momentan derjenige, der die Werte in das Formular eingibt. Das ist ziemlich nutzlos.
Die Idee ist: Gibt es eine Möglichkeit, die Dankesnachricht, die unseren auszuführenden Code enthält, erneut aufzurufen?
Kehren wir zu unserem ersten Submit zurück, dem der „Erkundung“ (oder führen wir die ersten Schritte erneut aus).
Durch Analyse des Netzwerkverkehrs oder des Seitenquellcodes erkennen wir, dass das Formular eine POST-Anfrage an die folgende Adresse sendet:
http://127.0.0.1/wordpress/cf-api/CF5ad9b3176c0f4
(Der letzte Teil kann variieren; passen Sie ihn in allen folgenden Beispielen entsprechend an.)
also an die Adresse:
http://<target>/cf-api/<form-id>