Übersicht über die Sicherheitsanfälligkeit in Mikrotik Winbox. Oder eine große Datei

Guten Tag, wahrscheinlich haben viele von der jüngsten Sicherheitslücke in Mikrotik-Routern gehört, mit der Sie die Passwörter aller Benutzer extrahieren können. In diesem Artikel möchte ich das Wesentliche dieser Sicherheitsanfälligkeit detailliert zeigen und analysieren.
Das gesamte Material wird nur zu Informationszwecken bereitgestellt, sodass der Code, der die Sicherheitsanfälligkeit ausnutzt, nicht hier ist. Wenn Sie nicht daran interessiert sind, die Ursachen und die interne Struktur einer bestimmten Sicherheitsanfälligkeit zu erfahren, können Sie weiterlesen.

Fangen wir an


Als erstes muss die Verkehrsanalyse zwischen dem Winbox-Client und dem Gerät gestartet werden
Winbox ist eine Anwendung für das Windows-Betriebssystem, die die Weboberfläche genau wiederholt und das Gerät mit integriertem Router-Betriebssystem verwaltet und konfiguriert. 2 Betriebsarten unterstützt, TCP und UDP
Bevor Sie beginnen, sollten Sie die Verkehrsverschlüsselung in Winbox deaktivieren. Dies geschieht wie folgt: Sie müssen das Kontrollkästchen Extras -> Erweiterter Modus aktivieren. Danach ändert sich die Schnittstelle wie folgt:


Deaktivieren Sie den sicheren Modus . Starten Sie Wireshark und versuchen Sie, sich am Gerät anzumelden:


Wie Sie unten sehen können, wird nach der Autorisierung eine Listendatei angefordert und ihr Inhalt dann vollständig an uns übertragen. Es scheint, dass alles in Ordnung ist, aber schauen wir uns den Anfang dieser Sitzung an:


Zu Beginn sendet Winbox genau dasselbe Paket, in dem die Listendatei angefordert wird:


Betrachten Sie seine Struktur:

  1. 37010035 - Packungsgröße
  2. M2 ist eine Konstante, die den Start eines Pakets angibt
  3. 0500ff01 - Variable 0xff0005 im Wert True
  4. 0600ff09 01 - Variable 0xff0006 in Wert 1 (Anzahl der übertragenen Pakete)
  5. 0700ff09 07 - Variable 0xff0007 bei Wert 7 (Datei im Lesemodus öffnen)
  6. 01000021 04 6967374 - Variable 0x01000001 Zeichenfolgenliste mit 4 Bytes (normalerweise ist diese Variable für den Namen der Datei verantwortlich)
  7. 0200ff88 02 ... 00 - ein Array von 0xff0002 mit einer Größe von 2 Elementen
  8. 0100ff88 02 ... 00 - Ein Array von 0xff0001 mit einer Größe von 2 Elementen

Durch die Protokollumkehr und die entsprechenden Binärdateien auf Client- und Serverseite konnte die Struktur des Protokolls, über das Winbox mit dem Gerät kommuniziert, wiederhergestellt und in größerem Umfang verstanden werden.

Beschreibung des NvMessage-Protokolls

Feldtypen (Name: Digitale Bezeichnung)


  • u32: 0x08000000
  • u32_array: 0x88000000
  • Zeichenfolge: 0x20000000
  • string_array: 0xA0000000
  • addr6: 0x18000000
  • addr6_array: 0x98000000
  • u64: 0x10000000
  • u64_array: 0x90000000
  • true: 0x00000000
  • false: 0x01000000
  • bool_array: 0x80000000
  • Nachricht: 0x28000000
  • message_array: 0xA8000000
  • roh: 0x30000000
  • raw_array: 0xB0000000
  • u8: 0x09000000
  • be32_array: 0x88000000

Arten von Fehlern (Name: Digitale Bezeichnung)


  • SYS_TO: 0xFF0001
  • STD_UNDOID: 0xFE0006
  • STD_DESCR: 0xFE0009
  • STD_FINISHED: 0xFE000B
  • STD_DYNAMIC: 0xFE0007
  • STD_INACTIVE: 0xFE0008
  • STD_GETALLID: 0xFE0003
  • STD_GETALLNO: 0xFE0004
  • STD_NEXTID: 0xFE0005
  • STD_ID: 0xFE0001
  • STD_OBJS: 0xFE0002
  • SYS_ERRNO: 0xFF0008
  • SYS_POLICY: 0xFF000B
  • SYS_CTRL_ARG: 0xFF000F
  • SYS_RADDR6: 0xFF0013
  • SYS_CTRL: 0xFF000D
  • SYS_ERRSTR: 0xFF0009
  • SYS_USER: 0xFF000A
  • SYS_STATUS: 0xFF0004
  • SYS_FROM: 0xFF0002
  • SYS_TYPE: 0xFF0003
  • SYS_REQID: 0xFF0006

Fehlerwerte (Name: Digitale Bezeichnung)


  • ERROR_FAILED: 0xFE0006
  • ERROR_TOOBIG: 0xFE000A
  • ERROR_EXISTS: 0xFE0007
  • ERROR_NOTALLOWED: 0xFE0009
  • ERROR_BUSY: 0xFE000C
  • ERROR_UNKNOWN: 0xFE0001
  • ERROR_BRKPATH: 0xFE0002
  • ERROR_UNKNOWNID: 0xFE0004
  • ERROR_UNKNOWNNEXTID: 0xFE000B
  • ERROR_TIMEOUT: 0xFE000D
  • ERROR_TOOMUCH: 0xFE000E
  • ERROR_NOTIMP: 0xFE0003
  • ERROR_MISSING: 0xFE0005
  • STATUS_OK: 0x01
  • STATUS_ERROR: 0x02

Feldstruktur in einem Paket


Am Anfang eines Feldes steht sein Typ - 4 Bytes (3 Bytes - der Zweck der Variablen, dazu später mehr 1 Byte - direkt der Typ dieser Variablen), dann beträgt die Länge 1-2 Bytes und der Wert selbst.

Arrays


Bildlich kann das Array durch die folgende Struktur beschrieben werden:

struct Array { uint32 type; uint8 count; uint32 item1; uint32 item2; ... uint8 zero; } 

Typ (4 Bytes) / Anzahl der Elemente (1 Byte) / Elemente (4 Bytes) / Am Ende des Bytes \ x00

Linien


Strings sind nicht nullterminiert, haben aber eine klar definierte Länge:

 struct String { uint32 type; uint8 length; char text[length]; } 

Die Zahlen


Der einfachste Typ im Paket kann als Werttyp dargestellt werden:

 struct u* { uint32 type; uint8/32/64 value; } 

Je nach Typ hat der Wert eine entsprechende Bitdimension.

Boolescher Typ


Die Größe des Feldes beträgt 4 Bytes, das High-Byte ist für den Wert (True \ False) verantwortlich, die unteren 3 Bytes für die Zuweisung der Variablen

Zusätzlich enthält jedes Paket:

  1. spezielle Markierungen, die den Beginn des Pakets anzeigen
  2. Paketgröße
  3. große Paketkontrollmärkte


Konstanten gefunden


  • 0xfe0001 - Enthält die Sitzungskennung (1 Byte)
  • 0xff0006 - Nummer des gesendeten Pakets (1 Byte)
  • 0xff0007 - Dateizugriffsmodus (1 Byte)

Dateizugriffsmodi

  • 7 - zum Lesen geöffnet
  • 1 - zur Aufnahme geöffnet
  • 6 - Verzeichnis erstellen
  • 4 - lesen
  • 5 - löschen


Wenn wir nun wissen, wie das Protokoll funktioniert, können wir zufällig die benötigten Pakete generieren und beobachten, wie das Gerät darauf reagiert.

Auf der Geräteseite ist die ausführbare Datei / nova / bin / mproxy für die Verarbeitung der Pakete verantwortlich. Da die Namen der Funktionen nicht gespeichert wurden, habe ich eine Funktion aufgerufen, die das Paket verarbeitet und Entscheidungen darüber trifft, was mit der Datei file_handler () geschehen soll . Schauen Sie sich die Funktion selbst an:


PS Der Code, der uns interessiert, ist mit Pfeilen markiert.

Schritt 1


Wenn Sie ein Paket zum Öffnen einer Datei zum Lesen erhalten, wird die Verarbeitung von diesem Block aus gestartet:


Zu Beginn wird der Dateiname mit der Funktion nv :: message :: get <nv :: string_id> () aus dem Paket extrahiert.

Als nächstes teilt die Funktion tokenize () die resultierende Zeichenfolge in separate Teile auf, wobei das Zeichen " / " als Trennzeichen verwendet wird.

Das resultierende Array von Zeichenfolgen wird an die Funktion path_filter () übergeben , die das empfangene Array von Zeichenfolgen auf das Vorhandensein von " .. " überprüft und im Fehlerfall einen Fehler ERROR_NOTALLOWED (0xFE0009) zurückgibt.


PS ERROR_NOTALLOWED wird auch in der Antwort empfangen, wenn keine Dateiberechtigungen vorliegen

Wenn alles in Ordnung ist, wird der Pfad zum Verzeichnis webfig oder pckg an den Anfang des Dateinamens gekettet

Schritt 2



Wenn alles gut gegangen ist, wird die Datei geöffnet und ihr Handle im globalen Objekt gespeichert.

Wenn die Datei nicht geöffnet werden konnte, wird in der Antwort eine Fehlermeldung angezeigt: Die Quelldatei kann nicht geöffnet werden .


Um den Inhalt einer Datei zu erhalten, müssen also drei Bedingungen erfüllt sein:

  1. Der Dateipfad enthält nicht " .. ";
  2. Es gibt Rechte, auf die Datei zuzugreifen.
  3. Die Datei existiert und kann erfolgreich geöffnet werden.

Versuchen wir nun, einige Pakete zu senden, um die Funktionalität dieser Funktion zu testen:

 $ ./untitled.py -t 192.168.88.1 -f /etc/passwd Error: SYS_ERRNO => ERROR_FAILED Error: SYS_ERRSTR => cannot open source file $ ./untitled.py -t 192.168.88.1 -f /../../../etc/passwd Error: SYS_ERRNO => ERROR_NOTALLOWED $ ./untitled.py -t 192.168.88.1 -f //./././././../etc/passwd Error: SYS_ERRNO => ERROR_FAILED Error: SYS_ERRSTR => cannot open source file 

Also! Aber das ist schon seltsam ... Wir erinnern uns, dass ERROR_NOTALLOWED angezeigt wird, wenn die Prüfung in path_filter () nicht bestanden wurde, andernfalls würden wir immer noch eine Nachricht über das Fehlen von Zugriffsrechten erhalten, aber im letzteren Fall stellt sich heraus, dass die Datei im Verzeichnis der obersten Ebene durchsucht wurde?

Versuchen wir es so:

 $ ./untitled.py -t 192.168.88.1 -f //./.././.././../etc/passwd xvM2        1Enobody:*:99:99:nobody:/tmp:/bin/sh root::0:0:root:/home/root:/bin/sh 

Und es hat funktioniert. Aber warum? Schauen wir uns den Funktionscode path_filter () an :


Der Code zeigt deutlich, dass die Suche nach dem Auftreten von " .. " in dem resultierenden Array von Zeichenfolgen tatsächlich stattfindet. Aber dann, der interessanteste Teil, habe ich dieses Fragment rot hervorgehoben.
Der Kern dieses Codes besteht darin, dass: Wenn das vorherige Element auch " .. " ist, wird die Prüfung als fehlgeschlagen betrachtet. Ansonsten bedenken Sie, dass alles in Ordnung ist.

Das heißt, Damit alles funktioniert, müssen Sie nur " /./ " und " /../ " abwechseln, um erfolgreich durch alle Verzeichnisse zu navigieren und zu einer beliebigen Ebene des FS abzusteigen.


Mal sehen, wie die Mikrotik-Entwickler das Problem behoben haben:


Pseudo-C-Code-Vergleich


Das Verlassen des Verifizierungszyklus erfolgt nun beim ersten Erkennen von " .. ". Es ist mir allerdings nicht ganz klar, warum sie eine Prüfung für das Auftreten eines Punktes hinzugefügt haben. Und aufgrund einer Änderung des Aktivierungsmechanismus des Entwicklers gibt es leider keine Möglichkeit, dies in der Dynamik zu sehen.

Zusammenfassend


  1. Das Router-Betriebssystem verarbeitet eingehende Pakete bereits vor der Benutzerautorisierung ohne Probleme
  2. Aufgrund eines falschen Filters erhalten wir Zugriff auf jede Datei

In Anbetracht der vorherigen Absätze können wir auf einfache Weise: Dateien erstellen, löschen, lesen und schreiben sowie beliebige Verzeichnisse erstellen

Es ist daher nicht verwunderlich, dass der Zugriff zum Lesen von Dateien ohne Autorisierung das erste war, was getan wurde, indem die Datei mit Benutzerkennwörtern gelesen wurde. Glücklicherweise verfügt das Netzwerk über zahlreiche Informationen darüber, wo es sich befindet und wie Daten daraus extrahiert werden können.

Diese Sicherheitsanfälligkeit kann auch ein hervorragender Ersatz für die bisher bekannte Möglichkeit sein, den Entwicklermodus zu aktivieren, da Sie das Gerät nicht neu starten müssen. Sichern / Wiederherstellen der Konfigurationsdatei jetzt.

Source: https://habr.com/ru/post/de416067/


All Articles