Leakage of Sensitive Data Through Android Webviews
2021-02-17 23:32:16 Author: infosecwriteups.com(查看原文) 阅读量:216 收藏

Would start this story by brushing up on some fundamentals so that people new to the Android world could understand the issue. Folks familiar with Android Webviews can skip the next section.

Image for post

Android allows developers to display web content directly into their application through Webviews. You may consider it as a dedicated web browser instance of an application, which could be used to deliver web pages to the users.

Loading Content in Webview

The usage of Webviews is very developer-friendly and hence is used extensively these days. We can load the web content using Webview#loadUrl method as shown below:

--
WebView myWebView = (WebView) findViewById(R.id.webview);
myWebView
.loadUrl("http://www.google.com");
--

What if you want to pass some headers along with the request to load web content or you want to load some protected content??

Android also provides an overloaded version of Webview#loadUrl method which lets us pass additional request headers to the request as shown below:

--Map<String, String> headers = new HashMap<>();
headers.put("Authorization", token);
--
WebView myWebView = (WebView) findViewById(R.id.webview);
myWebView.loadUrl("http://shivsahni.com", headers);
--

The headers argument is a Map<String, String> having header names and the corresponding values. These headers are added to the request while making the call to load the web content.

The security issue was in the implementation of the overloaded version of the loadUrl(String url, Map<String, String> additionalHttpHeaders) which loads the web content and attaches the additionalHttpHeaders HTTP headers to the request. In the scenario wherein it contains sensitive data such as auth tokens, shared secrets, etc. it could be leaked to third-party.

This happens when the backend responds to this web content load(using overloaded loadUrl method) with a redirect. The frontend attaches the headers to the subsequent request as well, leading to unintended data leakage.

The following screenshot is from Google Docs(taken while reporting the bug). It is misleading as it mentions that the headers are sent for this URL whereas the actual behavior is sending the headers to subsequent requests as well.

Image for post

Proof of Concept

I made an Android application to demonstrate this security issue. The application has a Webview component that loads the webpage with an additional header(Authorization).

Note: I have used shouldOverrideUrlLoading in WebViewClient in order to allow Webview to control the redirects. As per the Google Docs:Do not call WebView#loadUrl(String) with the request's URL and then return true. This unnecessarily cancels the current load and starts a new load with the same URL. The correct way to continue loading a given URL is to simply return false, without calling WebView#loadUrl(String).In case you are calling loadUrl inside shouldOverrideUrlLoading, you might not be leaking the sensitive data to third-party but you might be landing yourself into another security/privacy risk as this causes all renderer-initiated navigations (e.g. redirects, JS location changes, clicking on links, etc) to be converted into browser-initiated navigations.

The following code snippet shows how auth data is passed while loading the web content in the Webview

Map<String, String> headers = new HashMap<>();
headers.put("Authorization", auth);
WebViewClient wc= new myWebClient();
webView.setWebViewClient(wc);
webView.loadUrl(URL, headers);

For this proof of concept code, I have used Flask to return the redirect response. The mobile app would receive an HTTP-302 response which would redirect the application to https://google.com

from flask import Flask,redirect
import os
app = Flask(__name__)
@app.route('/redirect')
def hello_world():
return redirect("
https://google.com", code=302)
if __name__ == '__main__':
print "Hello World!"
port = int(os.environ.get('PORT', 5000))
app.run(debug=True,host='0.0.0.0')

In order to see what is happening in the background, I connected the PoC mobile application to a proxy server. Burp Suite(Proxy) helped me to record all the requests and responses. You can easily observe that the Authorization header is sent to the redirect request(google.com) as well.

Image for post

Original Request

Image for post

Redirect Request

Due to the compatibility considerations, Google took a long time to fix this issue. The security issue was fixed in the latest Chromium Release.

Are you affected?

If you use the overloaded version of the loadUrl method with additional headers to load web content and pass sensitive data such as auth tokens, shared secrets(eg. API keys), etc. to your backend and expect a redirect response to a third-party/non-trusted domain then you might be at risk. You might want to respond to this in the following way:

  • In case you sent JWTs in additional header argument, they might have been shared with the third-party in the past, and in case you have long-lived JWT tokens for users, you must invalidate the JWT tokens to prevent third-party accessing them in the scenario of breach of trust
  • Rotate the secrets(API Keys, etc.)as they might have been unintendedly shared with the third-parties along with the redirect.

The Android users with Webview versions older than M88 should still be vulnerable. It is suggested that the users must update the Webview immediately.


文章来源: https://infosecwriteups.com/leakage-of-sensitive-data-through-android-webviews-3b0b86486a28?source=rss----7b722bfd1b8d--bug_bounty
如有侵权请联系:admin#unsafe.sh