Schlüssel für Bytecode Array Encoding auslagern
Geben Sie mit vmBytecodeArrayEncodingKey Ihren eigenen Schlüssel zur Verschlüsselung des VM-Bytecodes vor und reichen Sie ihn zur Laufzeit über einen Key-Getter zurück - außerhalb des Bundles gehalten, aus dem Client-Speicher gelesen oder von Ihrem Backend abgerufen.
Ansehen
Obfuscator.io Async Executor: Async Bytecode Key Getter and Async-Only VM Virtualization
Obfuscator.io Custom Bytecode Key: Compile-Time Key and Runtime Key Getter (Cookie, Fetch, Decoy Key)
Was diese Optionen bewirken
vmBytecodeArrayEncoding verschlüsselt das VM-Bytecode-Array, damit es nicht als
Klartext in der Ausgabe steht. Standardmäßig wird der Schlüssel aus der Umgebung abgeleitet und auf dem Client
rekonstruiert, sodass Sie nie damit in Berührung kommen. Das ist bequem, aber das Schlüsselmaterial befindet sich
weiterhin im Bundle.
Mit zwei Optionen können Sie den Schlüssel aus dem Bundle herausnehmen und selbst verwalten:
vmBytecodeArrayEncodingKey- der Schlüssel, den Sie zur Kompilierzeit angeben. Ist er gesetzt, wird er anstelle des standardmäßig aus der Umgebung abgeleiteten Schlüssels verwendet und nicht in die obfuskierte Ausgabe eingebettet.vmBytecodeArrayEncodingKeyGetter- ein JavaScript-Ausdruck, der denselben Schlüssel zur Laufzeit zurückgibt. Er wird wortwörtlich eingebettet und im Browser ausgewertet, sobald der obfuskierte Code geladen wird.
Es geht um Trennung: Da der Schlüssel nicht im Code steht, kann eine rein statische Analyse des Bundles ihn nicht wiederherstellen. Zur Laufzeit muss er trotzdem vorhanden sein, damit der Code läuft, er ist also nicht wirklich geheim. Sie entscheiden jedoch, woher er kommt und wer ihn zu sehen bekommt.
Diese beiden Optionen gehören zusammen, und der Obfuscator setzt das durch: Wird nur eine von beiden gesetzt, ist das ein
Validierungsfehler beim Build (vmBytecodeArrayEncodingKey allein hat keine Möglichkeit, den Schlüssel zur Laufzeit zu
beschaffen; ein Getter allein hat keinen Schlüssel zur Kompilierzeit, mit dem er übereinstimmen könnte). Außerdem wirken
sie nur, wenn das Bytecode-Array tatsächlich verschlüsselt wird. Daher muss auch vmBytecodeArrayEncoding: true aktiviert
sein - oder vmSelfDefending: true, das vmBytecodeArrayEncoding intern erzwingt. Setzen Sie beide Schlüssel zusammen
mit einer dieser Optionen.
Wie die beiden Schlüssel kombiniert werden
Ihr Schlüssel wird nie allein verwendet, sondern auf beiden Seiten mit einem internen Schlüssel gemischt, den der Obfuscator kontrolliert:
- Kompilierzeit.
vmBytecodeArrayEncodingKeywird mit einem vom Obfuscator abgeleiteten internen Schlüssel kombiniert, und das Bytecode-Array wird mit dem daraus entstehenden gemischten Schlüssel codiert. - Laufzeit. Der Wert, zu dem Ihr
vmBytecodeArrayEncodingKeyGetteraufgelöst wird, wird mit demselben internen Schlüssel kombiniert, der auf dem Client aus verschiedenen Laufzeitfaktoren rekonstruiert wird, um den Bytecode zu decodieren.
Da beide Seiten Ihren Schlüssel mit dem internen Schlüssel mischen, muss der Getter exakt denselben String liefern,
den Sie als vmBytecodeArrayEncodingKey übergeben haben. Keiner der beiden Teile genügt allein: Ihr Schlüssel ohne den
internen Schlüssel kann den Bytecode nicht decodieren, und der interne Schlüssel ist ohne Ihren wertlos. Deshalb schützt
tatsächlich die Kontrolle darüber, wer Ihren Schlüssel erhält, den Code.
Den Schlüssel zur Laufzeit bereitstellen
Standardmäßig ist der Getter synchron: Der Ausdruck muss den Schlüssel sofort zurückgeben, wenn der obfuskierte Code
geladen wird. Lesen Sie ihn aus einer Quelle, die auf dem Client bereits vorhanden ist: einem Cookie, localStorage,
einer globalen Variablen oder einem vom Server eingefügten DOM-Element.
Der Schlüssel muss vor der Ausführung des obfuskierten Codes vorhanden sein:
Andere synchrone Quellen funktionieren genauso. Wählen Sie diejenige, die Ihre Anwendung ohnehin befüllt:
Halten Sie den Schlüssel aus derselben Datei bzw. demselben Skript wie den obfuskierten Code heraus. Ihn dort
einzubetten, macht den ganzen Zweck zunichte: Eine statische Analyse des Bundles würde sowohl den Code als auch seinen
Schlüssel wiederherstellen. Legen Sie ihn in einer separaten Quelle ab, und übergeben Sie den vmBytecodeArrayEncodingKey
für die Kompilierzeit aus einer Umgebungsvariablen oder einem Secret, statt ihn zu committen.
Den Schlüssel vom Backend abrufen (asynchron)
Erfordert vmAsyncExecutor · v7.3.0+Ein synchroner Getter kann nur lesen, was bereits auf dem Client vorhanden ist. Um den Schlüssel von Ihrem Server
abzurufen, damit Sie ihn hinter eine Authentifizierung stellen und widerrufen können, muss der Getter asynchron sein, und
das erfordert vmAsyncExecutor. Mit aktiviertem Async Executor darf der
Getter ein Promise zurückgeben, und die VM wartet darauf, bevor sie ausgeführt wird.
Das Aktivieren von vmAsyncExecutor schränkt auch ein, was virtualisiert wird: In diesem Modus werden nur die
äußersten async-Funktionen in die VM kompiliert, synchroner Code wird nicht virtualisiert (die übrige Obfuskierung gilt
weiterhin). Wenn Ihr Programm überwiegend
synchron ist, verpacken Sie den zu schützenden Code in eine async-Funktion, damit er weiterhin abgedeckt wird; die
vollständige Regel finden Sie unter vmAsyncExecutor.
Ein Getter, der ein Promise zurückgibt, erfordert vmAsyncExecutor. Das lässt sich beim Build nicht prüfen, daher
schlägt ein Promise-Getter bei ausgeschaltetem vmAsyncExecutor zur Laufzeit fehl.
Entscheiden Sie auf dem Server anhand dessen, was Ihre Anwendung als vertrauenswürdig ansieht, welcher Schlüssel
zurückgegeben wird: eine validierte Sitzung, eine Lizenzprüfung und so weiter. Origin oder Referer allein
authentifizieren keinen Aufrufer, und GET-Anfragen vom selben Ursprung können Origin weglassen. Der Kniff: Statt nicht
vertrauenswürdige Aufrufer abzuweisen, geben Sie einen falschen Schlüssel zurück (unten VM_DECOY_KEY). Der
geschützte Code scheitert dann von selbst (Fehler, falsche Ergebnisse oder eine Seite, die nicht mehr reagiert). Das ist unauffälliger
als ein offensichtliches 401, das einem Angreifer genau verrät, was er umgehen muss.
Deaktivieren Sie das Caching der Antwort, damit der Schlüssel eines Aufrufers nie an einen anderen ausgeliefert wird. Binden Sie Schlüssel an die richtige Build-Version, und deployen Sie Schlüssel und Bundles gemeinsam. Ein Client, der den echten Schlüssel erhält, kann ihn zur Laufzeit dennoch einsehen.
Liefern Sie über diesen Endpunkt exakt denselben String aus, den Sie beim Build als vmBytecodeArrayEncodingKey
übergeben haben. Der Getter oben ruft eine relative URL (/api/vm-key) ab. Eine Kopie des Bundles, die auf einem
anderen Origin gehostet wird, fordert /api/vm-key daher von diesem Origin an und erhält Ihren Schlüssel nie; den
Köder-Schlüssel bekommt ein Aufrufer, der Ihren Endpunkt zwar erreicht, aber ohne vertrauenswürdige Sitzung (eine
nicht authentifizierte Anfrage, ein gestohlenes Bundle, das über Ihren Origin weitergeleitet wird). In beiden Fällen
kommt der echte Schlüssel nie an, und der geschützte Code wird nicht ausgeführt.
Was als „gültig“ gilt, hängt ganz von Ihrer Anwendung ab: eine authentifizierte Sitzung, eine signierte Lizenz oder eine
beliebige Kombination. Was auch immer den Schlüssel erzeugt, verpacken Sie es in ein Promise, und der Async
Executor wartet darauf, bevor er die VM ausführt.
Wenn der Schlüssel nicht übereinstimmt
Der obfuskierte Code funktioniert nur, wenn der Getter exakt denselben Schlüssel zurückgibt, der bei der Obfuskierung
verwendet wurde. Weichen die Schlüssel voneinander ab oder gibt der Getter undefined, null oder einen leeren String
zurück, scheitert der Code zur Laufzeit: Er liefert falsche Ergebnisse, wirft einen gewöhnlichen Laufzeitfehler oder
reagiert nicht mehr.
Es gibt bewusst keine eigene, schlüsselspezifische Fehlermeldung: Ein falscher Schlüssel ist von keinem anderen Laufzeitfehler zu unterscheiden. Wenn ein VM-geschütztes Bundle also erst dann Fehler wirft, falsche Ergebnisse liefert oder einfriert, sobald diese Option im Spiel ist, prüfen Sie zuerst den Weg des Schlüssels: ob der Getter auf der Seite aufgelöst wird, einen nicht leeren String zurückgibt und denselben Wert liefert, mit dem Sie den Build erstellt haben.
