In this article
Einfach heißt nicht immer sicher: Vermeiden Sie dieses Golang-XSS-Muster
Cross-Site-Scripting-Angriffe (XSS) sind eine typische Web-Schwachstelle, über die Angreifer schädliche Skripte in Webseiten einschleusen können, die andere Nutzer aufrufen. Man könnte meinen, dass einfacher Code auch sicherer ist: keine Abhängigkeiten von Drittanbietern, weniger Abstraktionen. Das klingt ideal – aber stimmt das auch?
Dieser Artikel zeigt einen einfachen Webserver in Golang und erläutert, warum einfach nicht immer sicher bedeutet.
Über Cross-Site-Scripting-Angriffe
Cross-Site-Scripting (XSS) sind Skripte, die häufig Nutzerdaten stehlen, Sitzungen übernehmen oder Webseiten verunstalten. Golang bietet zwar robuste Tools für die Webentwicklung, ist aber nicht vor XSS-Schwachstellen gefeit, wenn keine geeigneten Sicherheitsvorkehrungen getroffen werden.
Beispiel für Cross-Site-Scripting in Golang
Eine häufige Ursache für XSS-Schwachstellen ist, dass von Nutzern eingegebene Daten ohne ausreichende Bereinigung oder andere Sicherheitskontrollen direkt in HTML-Ausgaben eingebettet werden. Wichtig: Eine wirksame Sicherheitskontrolle ist nicht immer die Bereinigung, sondern häufig die Ausgabekodierung.
Ein Beispiel für eine Go-Anwendung: Sie empfängt Daten von Nutzern über ein Formularfeld oder einen URL-Parameter (z. B. eine Abfragezeichenfolge) und fügt diese anschließend direkt als Teil der HTTP-Antwort in eine HTML-Seite ein. Ein Angreifer könnte schädlichen JavaScript-Code einschleusen (daher der Name Cross-Site-Scripting). Ruft ein anderer Nutzer die Seite auf, führt dessen Browser das eingeschleuste Skript aus – dadurch könnten dessen Daten oder Sitzung kompromittiert werden.
Ein häufiger Fehler in Golang-HTTP-Servern besteht darin, fmt.Fprint oder ähnliche Funktionen zu verwenden, um von Nutzern bereitgestellte Daten direkt in die HTTP-Antwort zu schreiben. Sehen Sie sich das folgende Codebeispiel an:
http.HandleFunc("/greet", func(w http.ResponseWriter, r *http.Request) {
name := r.URL.Query().Get("name")
response := fmt.Sprintf("<html><body><h1>Hello, %s!</h1></body></html>", name)
fmt.Fprint(w, response)
})Wenn ein Nutzer für die Abfragezeichenfolge name eine Eingabe wie <script>alert('XSS!')</script> festlegt, schleust dieser Code den JavaScript-Code alert() in die Seite ein und demonstriert so einen einfachen XSS-Angriff. Die Funktion fmt.Sprintf maskiert HTML-Entitäten nicht automatisch, sodass die Anwendung anfällig bleibt.
Das Golang-Codebeispiel ist Teil einer Open-Source-Sicherheitsherausforderung. Snyk hat dieses Code-Repository importiert und konnte erkennen, dass die Eingabe aus der Anfrage-URL nicht bereinigt wurde, und nachverfolgen, wie sie in den unsicheren Aufruf der Funktion fmt.Fprint gelangt, die die HTML-Vorlagenzeichenfolge rendert. Eine detaillierte Analyse des Quellcodes und des Codepfads durch Snyks SAST zeigt die Ergebnisse:

XSS in Golang beheben
Das obige anfällige Golang-Beispiel zeigt, wie wichtig es ist, Nutzereingaben ordnungsgemäß zu maskieren oder zu bereinigen, bevor sie in HTML-Antworten eingefügt werden.
Um potenziell gefährlichen HTML-Code zu maskieren, muss der Anwendungscode oder die verwendete Drittanbieterabhängigkeit bestimmte Nutzereingaben kodieren, damit sie nicht als HTML-DOM-Elemente interpretiert werden. Frontend-Frameworks wie React oder Vue wandeln beispielsweise das Zeichen < in die entsprechende HTML-Entität < um.
Heißt das, dass Sie sich immer auf Abhängigkeiten von Drittanbietern verlassen sollten? Nein. Wenn Sie diese jedoch aktiv überwachen und auf Schwachstellen prüfen und mit automatischen Updates stets aktuell halten, lässt sich das Sicherheitsrisiko besser kontrollieren. Zudem besteht das Risiko, dass eine Bibliothek falsch verwendet wird und dadurch weiterhin eine Schwachstelle entsteht.
Und wie sieht es mit Sicherheitsproblemen in Golang-Code aus? Snyk bietet umfassende Unterstützung für Go – für Go-Code, Go-Abhängigkeiten und Paketmanager.
Kostenloses Online-Tool zur Codeprüfung
Sichern Sie Ihren Code, bevor Sie Ihren nächsten Commit erstellen.