OWASP-Kategorie:MASVS-CODE: Code Quality
Übersicht
Das Laden eines unsicheren URI tritt auf, wenn eine Android-Anwendung die Gültigkeit eines URI nicht richtig bewertet, bevor sie ihn in eine WebView lädt.
Der zugrunde liegende Grund für diese Art von Sicherheitslücke ist, dass ein URI aus mehreren Teilen besteht, von denen mindestens das Schema und der Host (des Authority-Teils) überprüft (z.B. auf die Zulassungsliste gesetzt) werden müssen, bevor der URI in einem WebView geladen oder intern von der Anwendung verwendet wird.
Die häufigsten Fehler sind:
- Der Host wird geprüft, das Schema jedoch nicht. So kann ein Angreifer Schemas wie
http://
,content://
oderjavascript://
mit einem authentifizierten Host verwenden. - Die URI wird nicht richtig geparst, insbesondere wenn sie als String empfangen wird.
- Das Schema wird validiert, nicht aber der Host (unzureichende Hostvalidierung).
Im letzten Fall tritt dies in der Regel auf, wenn die Anwendung beliebige Subdomains einer primären Domain zulassen muss. Auch wenn der Hostname korrekt extrahiert wurde, verwendet die App Methoden wie startsWith
, endsWith,
oder contains
der Klasse java.lang.String
, um das Vorhandensein einer primären Domain im extrahierten Stringabschnitt zu validieren. Bei falscher Verwendung können diese Methoden zu fehlerhaften Ergebnissen führen und die Anwendung zwingen, einem potenziell schädlichen Host fälschlicherweise zu vertrauen.
Positiv beeinflussen
Je nach Kontext, in dem der Host verwendet wird, können die Auswirkungen variieren. In Fällen, in denen das Laden eines schädlichen URI (d.h. eines, der die Filterung/Zulassungsliste umgangen hat) in einer WebView potenziell zu einer Kontoübernahme (z.B. durch Phishing), zur Ausführung von Code (z.B. durch Laden von schädlichem JavaScript) oder zu einer Kompromittierung des Geräts (durch über einen Hyperlink bereitgestellten Exploit-Code) führen könnte.
Maßnahmen zur Risikominderung
Beim Verarbeiten von String-URIs ist es wichtig, den String als URI zu parsen und sowohl das Schema als auch den Host zu validieren:
Kotlin
fun isUriTrusted(incomingUri: String, trustedHostName: String): Boolean {
try {
val uri = Uri.parse(incomingUri)
return uri.scheme == "https" && uri.host == trustedHostName
} catch (e: NullPointerException) {
throw NullPointerException("incomingUri is null or not well-formed")
}
}
Java
public static boolean isUriTrusted(String incomingUri, String trustedHostName)
throws NullPointerException {
try {
Uri uri = Uri.parse(incomingUri);
return uri.getScheme().equals("https") &&
uri.getHost().equals(trustedHostName);
} catch (NullPointerException e) {
throw new NullPointerException(
"incomingUri is null or not well-formed");
}
}
Bei der Hostvalidierung ist es wichtig, den entsprechenden URI-Teil vollständig (und nicht nur teilweise) zu validieren, nachdem er isoliert wurde, um genau zu ermitteln, ob der Host vertrauenswürdig ist oder nicht. Wenn Methoden wie startsWith
oder endsWith
nicht vermieden werden können, ist es wichtig, die richtige Syntax zu verwenden und erforderliche Zeichen oder Symbole nicht zu übersehen. Bei endsWith
ist beispielsweise das Zeichen „.
“ vor dem Domainnamen erforderlich, damit die Übereinstimmung genau ist. Wenn Sie diese Zeichen nicht berücksichtigen, kann das zu ungenauen Übereinstimmungen führen und die Sicherheit beeinträchtigen. Da Subdomains beliebig verschachtelt werden können, ist der Abgleich regulärer Ausdrücke keine empfohlene Strategie zum Validieren von Hostnamen.
Beitragende: Dimitrios Valsamaras und Michael Peck von Microsoft Threat Intelligence