Skip to content

HTML5 Security - Die SQL-Datenbank

Mit HTML5 hält eine typische Server-Technik Einzug auf den Client: Die SQL-Datenbank. Und ihre typische Schwachstelle bringt sie gleich mit: SQL-Injection. Aber dagegen gibt es ja Prepared Statements mit parametrisierten Aufrufen, und auch die bringt das API mit. In sofern ist also eigentlich alles in Ordnung - man darf halt nur keine Fehler machen.

WebSQL - Monokultur stoppt Standard

WebSQL als Standard gibt es nicht, die Arbeit an der Spezifikation wurde eingestellt. Schuld daran sind die Entwickler der Webbrowser: Alle Implementierungen verwendeten das gleiche SQL-Backend (sqlite), und damit war die für eine Standardisierung nötige Vielfalt an Implementierungen nicht mehr gegeben. Es ist halt ziemlich schwierig, einen Standard-Entwurf immer weiter zu verbessern, bis letztendlich ein brauchbarer Standard heraus kommt, wenn sich die vorhandenen Implementierungen nicht ausreichend unterscheiden. Ohne Alternativen hätte man am Ende sqlite als Standard definiert, und das war ja nicht Sinn und Zweck des Ganzen.

Der fehlende Standard hindert die Browserhersteller aber nicht an der Implementierung der WebSQL-Datenbank, und wie man im Web immer wieder sieht, stören sich auch die Entwickler der Webanwendungen nicht daran. Denn sonst würden ja nicht immer wieder Webanwendungen fragen, ob Sie eine Datenbank anlegen dürfen. Bei mir dürfen sie das im Allgemeinen übrigens nicht. Warum sollte ich einer Webanwendung das Anlegen einer Datenbank erlauben, wenn ich gar nicht weiß, was die damit vor hat? Ich wüsste nicht, was zum Beispiel eBay auf meinen Rechner groß zu speichern hätte, eBay selbst verrät es mir beim Anlegen auch nicht - also ist es ja wohl nicht wichtig und die Zustimmung wird verweigert. Aber ich schweife ab. Zurück zum Thema:

Vorsicht vor SQL-Injection

JavaScript verleitet dazu, die SQL-Abfrage aus Strings zusammen zu setzen, so wie man es in JavaScript an allen möglichen Stellen sonst auch macht. Das könnte zum Beispiel so aussehen:

executeSql("SELECT spalte FROM tabelle WHERE wert=" + eingabe);

Wie in allen anderen Programmiersprachen auch führt das sehr schnell zu SQL-Injection-Schwachstellen. In diesem Fall könnte zum Beispiel mit der Eingabe

'nix' OR 1=1

die komplette Spalte ausgelesen werden, denn es ergibt sich damit die SQL-Abfrage

SELECT spalte FROM tabelle WHERE wert='nix' OR 1=1

Dieser Angriff ist für Webserver ein Klassiker, und jetzt gibt es ihn auch auf dem Webclient. Und genau so klassisch sind die Gegenmaßnahmen: Sie können die Eingaben prüfen oder maskieren oder die generell sichereren Prepared Statements mit parametrisierten Aufrufen verwenden, statt die Abfragen aus Strings mit vorgegebenem Code und Parametern zusammen zu setzen.

Da die Methode executeSql() des HTML5 Database API bereits für die Nutzung mit Prepared Statements ausgelegt ist, ist deren Nutzung kinderleicht. Im obigen Beispiel würde die Abfrage beispielsweise so aussehen:

executeSql("SELECT spalte FROM tabelle WHERE wert=?", [eingabe]);

Und schon wird die Eingabe nicht mehr als String, sondern als Literal interpretiert, und eingeschleuster SQL-Code kann die Abfrage nicht mehr verändern.

Vorsicht vor XSS

Für die SQL-Datenbank gilt das Gleiche wie für den Local Storage: Über eine XSS-Schwachstelle kann der Angreifer auf die darin gespeicherten Daten zugreifen.

Aber es gibt in diesem Zusammenhang auch eine gute Nachricht: Für die SQL-Datenbank gilt die Same Origin Policy. Und das bedeutet unter anderem, dass der Zugriff an das verwendete Protokoll gebunden ist. Auf über HTTPS gespeicherte Daten kann auch nur über HTTPS zugegriffen werden. Das entspricht dem Setzen des "Secure"-Flags bei Cookies, erfolgt aber automatisch.

Weitere Möglichkeiten, dem Browser einen zulässigen Zugriff von der jeweiligen Domain bzw. Webanwendung vorzutäuschen sind DNS-Hijacking, Beeinflussung der lokalen Namensauflösung (zum Beispiel durch eine Manipulation der hosts-Datei) oder Man-in-the-Middle-Angriffe, beispielsweise über einen Proxy. Die SQL-Datenbank ist also ein denkbar schlechter Ort, um sensitive Daten zu speichern.

Etwas Tarnung kann hilfreich sein

Um einem Angreifer die Daten nicht wie auf einem Tablett zu präsentieren, kann für die Datenbank ein eindeutiger, nicht zu erratender Name verwendet werden.

Wird die Webanwendung nur online genutzt, kann der Datenbankname zufällig erzeugt und auf dem Server gespeichert werden. Alle Skripte werden dann entsprechend angepasst, bevor sie an den Client gesendet werden.

Wird die Webanwendung auch offline genutzt, können die dafür verwendeten Skripte wie im Fall der reinen Online-Nutzung vom Server entsprechend vorbereitet werden. Besser ist es aber, ein Offline-Passwort zu verwenden, so dass es für einen Angreifer schwerer wird, den Datenbanknamen auf dem Client auszuspähen. Der Datenbankname wird dann aus Benutzername und Offline-Passwort gebildet.

Für die Online-Nutzung wird der Datenbankname auf dem Server gespeichert und wie im Fall der reinen Online-Nutzung vom Server in die Skripte integriert. Bei der Offline-Nutzung muss der Benutzer sich mit seinem Benutzernamen und dem Offline-Passwort (das aus nahliegenden Gründen nicht mit dem normalen Passwort identisch sein sollte) anmelden, woraufhin der Client-Code daraus den Datenbanknamen für den Zugriff bilden kann.

Im Fall eines XSS-Angriffs ist dieser Schutz aber wirkungslos, da der eingeschleuste JavaScript-Schadcode den Datenbanknamen aus dem laufenden JavaScript-Code der Webanwendung ausspähen kann.

Erst fragen, dann speichern!

Das folgende gilt sowohl für Local Storage als auch für SQL-Datenbank: Bevor Sie Daten auf dem Client speichern, bitten Sie den Benutzer um seine Erlaubnis. Die gilt dann nur für den aktuellen Rechner. Nur so können Sie vermeiden, versehentlich Daten auf einem öffentlichen Rechner, zum Beispiel in einem Internet Café, zu speichern.

Mehr zur SQL-Datenbank erfahren Sie in meinem auf deutsch und englisch erhältlichen eBook "HTML5 Security". Ab der nächsten Folge sehen wir uns die Kommunikationsmöglichkeiten von HTML5 an. Den Anfang machen Cross Origin Requests.

Carsten Eilers


Übersicht über alle Artikel zum Thema

HTML5 Security - Eine Einführung
HTML5 Security - SVG und Resident XSS
HTML5 Security - Formulare auf Abwegen
HTML5 Security - Gift für den Application Cache
HTML5 Security - Der Local Storage
HTML5 Security - Die SQL-Datenbank
HTML5 Security - Cross Origin Requests
HTML5 Security - Gefährliche WebSockets
HTML5 Security - postMessage() sicher nutzen

Trackbacks

Keine Trackbacks