Sie möchten Snyk in Aktion erleben?
JavaScript-Sicherheit
Wissenswertes über JavaScript-Schwachstellen und Best Practices
Wie praktisch jede Programmiersprache ist auch JavaScript nicht frei von potenziellen Sicherheitsrisiken. Diese können unter anderem dazu führen, dass Daten manipuliert oder abgegriffen und Sitzungen umgeleitet werden. Zwar gilt JavaScript grundsätzlich als clientseitige Anwendung. Dennoch können etwaige Sicherheitsprobleme auch auf der Serverseite zu Komplikationen führen.
Die beste Verteidigungsstrategie besteht mit Blick auf die Sicherheit von JavaScript darin, sich die möglichen Schwachstellen bewusst zu machen und geeignete Gegenmaßnahmen zu ergreifen.
Die wichtigsten JavaScript-Schwachstellen 2023
Zu den häufigsten Sicherheitsrisiken in JavaScript gehören Cross-Site-Scripting (XSS), Schadcode, Man-in-the-Middle-Angriffe und Schwachstellen im Anwendungsquellcode. Doch die lassen sich verhindern, wenn der Code bereits während der Entwicklung auf mögliche Schwachstellen hin überprüft wird und Sicherheitsschulungen für die Entwickler angeboten werden.
In diesem Artikel werden die häufigsten JavaScript-Schwachstellen beschrieben. Zudem sollen aktuelle Gegenmaßnahmen und Prüftools vorgestellt werden (darunter Prüf- und Analyseprogramme und der JavaScript-Schwachstellen-Scanner).
Was wird unter JavaScript-Sicherheit verstanden?
Die JavaScript-Sicherheit beinhaltet die Untersuchung, Prävention, Abwehr und Beseitigung von Sicherheitsmängeln in Anwendungen, in denen JavaScript eingesetzt wird.
Bei JavaScript handelt es sich um ein grundlegendes Werkzeug zur Erstellung von Webanwendungen sowie Server-, Desktop- und auch Mobilanwendungen. Die Programmiersprache erfreut sich großer Beliebtheit, ist jedoch auch ein häufiges Ziel für Hacker und kann von mehreren Seiten aus angegriffen werden. Da JavaScript vorrangig im Frontend eingesetzt wird, wird hier zunächst auf JavaScript-Sicherheitsprobleme im Browser eingegangen.
Die Sicherheitsrisiken von JavaScript sind der Softwareindustrie durchaus bewusst. Gegenmaßnahmen beinhalten spezielle Sicherheitsprogramme für JavaScript und diverse Prüftools, mit denen die Anwendungen sicherer gemacht und die Risiken von JavaScript verringert werden können. Mit unserem JavaScript-Codechecker finden Sie Schwachstellen in Ihrem Code.
Welche Schwachstellen hat JavaScript?
Die häufigsten Sicherheitsrisiken in JavaScript sind Schadprogramme, Sitzungsdaten oder lokal gespeicherten Browserdaten abzugreifen, Benutzer zu ungewollten Handlungen zu verleiten und Schwachstellen im Quelltext von Webanwendungen auszunutzen.
Diese Liste ist keineswegs vollständig und bezieht sich vorrangig auf das Frontend von Webanwendungen.
8 Schwachstellen in JavaScript
Beginnen Sie mit Capture the Flag
Lernen Sie, wie Sie Capture the Flag-Herausforderungen lösen, indem Sie sich unseren virtuellen 101-Workshop auf Abruf ansehen.
1. Schwachstellen im Code
Oft werden Schwachstellen im Quellcode zusammen mit anderen JavaScript-Sicherheitslücken ausgenutzt. Dagegen hilft leider auch keine Verschleierung im Alleingang. Da JavaScript interpretiert und nicht kompiliert wird, ist es praktisch unmöglich, Hackern den Zugriff auf den Anwendungscode auf diesem Wege zu verwehren. Dennoch ist die Verschleierung eine sinnvolle Methode, da sie die Hacker bei ihren Ausspähversuchen ausbremst.
Eine weitere Schwachstelle im Quellcode ist die verbreitete Nutzung öffentlich zugänglicher Pakete und Bibliotheken. NPM ist ein bekannter Name in Sachen JavaScript und hat über eine Million Pakete im Angebot. Ein Angebot dieser Größenordnung ist ein echter Vorteil, bedeutet andererseits aber auch eine potenziell große Anzahl unbekannter Schwachstellen, die dann in Webanwendungen übernommen werden.
Zudem werden oft selbst für die einfachsten Arbeitsschritte ganze Pakete installiert, was die Anzahl der Abhängigkeiten übermäßig erhöht. Und das wiederum kann zu Sicherheitsproblemen und anderen gravierenden Konsequenzen führen.
Natürlich ist es sehr zeit- und arbeitsintensiv, alle potenziellen Schwachstellen zu ermitteln, die sich aus diesen Abhängigkeiten ergeben könnten. Hier schaffen glücklicherweise Prüftools Abhilfe, die das Verfahren automatisieren und somit beschleunigen.
Ein mehrgleisiger Ansatz zur Abwehr von Sicherheitsrisiken in JavaScript-Quellcode sollte die folgenden Schritte beinhalten:
Sensibilisierung der Entwickler für etablierte Verfahren
Ausreichende Prüfung des Anwendungscodes zur Erkennung möglicher Schwachstellen
Unit-Tests zur Überprüfung der ordnungsgemäßen Funktionsweise des Quellcodes und seiner sicheren Ausführung
Laufende Überwachung der Anwendungen und Suche nach JavaScript-Sicherheitsproblemen in Paketen und Bibliotheken von externen Anbietern
2. Ungewollte Skriptausführung
Die häufigste Form der ungewollten Skriptausführung ist das sogenannte Cross-Site-Scripting (XSS). Dabei ist vor allem die Interaktion mit dem Document Object Model (DOM) der jeweiligen Website interessant, da auf diese Weise Skripte auf Client-Computern eingebettet und ausgeführt werden können. Was allen XSS-Angriffen gemeinsam ist: Sie führen dazu, dass nicht vertrauenswürdige Skripte im Browser des Benutzers erscheinen und ausgeführt werden.
Besonders häufig geschieht dies in Internetforen, in denen die Nachrichten anderer Benutzer gelesen werden können. Wird HTML oder JavaScript in diesen Nachrichten nicht richtig verschlüsselt, können skrupellose Benutzer in einem Forum ein Skript posten.
Mit diesem Skript können alle anderen Benutzer dazu gebracht werden, durch Ausführen der Anwendung ungewollt am Angriff mitzuwirken. Denn der Schadcode sieht wie ein gewöhnlicher Bestandteil der Website aus.
Um XSS-Angriffe abzuwehren, sollten Benutzereingaben und Ausgaben bei der Verarbeitung stets bereinigt werden. Dies beinhaltet das Maskieren (Escaping), Filtern und Prüfen von Stringdaten.
3. Maskierung und Verschlüsselung von Benutzereingaben
XSS-Angriffe basieren auf bestimmten Sonderzeichen, die im HTML-, JavaScript- oder CSS-Code einer Website verwendet werden. Trifft der Browser bei der Darstellung der Website dann auf diese Zeichen, werden sie fälschlicherweise als Codebestandteil und nicht als Anzeigewert betrachtet. Auf diese Weise können die Angreifer außerhalb von Textfeldern Schadcode in den Browser einspielen, der dann ausgeführt wird.
Um das zu verhindern, sollten Sonderzeichen durch Escape-Codes ersetzt werden, wann immer Browserdaten als Teil einer Antwort zurückgegeben werden – ganz gleich ob die Antwort sofort oder über eine Datenbank erfolgt.
So können die
< and > Zeichen zur Abgrenzung von HTML-Entitäten durch
< and > ersetzt werden. Dadurch wird der Browser angewiesen, diese Zeichen anzuzeigen und sie nicht als HTML-Entitäten zu behandeln. Werden Browserdaten in JavaScript zurückgegeben, sollten Sie das Escaping mit xNN auf alle nicht alphanumerischen Zeichen anwenden. NN steht dabei für den hexadezimalen ASCII-Wert des jeweiligen Zeichens.
4. Eingabefilter
In einigen Fällen ist besser, potenziell gefährliche Zeichen ganz aus den Eingabedaten zu entfernen. Dies bietet einen gewissen Schutz, sollte aber nicht als einzige Maßnahme gegen Manipulationsversuche verwendet werden. Denn die Hacker haben diverse Möglichkeiten, derartige Filter zu umgehen.
5. Eingabevalidierung
Sofern dies möglich ist, sollten Browsereingaben stets dahingehend überprüft werden, dass sie ausschließlich die erwarteten Zeichen enthalten. So sollten Telefonnummernfelder nur Ziffern und unter Umständen Querstriche oder Klammern enthalten dürfen. Eingaben, die andere Zeichen enthalten, sollten dagegen direkt abgelehnt werden. Die Filter sollten so eingerichtet werden, dass sie nach zulässigen Zeichen suchen und alle anderen blockieren.
6. Ausschließlich clientseitige Validierung
Die oben beschriebenen Verfahren sind durchaus verlässlich und gut für Browser geeignet. Doch die Hacker nutzen mitunter besondere Programme, um Daten direkt an den Server zu übermitteln und clientseitige Prüfungen so zu umgehen. Das kann dazu führen, dass schädliche oder ungeprüfte Daten tatsächlich den Server erreichen. Ohne eine ergänzende serverseitige Validierung könnten auf diese Weise die gespeicherten Daten manipuliert oder durch gefälschte Daten ersetzt werden.
Um das zu verhindern, ist eine Kombination aus client- und serverseitiger Validierung empfehlenswert. So lässt sich das Risiko gefährlicher Daten verringern, während die Validierungsfunktionen im Client mitsamt den Vorteilen für die Benutzer erhalten bleiben.
Eine ausschließlich serverseitige Validierung schadet dagegen dem Benutzererlebnis. Denn dann müssen jedes Mal mehrere Onlineformulare ausgefüllt werden. Per JavaScript-Validierung sollten die Benutzer unverzüglich auf Problemstellen in ihren Eingaben hingewiesen werden. Und die Servervalidierung sorgt dafür, dass ausschließlich die erwarteten Daten in die Anwendung gelangen.
7. Diebstahl von Sitzungsdaten
Clientseitige Browserskripte können sehr leistungsfähig sein. Denn sie haben Zugriff auf sämtliche Inhalte, die die Webanwendung an den Browser übermittelt. Hierzu zählen auch Cookies und die darin möglicherweise enthaltenen sensiblen Daten wie etwa Session-IDs. Nicht umsonst versuchen Hacker bei XSS-Angriffen gerne, benutzerspezifische ID-Token an sich selbst zu übermitteln, damit sie die Sitzung kapern können.
Um das zu verhindern, unterstützen die meisten Browser-Cookies mittlerweile das HttpOnly-Attribut. Legt der Server einen Cookie im Browser ab, weist dieses Attribut den Browser an, den Zugriff auf den Cookie vom DOM aus zu blockieren. So kann verhindert werden, dass bei skriptbasierten Angriffen auf der Clientseite auf sensible Daten zugegriffen werden kann, die in diesen Cookies gespeichert sind.
Lokal und in der Sitzung gespeicherte Browserdaten können auf dieselbe Weise entwendet werden. Hier ist ein Schutz über das DOM allerdings nicht möglich. Deshalb empfiehlt es sich, die Speicherung sensibler Daten wie z. B. Token im Browser ganz zu vermeiden, sofern diese nicht für ganz bestimmte Funktionen der Webanwendung erforderlich sind.
8. Täuschung der Benutzer
Bei der Cross-Site Request Forgery (CSRF) werden Browser dazu gebracht, manipulierte Anfragen an eine Website zu übermitteln, in der der Benutzer bereits angemeldet ist. Dies ist selbst dann möglich, wenn die jeweilige Seite gerade nicht geöffnet ist. Nutzt die Zielseite Sitzungscookies, können diese Anfragen automatisch um Cookies für die Autorisierung ergänzt werden.
Gerne nutzen Hacker auch ihre eigenen Websites, um beim Öffnen einer Seite im Hintergrund manipulierte Anfragen an andere Seiten zu übermitteln. Und auch in sozialen Netzwerken, Foren und anderen Plattformen werden manipulierte Links und andere Inhalte veröffentlicht, um Browser dazu zu bringen, unter Verwendung der benutzerseitigen Sitzungscookies unbemerkt andere Seiten aufzurufen.
Diese Schwachstelle lässt sich am besten durch die Tokenisierung der Kommunikation zwischen Client und Server beheben. Dabei wird ein weiterer Token eingesetzt, der nicht in den Cookies gespeichert wird. Zu Beginn der Sitzung sollten für jedes Website-Formular Token generiert und gemeinsam mit den Anfragen übermittelt werden, solange der Benutzer auf der Website unterwegs ist.
Wie begegnet Sie am besten den JavaScript-Sicherheitsrisiken?
Anwendungen und Server können mithilfe etablierter Verfahren und geeigneter Scanner vor Schwachstellen geschützt werden, die sich aus JavaScript ergeben.
Zudem sollten Sie bei der Webentwicklung stets aufmerksam verfolgen, ob neue JavaScript-Sicherheitsrisiken bekannt werden. Die Anwendungen auf ihre Funktionen zu überprüfen, ist zwar wichtig. Regelmäßig geeignete Prüftools für die JavaScript-Sicherheit anzuwenden, ist aber mindestens genauso entscheidend. Und schließlich lässt sich die Lebensdauer von Anwendungen auch mithilfe etablierter Verfahren verlängern.
Mit diesen Tipps erhöhen Sie die Sicherheit Ihrer JavaScript-Anwendungen.
\**eval()** vermeiden: Auf diesen Befehl sollten Sie verzichten, da er übergebene Argumente ausführt, sofern es sich dabei um einen JavaScript-Ausdruck handelt. Gelingt es einem Hacker also, Eingabewerte zu manipulieren, können auf diese Weise beliebige Skripte ausgeführt werden. Setzen Sie stattdessen auf Alternativen, die mehr Sicherheit bieten.
Verschlüsseln Sie den Datenverkehr zwischen Client und Server per HTTPS/SSL.
Cookie-Einstellungen auf „sicher“ setzen: So erzwingen Sie die Verwendung von SSL/HTTPS und Cookies Ihrer Anwendung können dann ausschließlich von sicheren Websites genutzt werden.
API-Zugriffsschlüssel einrichten: Weisen Sie jedem Benutzer individuelle Token zu. Bei Diskrepanzen wird der Zugriff dann entweder verweigert oder zurückgenommen.
SichereDOM-Manipulation: Verfahren wie innerHTML sind gleichermaßen leistungsstark wie riskant, da die Werte nicht maskiert bzw. verschlüsselt werden. Bei Verfahren wie innerText werden potenziell gefährliche Inhalte dagegen automatisch maskiert. So können insbesondere DOM-basierte XSS-Angriffe unterbunden werden.
Die Bestimmung möglicher JavaScript-Sicherheitsrisiken ist ein wichtiger erster Schritt, um Schwachstellen in der Anwendungsentwicklung zu beseitigen. Testen Sie Ihren Code also am besten gleich mit einem Open-Source-Schwachstellen-Scanner.
Beginnen Sie mit Capture the Flag
Lernen Sie, wie Sie Capture the Flag-Herausforderungen lösen, indem Sie sich unseren virtuellen 101-Workshop auf Abruf ansehen.
Up Next
Storytime by Tanya Janca - Secure Coding Libraries
Listen to Tanya share her best practices for creating templates for secure code.
Weiterlesen