当前位置: 首页 > article >正文

Android WebView 中网页被劫持的原因及解决方案

文章目录

    • 可能的原因
    • 解决方案
    • 解决方案代码示例
    • 解决方案及代码示例
      • 1. 使用 HTTPS
      • 2. 验证 URL
      • 3. 禁用 JavaScript
      • 4. 使用安全的 WebView 设置
      • 5. 监控网络请求
      • 6. 使用安全的 DNS
    • 案例深入分析
      • 问题
      • 分析
    • 结论

在 Android 应用开发中,WebView 是一个常用的组件,用于在应用内显示网页内容。然而,有时用户可能会发现网页被劫持到另一个不安全的网页。这种情况不仅影响用户体验,还可能带来安全隐患。本文将探讨导致网页被劫持的可能原因,并提供相应的解决方案。

可能的原因

  1. JavaScript 重定向

    • 示例:某个网页中包含以下 JavaScript 代码:
      window.location.href = "http://malicious-site.com";
      
      这段代码会在页面加载时将用户重定向到恶意网站。
  2. 恶意网页

    • 示例:用户点击了一个链接,访问了一个看似正常的网站,但该网站实际上是一个钓鱼网站,包含重定向代码,试图引导用户输入敏感信息。
  3. WebView 设置不当

    • 示例:开发者在 WebView 中未设置 WebViewClient,导致 WebView 默认行为是打开所有链接,而不是在应用内处理。这可能导致用户被重定向到外部浏览器,增加了被恶意网站劫持的风险。
  4. 拦截 URL 加载

    • 示例:在 shouldOverrideUrlLoading 方法中,开发者没有正确处理 URL,例如:
      @Override
      public boolean shouldOverrideUrlLoading(WebView view, String url) {
          // 没有验证 URL,直接加载
          view.loadUrl(url);
          return true;
      }
      
      这可能导致用户被重定向到不安全的网站。
  5. 广告或跟踪脚本

    • 示例:某些网页可能嵌入了广告或跟踪脚本,这些脚本会在用户访问时自动重定向到广告商的网站,甚至可能是恶意网站。
  6. 中间人攻击

    • 示例:在公共 Wi-Fi 网络中,攻击者可能通过中间人攻击拦截用户的网络请求,并将其重定向到恶意网站,伪装成合法网站。
  7. DNS 劫持

    • 示例:用户的 DNS 请求被劫持,导致访问某个合法网站时,实际上被重定向到攻击者控制的 IP 地址。例如,用户输入 www.example.com,但由于 DNS 劫持,实际访问的是 malicious-site.com

解决方案

为了减少网页被劫持的风险,开发者可以采取以下措施:

  • 使用 HTTPS:确保访问的网页使用 HTTPS,这样可以减少中间人攻击的风险。

  • 验证 URL:在 shouldOverrideUrlLoading 方法中,验证即将加载的 URL,确保它是安全的。

  • 禁用 JavaScript:如果不需要 JavaScript,可以考虑禁用它,减少潜在的重定向风险。

  • 使用安全的 WebView 设置:确保 WebView 的设置是安全的,例如启用安全的内容加载策略。

  • 监控网络请求:使用网络监控工具,查看 WebView 中的网络请求,识别潜在的恶意重定向。

  • 使用安全的 DNS:考虑使用安全的 DNS 服务(如 DNS over HTTPS),以减少 DNS 劫持的风险。

解决方案代码示例

当然可以!以下是更新后的解决方案部分,包含了关于 DNS 解析的优化和 inline hook 的内容。

解决方案及代码示例

1. 使用 HTTPS

确保加载的网页使用 HTTPS。可以在加载 URL 前进行检查:

private void loadUrl(WebView webView, String url) {
    if (url.startsWith("https://")) {
        webView.loadUrl(url);
    } else {
        // 提示用户或处理不安全的 URL
        Toast.makeText(context, "不安全的链接,无法加载!", Toast.LENGTH_SHORT).show();
    }
}

2. 验证 URL

shouldOverrideUrlLoading 方法中验证即将加载的 URL:

@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
    if (isSafeUrl(url)) {
        view.loadUrl(url);
    } else {
        // 提示用户或处理不安全的 URL
        Toast.makeText(context, "不安全的链接,无法加载!", Toast.LENGTH_SHORT).show();
    }
    return true;
}

private boolean isSafeUrl(String url) {
    // 这里可以添加更复杂的 URL 验证逻辑
    return url.startsWith("https://") || url.startsWith("http://trusted-site.com");
}

3. 禁用 JavaScript

如果不需要 JavaScript,可以在 WebView 设置中禁用它:

WebView webView = findViewById(R.id.webview);
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(false); // 禁用 JavaScript

4. 使用安全的 WebView 设置

确保 WebView 的设置是安全的,例如启用安全的内容加载策略:

webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_NEVER_ALLOW); // 禁止混合内容
webSettings.setDomStorageEnabled(true); // 启用 DOM 存储

5. 监控网络请求

使用 WebViewClient 监控网络请求,识别潜在的恶意重定向:

webView.setWebViewClient(new WebViewClient() {
    @Override
    public void onPageStarted(WebView view, String url, Bitmap favicon) {
        super.onPageStarted(view, url, favicon);
        // 监控页面加载
        Log.d("WebView", "Loading URL: " + url);
    }

    @Override
    public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
        super.onReceivedError(view, request, error);
        // 处理加载错误
        Toast.makeText(context, "加载错误: " + error.getDescription(), Toast.LENGTH_SHORT).show();
    }
});

6. 使用安全的 DNS

在 Java 层,DNS 解析由 AddressCache 管理。当未命中缓存时,会调用 Libcore.os.android_getaddrinfo 方法进行域名解析。通过阅读源码发现,解析逻辑由 libc.so 中的 getaddrinfo 方法实现,而 WebView 中的域名解析逻辑也是通过 libwebviewchromium.so 调用这个底层方法。

为了优化 DNS 解析,我们可以使用 inline hook 的方式(具体方案可以参考 ShadowHook)来 hook getaddrinfo 方法。这样可以先查询我们维护的缓存,再进行相应的优化和兜底处理。

以下是一个简单的示例,展示如何使用 ShadowHook 来 hook getaddrinfo 方法:

import com.github.shadowhook.ShadowHook;

public class DnsHook {
    public static void hookGetAddrInfo() {
        ShadowHook.hook("libc.so", "getaddrinfo", new ShadowHook.HookCallback() {
            @Override
            public Object invoke(Object... args) {
                String hostname = (String) args[0];
                // 查询自定义缓存
                String cachedIp = queryCustomDnsCache(hostname);
                if (cachedIp != null) {
                    // 返回缓存的 IP 地址
                    return cachedIp;
                }
                // 调用原始的 getaddrinfo 方法
                return ShadowHook.callOriginal(args);
            }
        });
    }

    private static String queryCustomDnsCache(String hostname) {
        // 实现自定义 DNS 缓存查询逻辑
        return null; // 返回 null 表示未命中缓存
    }
}

案例深入分析

问题

用户点击一个工作应用的链接A,会跳转到链接B,B是一个不良网站,在用户手机上必现。

分析

  1. 因为用户在任何网络环境都能复现,怀疑是用户android端的DNS解析被劫持了。
    验证方法:android端打开huatuo的DNS检测页面,发现解析结果为空。在其他浏览器打开链接A,也是符合预期的。说明DNS没有被劫持。
    https://itango.tencent.com/app/data/huatuo
    在这里插入图片描述
  2. 通过抓包工具分析,发现没有连接A的请求包。虽然界面上打开的是链接A,但是确实直接发起了B的请求。通过这一点,怀疑是Webview缓存之前在某个网络环境下的DNS解析结果,默认跳转过去了链接B。
    验证方法:删除应用的【缓存】(不需要清除数据),用户恢复正常。验证了确实是Webview在应用沙箱中缓存了解析结果。

结论

在 Android WebView 中,网页被劫持的情况可能由多种因素引起,包括 JavaScript 重定向、恶意网页、设置不当等。通过采取适当的安全措施,开发者可以有效降低这些风险,保护用户的浏览体验和数据安全。确保在开发过程中关注这些潜在的安全隐患,将有助于提升应用的整体安全性和用户信任度。


http://www.kler.cn/a/518719.html

相关文章:

  • 大数据之路:阿里巴巴大数据实践(1)
  • Mono里运行C#脚本36—加载C#类定义的成员变量和方法的数量
  • kafka-保姆级配置说明(consumer)
  • 数据结构——二叉树——堆(1)
  • 沃尔玛 礼品卡绑定 分析
  • 安装最小化的CentOS7后,执行yum命令报错Could not resolve host mirrorlist.centos.org; 未知的错误
  • 斯坦福:数据对齐在LLM训练中的重要性
  • 【再谈设计模式】职责链模式 - 串联请求处理者的链条
  • 数据分析学习路线
  • 解决vsocde ssh远程连接同一ip,不同端口情况下,无法区分的问题
  • 安装包报错
  • MQ的可靠消息投递机制
  • 【Uniapp-Vue3】previewImage图片预览
  • 编译原理之基于自动机的词法分析器的设计与实现
  • 省市区三级联动
  • centos操作系统上以service形式运行blackbox_exporter监控网页端口
  • 【JAVA 基础 第(20)课】JDBC JAVA 连接 MySql 数据库
  • [C++技能提升]类型归一
  • 定位的主要知识
  • OpenCV:图像处理中的低通滤波
  • 小哆啦解题记:寻找最后一个单词的“长度”
  • 数据结构与算法分析:专题内容——人工智能中的寻路6之NegMax(代码详解)
  • 链式存储结构
  • 详解生成对抗网络(GAN)模型
  • Oracle迁移DM数据库
  • Facebook 元宇宙与全球文化交流的新趋势