
Sichere Isolation und Kapselung von DOM-Bäumen mittels ShadowDOM
⚠️ EXPERIMENTELL [WIP] - VERWENDUNG AUF EIGENE GEFAHR (mehr erfahren)
Nehmen Sie es mit LavaDome auf - besuchen Sie die Demo-App, öffnen Sie die Konsole, und tun Sie alles in Ihrer Macht Stehende, um das Geheimnis aus der LavaDome-Instanz zu stehlen (melden Sie Ihren Erfolg)
Nach heutigen Webstandards gibt es keinen etablierten Weg, DOM-Teilbäume auf sichere Weise selektiv zu isolieren. Mit anderen Worten: Wir können den Zugriff auf Abschnitte des DOM nicht kontrollieren, indem wir einigen Parteien Zugriff gewähren, während wir anderen den Zugriff verwehren, wenn sie dieselbe JavaScript-Ausführungsumgebung teilen.
Wir leben in einer Welt, in der wir dem Code in unseren eigenen Apps nicht mehr vertrauen können, und die Ausführung unter demselben Ursprung (Same-Origin) garantiert keine Sicherheit. Um Geheimnisse im Frontend zu sichern, müssen wir in der Lage sein, dem Benutzer Inhalte zu präsentieren und gleichzeitig sicherzustellen, dass sie nicht durch JavaScript-Code kompromittiert werden können, der unter demselben Ursprung ausgeführt wird.

Derzeit wird dieser vertrauliche Inhalt einfach an das DOM angehängt, sobald er exportiert wird, wodurch er für alle Entitäten, die in derselben App laufen, vollständig zugänglich ist. Das heißt, Codeteile, die keinen Zugriff auf den privaten Schlüssel haben sollten, könnten ihn leicht im Klartext extrahieren, solange der bösartige Code Zugriff auf das DOM hat.
Aber seien Sie versichert. Wir glauben, dass dies ein lösbares Problem ist 👇
LavaDome unterstützt derzeit Vanilla JavaScript und React (weitere in Kürze)
import { LavaDome as LavaDomeJavaScript } from '@lavamoat/lavadome-javascript';
const root = document.getElementById('root'); const lavadome = new LavaDomeJavaScript(root); lavadome.text(secret); lavadome.copy(); // copy to clipboard
### [React](https://github.com/lavamoat/lavadome/blob/main/packages/react)```javascript
import { LavaDome as LavaDomeReact, toLavaDomeToken } from '@lavamoat/lavadome-react';
function Secret({ text }) {
const {token, copy} = toLavaDomeCapabilities(text);
return <>
<a onClick={copy}> copy to clipboard </a>
<LavaDomeReact token={token} />
</>;
}
Zusätzlich zum Root-Knoten akzeptieren alle Konstruktoren ein optionales options-Argument als 2. Argument:```javascript // javascript new LavaDomeJavaScript(root, { // boolean unsafeOpenModeShadow: false, });
// react function Secret({ text }) { const {token} = toLavaDomeCapabilities(text); return <LavaDomeReact token={token} // boolean unsafeOpenModeShadow={false} /> }
### Sichere Verwendung
Aufgrund der Einschränkungen des Webkerns gibt es bei der sicheren Integration von LavaDome einige Punkte zu beachten, die aktive Arbeit des integrierenden Entwicklers erfordern:
#### Ausführungsreihenfolge
LavaDome ist wie jede andere JavaScript-Sicherheitssoftware immer anfällig für Code, der vor ihm ausgeführt wird.
Das bedeutet, dass LavaDome – abgesehen von Code, dem wir absolut vertrauen – das erste Codestück sein muss, das im Webanwendungsprogramm geladen wird.
Das bedeutet zwar nicht, dass der Entwickler es sofort nutzen muss (sondern nur dann, wenn er es benötigt), er muss das Programm jedoch so früh wie möglich einbinden.
Um dies korrekt (sicher) zu tun, muss es die erste import/require-Deklaration im gesamten Programm sein:```javascript
import '@lavamoat/lavadome-react';
import 'other-stuff';
console.log('Program starts here');
Auf diese Weise stellen wir sicher, dass sich LavaDome auf den sicheren Gebrauch vorbereiten kann.
Beachten Sie, dass dies in ähnlicher Weise für die übrigen LavaDome-Pakete gilt und nicht nur für @lavamoat/lavadome-react (weshalb es unnötig ist, mehr als eines davon zu importieren).
Springen Sie zu Security(defensive-coding), um mehr zu erfahren.
Aufgrund von Side-Channel-Angriffen und Webspezifischen Einschränkungen kann das Importieren externer Schriftarten eine erfolgreiche Technik gegen LavaDome sein. Da dies in den Bereichen von CSS eingebettet ist, ist die Behebung dieses Problems über LavaDome derzeit nicht möglich.
Glücklicherweise kann dies mithilfe der font-src-Direktive von CSP wirksam angegangen werden.
Um diese Art von Angriff zu entschärfen, stellen Sie sicher, dass Ihre Web-App das Abrufen von Schriftarten von unbekannten Servern nicht erlaubt.
Springen Sie zu Security(side-channeling), um mehr zu erfahren.
Text, der LavaDome vom Entwickler bereitgestellt wird, muss zu 100 % unvorhersehbar sein, andernfalls kann er angegriffen und preisgegeben werden.
Wenn Ihre App also "your key is 234789" anzeigen soll, bedeutet dies, dass Ihre DOM-Struktur wie folgt aussehen sollte:```html
your key is 234789
und darf nicht sein:```html
<span> <lavadome>your key is 234789</lavadome> </span>
Wechsle zu Sicherheit(Auffindbarkeit), um mehr zu erfahren.
Die Integration von LavaDome im Kontext des Testens kann knifflig sein, denn da LavaDome gute Arbeit beim Verbergen des Geheimnisses leistet, verbirgt es das Geheimnis auch ziemlich gut vor deinen Tests!
Um LavaDome erfolgreich in deine Testumgebung zu integrieren, brauchst du möglicherweise etwas Hilfe von LavaDomeDebug, das von @lavamoat/lavadome-core exportiert wird:```javascript
// IMPORT/USE FOR TESTING/DEBUGGING PURPOSES ONLY - NEVER IN PRODUCTION!
import { LavaDomeDebug } from '@lavamoat/lavadome-core';
Hier sind einige der Debugging-Utility-Methoden, die `LavaDomeDebug` exportiert und die dir beim Testen von Komponenten auf Basis von `LavaDome` helfen können:
#### `getTextByRoot()`
Wenn eine `LavaDome`-Root angehängt ist, extrahiert `getTextByRoot()` rekursiv das innere Geheimnis und rekonstruiert es. Damit das möglich ist, muss die `LavaDome`-Instanz ursprünglich mit der UNSAFE-Option `@unsafeOpenModeShadow` initialisiert worden sein, welche die inneren Schatten von `LavaDome` von außen zugänglich macht.