Specifically: every click/interaction that loads content in your custom web view sends the webView:shouldStartLoadWithRequest:navigationType: message to your web view delegate. Without implementing that method, clicking a tel: link will prompt first. However, many apps throw some logic in there to detect any URI schemes that don't match the standard HTTP/HTTPS schemes used in normal websites, and trying to do something "nice" for the user, they handle requests for those URIs by calling:
[[UIApplication sharedApplication] openURL:request.URL];
This is a reasonable thing to do (outside the context of tel: links) because it allows the app to spawn an external app for custom URIs.
Therein lies the problem: not that UIWebView opens tel: links without prompting (it doesn't), but that many app developers are just trying to improve the inter-app experience, and unknowingly open tel: links directly with that openURL: method.
EDIT: Just my opinion, but I think it's actually pretty cool that Apple gives developers the ability to dial phone numbers without an extra prompt. It makes third-party contact/phone apps much more useful (imagine having to confirm every phone number to dial after tapping the contact in the built-in phone app). In a way, this is the kind of trust / freedom that iOS developers rarely enjoy without a fight. It's just unfortunate that in this instance, it also happens to be very easy to overlook this pitfall when implementing web view logic that handles non-http links.
The advantage that you get with telprompt:// is that, once the call finishes, the user comes right back into the app that initiated the call. With tel:// that is not the case.
On the other hand, with this system, every single app that ever uses a web view has to somehow magically divine that this could be an issue. The UIWebView docs certainly don't warn you about this. So what, is the expected behavior is that if you ever use a WebView in your app you should read every RFC on the planet in case there's some weird edge case like this? Maybe instead of creating systems that require careful developers we could try creating systems that work well by default and need you to explicitly turn on dangerous features like this.
I'd blame Apple just as much as the devs. They made a choice to be insecure by default in a situation when a majority of developers are going to assume it functions like the rest of the OS does. Web views in any app ought to behave like Safari by default.
I just did a talk during BSidesLV on the subject of URL Schemes and dangerous implementations.
For those who want all the details:
For those who want to skip explanations on how they work and see the bad examples, auto skipping about 10min:
One example that I have in there is Yo. Yo will automatically Yo someone on your behalf. So if an inline frame has yo://gepeto42 (basically), and you have Yo installed, I have just "de-anonymized" your Yo account as you browsed my website (or any page where I could inject that iframe). A good tip on where to find out about those is to buy Launch Center Pro and to extract the plist it has. This has info about hundreds of iOS apps and how their URL Schemes work.
What is the justification for this behavior? Why should the web browser open a prompt but not other apps?
I'm not saying that Apple's design is good, but it is documented.
FB, Google, and others all pay for bugs such as these, so even monetarily, it doesn't make sense to just release it to the public immediately. Again, this is assuming these bugs were not disclosed previously to companies affected.
This affects users much more than it affects Apple.
If it was me, I would have notified Apple and all of the companies who have bug bounty programs.
I reported CVE-2013-6835. They fixed Facetime-Audio from Safari, but not from other browsers (yet?). This is quite a wide issue. I do not think letting every individual developer know is feasible. I did it for a few bad issues, but there's a limit to what can be done.
And a lot of these can be found in a matter of minutes anyways.
There's yet another intent for dialling emergency numbers without prompt, which is reserved for system use -- non-system apps can only dial emergency numbers indirectly using ACTION_DIAL.
see `- (BOOL)webView:(UIWebView )webView shouldStartLoadWithRequest:(NSURLRequest )request navigationType:(UIWebViewNavigationType)navigationType` method in official UIWebViewDelegate reference
Is this a standard thing? Are there really sites, especially one as big as gizmodo, that think it's a great idea to not let people view a few kilobytes of text before burning through any data limit they have with some mandatory video I don't care about?
Now I remember why I installed AdBlock.
Facetime calls are instant. Imagine you clicking a link, your phone calls my (attacker) account, I instantly pick it up and (yes) save all the frames. Now I know how your face looks like and maybe where you are. Hello pretty!
Yes, it works. I tried.
You did say this, though, which is what GP is responding to:
> Who did the mistake?
> Well Apple did not. People didn't read the documentation at all.
If the default is this bad, having it in the documentation is not an excuse.
Especially since this is in the documentation for handling phone links, and the exploit explicitly affects apps that do not utilize/customize this functionality.
You can't say it's the developer's fault for not reading the documentation for a feature they never wanted to use in the first place.
"In practice, the closest to 'malicious' use I've seen the redict-to-app-store-from-ad case"