Secure Coding: CWE-1007 – die unsichtbare Gefahr durch visuell ähnliche Zeichen

Vorsätzliche Homoglyphen-Angriffe durch visuell ähnliche Zeichen können Anwender in die Irre leiten. Zum Schutz dagegen helfen verschiedene Best Practices.

vorlesen Druckansicht 34 Kommentare lesen
Halber Mensch vor einer Wolke aus Programmcodezeichen

(Bild: erstellt mit Chat-GPT / DALL-E)

Lesezeit: 17 Min.
Von
  • Sven Ruppert
Inhaltsverzeichnis

Viele Cybersecurity-Bedrohungen sind überraschend subtil und schwer zu erkennen. Dazu zählt unter anderem das Problem der sogenannten Homoglyphen. Die Common Weakness Enumeration CWE-1007 – bekannt als "Insufficient Visual Distinction of Homoglyphs Presented to User" (unzureichende visuelle Unterscheidung von Homoglyphen für Benutzer) – beschreibt eine solche Schwachstelle. Sie wird oft von Angreifern genutzt, um Anwender aber auch Entwickler zu täuschen und Systeme oder Daten zu kompromittieren.

Secure Coding – Sven Ruppert
Sven Ruppert

Seit 1996 programmiert Sven Java in Industrieprojekten und seit über 15 Jahren weltweit in Branchen wie Automobil, Raumfahrt, Versicherungen, Banken, UN und Weltbank. Seit über 10 Jahren ist er von Amerika bis nach Neuseeland als Speaker auf Konferenzen und Community Events, arbeitete als Developer Advocate für JFrog und Vaadin und schreibt regelmäßig Beiträge für IT-Zeitschriften und Technologieportale. Neben seinem Hauptthema Core Java beschäftigt er sich mit TDD und Secure Coding Practices.

Dieser Blogartikel liefert einen tiefen Einblick in CWE-1007, um dessen Mechanismen zu verstehen und zu erfahren, wie man sich vor solchen Angriffen schützen kann. Die vorgestellten Beispiele, technischen Herausforderungen und bewährten Verfahren helfen Entwicklerinnen und Entwicklern, diese Bedrohung nicht nur zu verstehen, sondern auch geeignete Maßnahmen zur Abwehr umzusetzen.

Bevor wir uns in CWE-1007 vertiefen, ist es wichtig, zu verstehen, was Homoglyphen sind. Homoglyphen sind Zeichen, die sich visuell ähneln, hinter denen aber unterschiedliche Unicode-Codes stehen. Das kann sowohl Buchstaben, Zahlen als auch Symbole betreffen. Ein bekanntes Beispiel ist der lateinische Großbuchstabe "O" und die Ziffer "0", die für das menschliche Auge nahezu identisch aussehen können. Es gibt viele weitere Beispiele wie "l" (kleines L) und "I" (großes i), oder verschiedene kyrillische Buchstaben, die wie einige lateinische Buchstaben aussehen.

Die visuelle Ähnlichkeit von Homoglyphen wird oft zum Täuschen ausgenutzt. Angreifer setzen solche Zeichen gezielt ein, um Phishing-Websites zu erstellen, URLs zu imitieren oder Code so zu verfälschen, dass Anwender glauben, es mit einer vertrauenswürdigen Ressource zu tun zu haben. Dies ist besonders problematisch, da wir Menschen es gewohnt sind, visuelle Muster zu verwenden, um schnelle Entscheidungen zu treffen, und dadurch leicht Opfer solcher Täuschungen werden können.

CWE-1007 bezeichnet die unzureichende visuelle Unterscheidung von Homoglyphen, wenn diese gezielt Nutzern präsentiert werden. Ist ein System nicht in der Lage, zwischen ähnlich aussehenden Zeichen zu unterscheiden oder Anwender darauf aufmerksam zu machen, kann dies zu erheblichen Sicherheitsrisiken führen – etwa das versehentliche Klicken auf einen schädlichen Link, den Besuch einer gefälschten Domain oder das Ausführen eines betrügerischen Befehls.

Videos by heise

Die Schwachstelle tritt besonders häufig auf, wenn es um das Darstellen von URLs, Benutzernamen oder Befehlen geht. Angreifer haben es dabei häufig auf Passwörter, Kreditkarteninformationen oder andere sensible Daten abgesehen und nutzen die Verwechslungsgefahr bei Homoglyphen, um Anwender auf eine scheinbar korrekte, tatsächlich aber gefälschte Website zu lenken.

Ein typisches Beispiel ist der Einsatz von gefälschten Domains, die Homoglyphen verwenden: Ein Nutzer erhält beispielsweise eine E-Mail mit einem Link zu paypa1.com (bei dem die Zahl 1 anstelle des Buchstabens l verwendet wurde). Ohne genauere Betrachtung könnte es sich um einen legitimen Link zur PayPal-Website handeln. Das gleiche Prinzip funktioniert auch für Benutzernamen in sozialen Netzwerken oder sogar für wichtige Befehle in einer Konsole.

Ein weiteres Beispiel ist die Verwendung von Homoglyphen in Sourcecode. Angreifer könnten gefälschte Zeichen in den Code einbauen, die aussehen wie legale Zeichen, aber zu einer anderen Funktionalität führen. Dies kann besonders gefährlich in Open-Source-Projekten oder in Teams sein, in denen mehrere Entwickler am selben Code arbeiten und ähnliche Zeichen übersehen könnten. Dies führt zu Sicherheitslücken, die sich für Angriffe nutzen lassen, und stellt ein hohes Risiko für die Integrität des Codes dar.

Ein Beispiel aus dem Alltag ist ein gefälschter Benutzername in sozialen Netzwerken. Um sich als offizieller Support-Kanal auszugeben, könnte ein Angreifer einen Benutzernamen wie "facеbook_support" erstellen, bei dem das lateinische "e" durch das zum Verwechseln ähnliche kyrillische "е" ersetzt wurde. Unachtsame Anwender könnten diesem vermeintlich seriösen Account dann gegebenenfalls sensible Daten preisgeben.

CWE-1007 ist gefährlich, weil wir Menschen uns stark auf visuelle Hinweise verlassen, um Entscheidungen zu treffen. Das menschliche Auge ist darauf trainiert, Muster zu erkennen und Informationen schnell zu verarbeiten – auf eine genaue Prüfung jedes einzelnen Zeichens wird dabei häufig aber verzichtet. Diese Schwäche können Angreifer gezielt ausnutzen, um zu täuschen.

Die Gefahr dieser Schwachstelle liegt nicht nur darin, dass man auf Phishing-Angriffe hereinfallen könnte, die etwa Anmeldeinformationen abgreifen sollen. Sie kann auch zu schwerwiegenderen Sicherheitsverletzungen führen, wie der Manipulation von Software oder dem Einfügen von schädlichem Code in mutmaßlich legitime Projekte. Darüber hinaus können durch diese Täuschung auch finanzielle Schäden entstehen, wenn Zahlungsinformationen über gefälschte Websites in die falschen Hände gelangen und dann missbraucht werden.

Ein weiterer Aspekt ist die Gefahr der gezielten Rufschädigung von Unternehmen. Angreifer nutzen dazu bewusst das Vertrauen der Benutzer in eine bekannte Marke aus und locken sie zu einer gefälschten Version. Machen Anwenderinnen und Anwender dabei schlechte Erfahrungen, und geschieht dies zudem häufiger, kann das Vertrauen in die eigentliche Marke stark leiden. Das auf diese Weise untergrabene Vertrauen in die Marke zieht womöglich einen dauerhaften Schaden für das betroffene Unternehmen nach sich.

Phishing-Angriffe mit gefälschten URLs: Angreifer können eine URL erstellen, die fast identisch mit einer bekannten Website aussieht. Bei einem unvorsichtigen Klick auf den Link – ohne zu bemerken, dass die Domain eine leichte Änderung aufweist (z. B. ein kyrillischer Buchstabe anstelle eines lateinischen Buchstabens) – können Angreifer sensible Informationen wie Passwörter oder Kreditkartendaten abgreifen.

Code-Injection durch gefälschte Zeichen: In komplexen Softwareprojekten kann der Einsatz von Homoglyphen dazu dienen, dass der Code anders ausgeführt wird, als es auf den ersten Blick scheint. Angreifer können beispielsweise schädliche Funktionen einfügen, die erst im Produktionsumfeld auffallen. Solche Schwachstellen im Code sind schwer auffindbar, da Entwickler die ähnlichen Zeichen leicht übersehen können.

Social Engineering in sozialen Netzwerken: Ein Angreifer könnte einen Benutzernamen erstellen, der dem eines vertrauenswürdigen Kontakts fast identisch ist, um Nutzer zu täuschen und Informationen zu stehlen. Beispielsweise könnte jemand den Namen "LinkedIn-Support" mit einem leicht abgeänderten Buchstaben verwenden, um Anmeldeinformationen zu erschleichen. Diese Art der Täuschung ist dann besonders effektiv, wenn auf zusätzliche Sicherheitsprüfungen verzichtet wird.

Um sich vor der Bedrohung durch CWE-1007 zu schützen, sind sowohl technische als auch organisatorische Maßnahmen notwendig. Hier sind einige Strategien, die helfen können, das Risiko zu minimieren:

Unicode-Normalisierung: Eine der effektivsten Methoden, um Homoglyphen zu erkennen, ist die Unicode-Normalisierung. Dabei werden ähnlich aussehende Zeichen in eine standardisierte Form überführt, die es einfacher macht, sie zu identifizieren. So lässt sich verhindern, dass verschiedene Schriftsysteme zur Täuschung verwendet werden.

Das folgende Codebeispiel zeigt, wie Zeichen normalisiert werden können, um sicherzustellen, dass visuell ähnliche, aber unterschiedliche Zeichen richtig erkannt werden:

  import java.text.Normalizer;

   public class UnicodeNormalizationExample {
       public static void main(String[] args) {
           String suspiciousString = "päypäl.com";
           String normalizedString = Normalizer.normalize(suspiciousString, Normalizer.Form.NFKC);
           System.out.println("Normalized String: " + normalizedString);
       }
   }

Nutzerschulung: Die Schulung im Umgang mit verdächtigen E-Mails, Links und Domain-Namen ist eine wichtige Verteidigungslinie. Jeder sollte lernen, URLs genau zu prüfen und sich darüber bewusst sein, dass Zeichen aus unterschiedlichen Schriftsystemen verwendet werden können, um zu täuschen. Diese Schulung sollte regelmäßige Übungen und Beispiele beinhalten, um das Bewusstsein zu stärken und die Fähigkeiten zur Erkennung solcher Angriffe zu verbessern.

Sicherheitswarnungen im Browser: Moderne Browser verfügen über Mechanismen, die davor warnen, wenn Anwender eine Domain besuchen, die verdächtig erscheint oder Zeichen aus unterschiedlichen Unicode-Schriftsystemen verwendet. Diese Warnungen sollten stets aktiviert bleiben. Entwickler von Browser-Erweiterungen könnten zusätzliche Filtermechanismen implementieren, die rechtzeitig auf mögliche Täuschungen hinweisen.

Code-Reviews und Tools zur statischen Codeanalyse: In Softwareprojekten sollten Entwickler Code-Reviews durchführen, um verdächtige Zeichen zu identifizieren. Tools zur statischen Codeanalyse können ebenfalls dabei helfen, Homoglyphen im Code zu erkennen und potenzielle Sicherheitsrisiken zu mindern.

Dieses Codebeispiel zeigt, wie eine einfache Überprüfung helfen kann, potenziell gefährliche Zeichen zu erkennen und entsprechend zu handeln:

   public class CodeReviewExample {
       public static boolean containsSuspiciousCharacters(String input) {
           // Prüft, ob der String nicht-lateinische Zeichen enthält
           return !input.matches("^[\ -\~]*$");
       }

       public static void main(String[] args) {
           String input = "paypaı.com"; // enthält das Homoglyph "ı" (kleines i ohne Punkt)
           if (containsSuspiciousCharacters(input)) {
               System.out.println("Verdächtige Zeichen gefunden: " + input);
           }
       }
   }

Zulassen bestimmter Zeichenmengen: Eine weitere Maßnahme zur Risikominderung besteht darin, die Verwendung bestimmter Zeichenmengen einzuschränken. Beispielsweise könnte eine Anwendung festlegen, dass nur lateinische Zeichen in Benutzernamen oder URL-Pfaden erlaubt sind, um das Risiko von Homoglyph-Angriffen zu verringern. Diese Einschränkung hilft, die Angriffsfläche zu reduzieren.

Das Codebeispiel präsentiert eine einfache Methode zur Einschränkung der erlaubten Zeichen in Eingaben, um die Nutzung von Homoglyphen zu verhindern:

  public class CharacterWhitelistExample {
       public static boolean isValidInput(String input) {
           return input.matches("^[a-zA-Z0-9]*$");
       }

       public static void main(String[] args) {
           String username = "usernäme"; // enthält ein nicht-lateinisches Zeichen
           if (isValidInput(username)) {
               System.out.println("Benutzername ist gültig.");
           } else {
               System.out.println("Benutzername enthält ungültige Zeichen.");
           }
       }
   }

Homoglyphen zuverlässig zu erkennen, ist technisch herausfordernd. Ein Grund dafür ist die schiere Anzahl an Zeichen im Unicode-Standard. Unicode umfasst tausende von Zeichen aus verschiedenen Schriftsystemen, die ähnlich oder identisch aussehen können. Ein Algorithmus, der solche Zeichen identifizieren soll, muss in der Lage sein, zwischen visuellen Ähnlichkeiten und tatsächlicher Bedeutung zu unterscheiden.

Ein weiteres Problem besteht darin, dass nicht alle Anwendungen oder Systeme gleich gut in der Lage sind, Unicode korrekt darzustellen. In einigen Fällen können unterschiedliche Zeichen durch den Rendering-Prozess identisch dargestellt werden, wodurch es noch schwieriger wird, zwischen legitimen und gefälschten Inhalten zu unterscheiden. Diese technischen Herausforderungen erfordern die Entwicklung robuster Prüfmechanismen, die sicherstellen, dass derartige Täuschungsversuche erkannt werden können.

Entwicklerinnen und Entwickler spielen eine entscheidende Rolle dabei, die Bedrohungen durch CWE-1007 zu verhindern. Hier sind einige Best Practices, die beim Entwickeln sicherer Anwendungen berücksichtigt werden sollten:

Eingabevalidierung: Eingabedaten, die von Benutzern stammen, sollten immer validiert werden, um sicherzustellen, dass sie keine gefährlichen Zeichen enthalten. Wenn möglich, sollten nur ausgewählte Zeichensätze erlaubt sein.

  public class InputValidationExample {
       public static boolean isValidInput(String input) {
           return input.matches("^[a-zA-Z0-9]*$");
       }

       public static void main(String[] args) {
           String userInput = "hello123";
           if (isValidInput(userInput)) {
               System.out.println("Eingabe ist gültig.");
           } else {
               System.out.println("Eingabe enthält ungültige Zeichen.");
           }
       }
   }

Escape und Encode: Daten, die für die Anzeige oder für die Übertragung verwendet werden, sollten immer escaped und encoded werden, um sicherzustellen, dass keine schädlichen Zeichen unbemerkt eingefügt werden.

Das Codebeispiel zeigt, wie potenziell schädliche Eingaben korrekt behandelt werden können, um Angriffe wie Cross-Site Scripting (XSS) zu verhindern:

 import org.apache.commons.text.StringEscapeUtils;

   public class EscapeEncodeExample {
       public static void main(String[] args) {
           String userInput = "<script>alert('XSS');</script>";
           String escapedInput = StringEscapeUtils.escapeHtml4(userInput);
           System.out.println("Escaped Input: " + escapedInput);
       }
   }

Bewusste Verwendung von Schriftarten: Die Wahl der geeigneten Schriftart kann dabei helfen, Homoglyphen besser zu erkennen. Einige Schriftarten unterscheiden deutlicher zwischen ähnlich aussehenden Zeichen, was es einfacher macht, Unterschiede zu erkennen. Beispiele für solche Schriftarten sind etwa Consolas, Courier New und DejaVu Sans Mono. Diese Schriftarten eignen sich besonders, wenn es gilt, Zeichen eindeutig voneinander zu unterscheiden, beispielsweise in Quellcode oder sicherheitsrelevanten Informationen.

Zusätzliche Kontextinformationen bereitstellen: Im Zusammenhang mit der Aufforderung, sensible Informationen wie URLs oder Benutzernamen zu prüfen, kann es sinnvoll sein, zusätzliche Kontextinformationen bereitzustellen, die helfen, die Legitimität zu überprüfen. Dazu gehören Warnhinweise oder visuelle Markierungen, die darauf hinweisen, dass bestimmte Zeichen möglicherweise gefährlich sein könnten.