导读:本期聚焦于创作的《WebView安全漏洞有哪些?JS交互防坑指南与安全加固实践》,敬请观看详情。加载网页的同时执行JS代码,这是WebView最常见的功能,也是最容易被攻击者利用的入口。本文围绕WebView安全漏洞与JS交互的注意事项展开,重点分析addJavascriptInterface漏洞、File协议跨目录读取、SSL证书校验缺失、密码明文存储等典型风险,并给出对应的加固方案,包括限制JS调用范围、使用@JavascriptAnnotation、关闭文件访问、严格校验HTTPS证书等实践建议,帮助开发者在混合开发中守住安全底线。

混合开发已经成为移动端的主流方案之一,WebView承担着展示H5页面并桥接原生能力的职责。然而一旦JS与原生的交互通道被滥用,攻击者就可能通过一个恶意网页反向控制App的Java层代码,造成用户数据泄露甚至远程执行任意命令。本文从WebView常见的几类安全漏洞入手,结合实际案例与代码,逐一说明JS交互时需要特别注意的事项。

WebView安全漏洞有哪些?JS交互防坑指南与安全加固实践

一、addJavascriptInterface远程代码执行漏洞

这是WebView历史上最严重的漏洞之一。在Android 4.2之前,通过addJavascriptInterface注入到WebView的对象,其所有public方法都会暴露给JS,包括那些继承自Object类的反射相关方法。攻击者只需让WebView加载一个恶意页面,就能利用getClass配合反射机制执行任意系统命令。

典型的攻击代码非常简短,这也是该漏洞危害巨大的原因:

function execute(cmd) {
    // 利用addJavascriptInterface注入的对象进行反射调用
    return jsObj.getClass().forName('java.lang.Runtime')
        .getMethod('getRuntime', null)
        .invoke(null, null)
        .exec(cmd);
}

防护要点有三条。第一,Android 4.2及以上的系统要求被JS调用的方法必须显式标注@JavascriptInterface注解,未标注的方法不会暴露给JS,务必确认所有暴露方法都添加了该注解:

public class SafeBridge {
    // 只有标注了注解的方法才会暴露给JS
    @JavascriptInterface
    public String getUserToken() {
        return TokenManager.getScopedToken();
    }

    // 这个方法没有注解,JS无法访问
    public String getRawPassword() {
        return PasswordStore.read();
    }
}

第二,不要将包含敏感操作的通用对象直接注入。注入对象应做最小化设计,只暴露确实需要的只读方法。第三,对于必须支持低版本系统的场景,服务端应禁止WebView加载不可信的第三方URL,并对所有跳转链接做白名单校验。

二、File协议与域限制带来的本地文件泄露

WebView默认开启文件访问能力时,本地HTML文件可以通过File协议读取应用私有目录中的内容。如果攻击者诱导App加载了SD卡上一个恶意HTML,该页面就能遍历/data/data/包名/下的私有文件,把数据库、SharedPreferences里的登录凭证、聊天记录全部发送出去。

Android 4.1之后系统默认关闭了File域下的跨域访问,但很多开发者为了兼容旧页面会手动重新打开,这是非常危险的做法。正确的配置应该是:

WebSettings settings = webView.getSettings();
// 禁止通过file协议访问本地文件
settings.setAllowFileAccess(false);
// 禁止file域页面通过XHR读取其他本地文件,默认应为false
settings.setAllowFileAccessFromFileURLs(false);
// 禁止file域页面读取http/https资源
settings.setAllowUniversalAccessFromFileURLs(false);

需要注意setAllowFileAccessFromFileURLssetAllowUniversalAccessFromFileURLs默认值即为false,切勿为了解决某个本地页面加载问题而贸然改为true。如果业务确实需要加载本地页面,建议将HTML资源放入assets目录并通过https:或自定义协议代理访问,同时在shouldOverrideUrlLoading中对URL做域名白名单判断:

@Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
    String host = request.getUrl().getHost();
    if (!TRUSTED_HOSTS.contains(host)) {
        // 非白名单域名直接拦截,跳转到外部浏览器
        openInSystemBrowser(request.getUrl());
        return true;
    }
    return false;
}

此外,还要警惕通过Intent传入的URL直接交给WebView加载的场景。二维码扫描、Push消息中的跳转链接都属于外部输入,必须经过校验后才能进入WebView,否则用户可能被引导到钓鱼页面并触发上述File协议攻击。

三、JS交互通道的安全设计与证书校验

即使堵住了前两个漏洞,JS桥本身的设计缺陷依然可能成为突破口。一个常见错误是桥接方法缺少权限分层:例如提供pay(orderInfo)这样的方法,任何页面都能调用,包括被嵌入的第三方广告页。正确的做法是为每个桥接方法声明所需的权限等级,在调用时校验当前页面的域名是否具备该权限。

同时建议对通信内容做签名验证。原生侧在注入桥对象前,先向页面下发一个一次性token,页面每次调用桥方法时携带该token,原生侧校验通过后才执行业务逻辑。这样即使恶意页面成功注入脚本,也无法伪造合法调用。

证书校验是另一块容易被忽视的短板。为了抓包调试,一些开发者重写了onReceivedSslError并直接调用handler.proceed(),这个配置如果带入线上版本,等于放弃了HTTPS的防中间人能力,攻击者在公共WiFi下即可窃听全部通信内容。正确做法是只在测试构建中放行证书错误:

@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
    if (BuildConfig.DEBUG && ALLOW_DEBUG_SSL) {
        handler.proceed(); // 仅调试环境放行
    } else {
        handler.cancel(); // 线上环境一律取消
    }
}

更进一步,可以重写shouldInterceptRequest对响应内容做关键接口的证书锁定(Certificate Pinning),或者使用OkHttp拦截替换关键请求,确保登录、支付等敏感流量不经过可被篡改的通道。

最后几个容易遗漏的点:一是setSavePassword早已废弃且默认关闭,切勿手动开启明文密码保存;二是关闭setJavaScriptEnabled不需要JS的页面,缩小攻击面;三是通过setWebContentsDebuggingEnabled开启的远程调试只能在Debug构建中启用,否则任何人用Chrome的inspect面板都能查看你的WebView内容;四是onJsAlert、onJsPrompt等回调中返回的Prompt桥接方案,要防止页面伪造弹窗骗取用户授权。安全从来不是单点配置,而是从URL入口、桥接权限、传输层到调试开关的一整条链路的层层设防。

WebView安全JS交互JavaScript注入防护修改时间:2026-09-01 02:44:30

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。