© Teguh Jati Prasetyo/Shutterstock.com
Mit Obfuscators seinen JavaScript-Code schützen

Getarntes JavaScript


Entweder man liebt sie, oder man hasst sie: Die View-Source-Option ermöglicht Nutzern und Entwicklern die Analyse der hinter einer Webapplikation stehenden Logik. Mit Obfuscators kann man bis zu einem gewissen Grad gegensteuern, um geistiges Eigentum vor neugierigen Konkurrenten zu schützen.

Das Feld der Obfuscation von JavaScript ist weit: Es reicht von einfachen Minimierungswerkzeugen bis zu kompletten serverbasierten Lösungen. In diesem Artikel möchte ich Ihnen einige Möglichkeiten konzeptuell vorstellen, damit Sie mehr über die verschiedenen Vorgehensweisen erfahren. Schon an dieser Stelle sei angemerkt, dass Obfuscators keinen Ersatz für eine serverseitige Verifikation darstellen. Ein als Fuzzing bezeichnetes Verfahren erlaubt Angriffe gegen extrem komplizierte Protokolle – der Ratschlag, vom Client eingehende Informationen als toxisch zu betrachten, gilt auch bei Verwendung aller in diesem Artikel besprochenen Methoden.

Mit Brachialgewalt

Wie so oft in der Welt der Informatik gilt auch hier, dass es keine universell sichere Lösung gibt. Die Aufgabe aller besprochenen Verfahren ist, einen Angriff so teuer zu machen, dass er sich für Hacker nicht lohnt. Hat man es mit extrem empfindlichem oder fragwürdigem geistigen Eigentum zu tun, so ist die Nutzung von Obfuscators oft nicht ausreichend. In diesem Fall empfiehlt es sich, auf eine Client-Server-Architektur zu setzen. Ein Beispiel dazu ist in Abbildung 1 zu sehen, bei der ein fiktives Berechnungsprogramm in zwei Komponenten aufgeteilt wird.

hanna_obfuscation_1.tif_fmt1.jpgAbb. 1: Liegt die Logik am Server, ist der Clientcode weitgehend wertlos

Diese auf den ersten Blick seltsame Vorgehensweise ist in Zeiten von WebSocket und Co. problemlos implementierbar. Überraschenderweise beklagen sich Nutzer in der Praxis nur wenig, wenn ihr Programm ohne Netzwerkverbindung nicht funktioniert. Der Autor testete das unter Firefox OS: Trotz permanenter Verbindung zum Server erhielt der hauseigene wissenschaftliche Taschenrechner beste Bewertungen. In eine ähnliche Kerbe schlägt die Nutzung eines Produkts wie beispielsweise Emscripten. Das von Alon Zakai entwickelte Framework erlaubt die Kompilation von C-Code, der danach in einer virtuellen Maschine zur Ausführung kommt.

Der Code befindet sich zwar auf der Maschine des Klienten, ist aber extrem schwer zu analysieren. Emscripten-Code ist von der Komplexität her mit Qt und Co. vergleichbar. Beschwerden über Disassembler-Attacken auf C++-Programme findet man, anders als in der Welt von Java oder .NET, nur sehr selten.

Eine Frage des Konzepts

Möchten Sie nicht auf Brachialmethoden setzen, so steht eine Vielzahl von Obfuscators zur Verfügung. Sie verhalten sich im Großen und Ganzen so, wie man es aus der Java-Welt kennt. Links kommt lesbarer Code in die Blackbox, die auf der anderen Seite verfremdeten Code ausspielt. Im Idealfall ist das Chiffrat sofort ausführbar. Dass die Praxis anders aussieht, sei schon hier angemerkt.

Bei der Arbeit mit JavaScript Obfuscators ist eine Besonderheit zu beachten. Während Obfuscators für andere Programmiersprachen normalerweise durch die Reduzierung des Programmumfangs zu einer Beschleunigung des Programms beitragen, wirken sich JavaScript-Verschwurbler oft negativ auf die Gesamtperformance aus. Die Ursache dieses paradoxen Verhaltens liegt an Zweierlei: Erstens ist der verwurstete Code oft umfangreicher als die Basisvariante, was die Ausführung verlangsamt. Das ist nicht vermeidbar, da das Einführen von Arrays, globalen Sprungtabellen und ähnlichen Nettigkeiten naturgemäß Rechenleistung kostet.

Ein zweites, und noch lästigeres Antipattern, ist die Verwurstung von bei Drittanbietern bezogenen Bibliotheken. Zur Erklärung: Verwenden Sie eine häufige Version von jQuery, so kann der Browser diese aus einem CDN (oder sogar aus seinem lokalen Cache) beziehen und auf diverse Arten beschleunigen. Eine von Ihnen verschlüsselte Variante der Bibliothek müsste stattdessen komplett neu eingelesen und geparst werden, was wertvolle Zeit verschlingt.

Der von Timofey Kachalov entwickelte JavaScript Obfuscator ist ein Klassiker der Szene. Er unterscheidet sich von Konkurrenten wie UglifyJS dadurch, dass er sich nicht nur auf das Entfernen von Steuerzeichen und sonstige Lustigkeiten beschränkt, sondern auch Eingriffe in die Codestruktur durchführt, um die Nutzung von JavaScript-Verschönerungsprogrammen zu erschweren. Auf Wunsch integriert der Obfuscator sogar Checkroutinen, die den Code bei Erkennung der Änderung des Formats automatisch deaktivieren.

Auch wenn unter https://obfuscator.io eine Onlineversion des Werkzeugs bereitsteht, empfiehlt sich für ernsthafte Versuche die Nutzung einer lokalen Installation. Hierzu ist Node.js erforderlich, auf der Workstation des Autors war Version 10.1.0 installiert. npm ist für das Herunterladen verantwortlich und lag unter Ubuntu 14.04 in Form der extern heruntergeladenen Version 5.6.0 vor.

JavaScript Obfuscator lässt sich auf mehrere Arten installieren. Wer nicht mit einem in Node.js lebenden Projekt arbeitet, sollte das Programm im Interesse der Bequemlichkeit global installieren. Hierzu dient folgende Kommandosequenz (falls es zu Berechtigungsfehlern kommt, müssen Sie vor dem Aufruf noch sudo platzieren):

tamhan@TAMHAN14:~$ npm install -g javascript-obfuscator . . . + javascript-obfuscator@0.18.1 added 103 packages in 8.074s

Prüfen Sie nach dem Durchlaufen des Kommandos die erfolgreiche Installation, indem Sie das Kommando javascript-obfuscator in Ihr Terminal eingeben. Bei richtiger Parametrisierung präsentiert sich das Ergebnis wie in Abbildung 2 gezeigt.

hanna_obfuscation_2.tif_fmt1.jpgAbb. 2: Der JavaScript Obfuscator ist einsatzbereit

Zur Demonstration der Obfuskationsleistungen wollen wir im nächsten Schritt ein kleines Beispielprogramm realisieren. Sein Korpus präsentiert sich wie in Listing 1 zu sehen.

Listing 1: Beispielprogramm zur Darstellung von Obfuskationsleistungen

var myString = "Hallo SUS" function doTheTrick(){ var chiffrat; chiffrat = rot13(myString); return chiffrat; } function rot13(str) { var re = new RegExp("[a-z]", "i"); var min = 'A'.charCodeAt(0); var max = 'Z'.charCodeAt(0); var factor = 13; var result = ""; str = str.toUpperCase(); for (var i=0; i<str.length; i++) { result += (re.test...

Neugierig geworden? Wir haben diese Angebote für dich:

Angebote für Gewinner-Teams

Wir bieten Lizenz-Lösungen für Teams jeder Größe: Finden Sie heraus, welche Lösung am besten zu Ihnen passt.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang