<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>WebView Hijacking on 飞鸽跳转</title><link>https://feige301.com/zh-cn/tags/webview-hijacking/</link><description>Recent content in WebView Hijacking on 飞鸽跳转</description><generator>Hugo</generator><language>zh-CN</language><lastBuildDate>Wed, 25 Mar 2026 22:10:55 +0800</lastBuildDate><atom:link href="https://feige301.com/zh-cn/tags/webview-hijacking/index.xml" rel="self" type="application/rss+xml"/><item><title>移动端劫持新变种：WebView中的JS注入与重定向</title><link>https://feige301.com/zh-cn/posts/2026/mobile-hijacking-webview-js-injection-redirection.html</link><pubDate>Wed, 25 Mar 2026 22:10:55 +0800</pubDate><guid>https://feige301.com/zh-cn/posts/2026/mobile-hijacking-webview-js-injection-redirection.html</guid><description>&lt;p>我们的工作，就像是为数字世界中的航船保驾护航，不仅要防范海盗（恶意攻击者），还要应对多变的海流（网络环境）和暗礁（中间设备）。今天，我们来聊一个在移动互联网时代日益凸显的问题：移动端应用内嵌浏览器（WebView）中发生的JavaScript注入与强制重定向，这是一种隐蔽且影响用户体验的劫持新变种。&lt;/p>
&lt;h3 id="引言移动互联的便利与隐患">
 引言：移动互联的便利与隐患
 &lt;a class="anchor" href="#%e5%bc%95%e8%a8%80%e7%a7%bb%e5%8a%a8%e4%ba%92%e8%81%94%e7%9a%84%e4%be%bf%e5%88%a9%e4%b8%8e%e9%9a%90%e6%82%a3">#&lt;/a>
&lt;/h3>
&lt;p>当下，移动应用程序已成为用户接入互联网的主流方式。无论是社交、购物、新闻还是数字娱乐平台，用户都习惯于在App内部直接浏览网页内容，享受无缝衔接的体验。这背后，是App内嵌浏览器组件（如Android的WebView，iOS的WKWebView）在默默工作，它们使得应用程序无需频繁调用系统浏览器，就能快速加载和展示网页。&lt;/p>
&lt;p>然而，这种便利性也为一些不当行为提供了温床。我们经常会遇到这样的困境：网站管理员或App开发者明明提供了优质内容，却不断收到用户投诉，称在App内打开网页时，会突然被强制跳转到与内容无关的页面，甚至是一个第三方App的下载页。这种现象不仅严重损害了用户体验，也直接冲击了品牌信誉和业务转化。&lt;/p>
&lt;p>这些看似“无厘头”的跳转，往往并非源自我们的服务器配置错误或App代码缺陷，而是发生在用户设备与我们服务器之间的某个环节——网络流量传输过程中。这正是我们今天要深入探讨的用户痛点：如何理解并有效防御这种发生在WebView环境中的JS注入与重定向劫持。&lt;/p>
&lt;h3 id="一webview移动应用中的迷你浏览器">
 一、WebView：移动应用中的“迷你浏览器”
 &lt;a class="anchor" href="#%e4%b8%80webview%e7%a7%bb%e5%8a%a8%e5%ba%94%e7%94%a8%e4%b8%ad%e7%9a%84%e8%bf%b7%e4%bd%a0%e6%b5%8f%e8%a7%88%e5%99%a8">#&lt;/a>
&lt;/h3>
&lt;p>要理解App内的劫持，我们首先要认识WebView。简单来说，WebView是一个移动应用中用于显示网页内容的组件，它相当于App内部的一个迷你浏览器。&lt;/p>
&lt;ul>
&lt;li>&lt;strong>工作原理：&lt;/strong> 当App需要展示一个网页时，它会调用WebView组件，WebView则会像一个独立的浏览器一样，向服务器发起请求，接收HTML、CSS和JavaScript等内容，并将其渲染显示出来。Android和iOS平台都有各自的WebView实现，它们通常基于各自系统内置的浏览器引擎（如Android的WebView基于Chromium，iOS的WKWebView基于WebKit）。&lt;/li>
&lt;li>&lt;strong>特点：&lt;/strong> WebView的优势在于它提供了极大的灵活性，允许开发者自定义浏览器行为，实现App与Web内容之间的深度交互。但与此同时，它也继承了Web环境的复杂性和潜在的安全风险，尤其是在处理外部链接和未加密内容时。&lt;/li>
&lt;/ul>
&lt;h3 id="二网络流量的中间人角色流量网关的可能干预">
 二、网络流量的“中间人”角色：流量网关的可能干预
 &lt;a class="anchor" href="#%e4%ba%8c%e7%bd%91%e7%bb%9c%e6%b5%81%e9%87%8f%e7%9a%84%e4%b8%ad%e9%97%b4%e4%ba%ba%e8%a7%92%e8%89%b2%e6%b5%81%e9%87%8f%e7%bd%91%e5%85%b3%e7%9a%84%e5%8f%af%e8%83%bd%e5%b9%b2%e9%a2%84">#&lt;/a>
&lt;/h3>
&lt;p>互联网流量并非点对点直达，它需要经过一系列复杂的网络路径和设备。在这个传输链路上，存在着各种“中间设备”或“流量网关”。这些设备由“某地区运营商”或网络服务提供商部署和管理，它们的主要职责是路由、负载均衡、缓存、安全防护等。&lt;/p>
&lt;ul>
&lt;li>&lt;strong>DPI设备：&lt;/strong> 其中一类重要的“中间设备”是DPI（深度包检测）设备。顾名思义，DPI设备能够深入分析网络数据包的头部和负载内容，识别出数据包所属的应用协议，甚至解析出应用层的数据。最初，DPI被用于网络管理、服务质量保障（QoS）和安全监控。&lt;/li>
&lt;li>&lt;strong>流量劫持的产生：&lt;/strong> 然而，DPI的强大能力也可能被用于其他目的。当流量未加密时（即使用HTTP协议），“流量网关”能够完整地看到并修改传输中的数据。某些“某地区运营商”可能会出于商业目的，利用这些“中间设备”在用户请求的网页内容中植入广告脚本、弹窗代码，甚至强制跳转指令。这并非传统的网络攻击，而是一种利用网络基础设施进行的商业干预。&lt;/li>
&lt;/ul>
&lt;p>想象一下，你从A地寄送一封信到B地，这封信会经过邮局、分拣中心等多个环节。如果信件是明文的（HTTP），那么在某个分拣中心，工作人员理论上就可以打开信件，在里面塞入一张广告传单，再重新封装寄出。这就是“流量网关”进行内容注入的形象比喻。&lt;/p>
&lt;h3 id="三js注入劫持的常见手段与webview的脆弱性">
 三、JS注入：劫持的常见手段与WebView的脆弱性
 &lt;a class="anchor" href="#%e4%b8%89js%e6%b3%a8%e5%85%a5%e5%8a%ab%e6%8c%81%e7%9a%84%e5%b8%b8%e8%a7%81%e6%89%8b%e6%ae%b5%e4%b8%8ewebview%e7%9a%84%e8%84%86%e5%bc%b1%e6%80%a7">#&lt;/a>
&lt;/h3>
&lt;p>在“中间设备”进行的流量劫持中，JavaScript注入是最常见且有效的一种手段。&lt;/p>
&lt;ul>
&lt;li>&lt;strong>注入过程：&lt;/strong> 当用户通过WebView请求一个HTTP页面时，“流量网关”会拦截服务器返回的HTML响应。在HTML内容到达用户设备之前，该网关会在其中插入一段&lt;code>&amp;lt;script&amp;gt;&lt;/code>标签，或者修改已有的脚本。这段被注入的JavaScript代码会在WebView渲染页面时被执行。&lt;/li>
&lt;li>&lt;strong>注入后果：&lt;/strong> 被注入的JS代码可以执行各种恶意操作，例如：
&lt;ul>
&lt;li>&lt;strong>弹窗广告：&lt;/strong> 强制弹出广告窗口，影响用户阅读。&lt;/li>
&lt;li>&lt;strong>内容篡改：&lt;/strong> 修改页面上的链接、图片或文本，导向第三方内容。&lt;/li>
&lt;li>&lt;strong>重定向：&lt;/strong> 这是最常见的劫持方式，JS代码直接调用&lt;code>window.location.href&lt;/code>或类似API，强制WebView跳转到另一个URL，例如第三方App的下载页面。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>WebView的脆弱性：&lt;/strong> WebView作为App内的浏览器，其行为和安全性在很大程度上依赖于它所加载的网页内容。如果网页本身不安全，或者在传输过程中被注入了恶意脚本，WebView会无差别地执行这些脚本，从而导致劫持行为的发生。更糟糕的是，由于劫持发生在网络层面，App开发者和网站管理员往往难以直接察觉和控制。&lt;/li>
&lt;/ul>
&lt;h3 id="四案例剖析用户在app内打开网页被强制跳转到第三方app下载页">
 四、案例剖析：用户在APP内打开网页被强制跳转到第三方APP下载页
 &lt;a class="anchor" href="#%e5%9b%9b%e6%a1%88%e4%be%8b%e5%89%96%e6%9e%90%e7%94%a8%e6%88%b7%e5%9c%a8app%e5%86%85%e6%89%93%e5%bc%80%e7%bd%91%e9%a1%b5%e8%a2%ab%e5%bc%ba%e5%88%b6%e8%b7%b3%e8%bd%ac%e5%88%b0%e7%ac%ac%e4%b8%89%e6%96%b9app%e4%b8%8b%e8%bd%bd%e9%a1%b5">#&lt;/a>
&lt;/h3>
&lt;p>我们来深入分析一个典型的真实互联网案例：用户在移动App内打开一个正常的商品详情页或新闻资讯页时，却被强制跳转到了一个与App内容毫无关联的第三方App下载页面，例如某个“数字娱乐平台”或“高并发商业站点”的推广页。&lt;/p>
&lt;p>&lt;strong>场景重现：&lt;/strong>
某用户在手机App（例如一个电商App）中，点击了一个链接，准备查看某件商品的详情。该链接指向的URL是&lt;code>http://www.example.com/product/12345.html&lt;/code>。App内部通过WebView加载这个页面。然而，页面刚开始加载，甚至用户还没来得及看到商品信息，WebView就突然跳转到了一个第三方App商店的下载链接，比如&lt;code>market://details?id=com.thirdparty.app&lt;/code>，或者一个第三方App的Web推广页。用户感到困惑和愤怒，认为App或网站有问题。&lt;/p>
&lt;p>&lt;strong>技术刨析：&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>&lt;strong>初始请求：&lt;/strong> 用户在App内点击链接，WebView发起对&lt;code>http://www.example.com/product/12345.html&lt;/code>的HTTP请求。&lt;/li>
&lt;li>&lt;strong>流量网关拦截：&lt;/strong> 由于请求是HTTP协议，数据未加密，网络路径上的“流量网关”（属于“某地区运营商”）能够完整地拦截并读取服务器返回的HTML响应。&lt;/li>
&lt;li>&lt;strong>JS注入：&lt;/strong> “流量网关”在服务器返回的HTML响应体中，悄悄地插入了一段恶意的JavaScript代码。这段代码通常会被插入到&lt;code>&amp;lt;head&amp;gt;&lt;/code>标签内，或者&lt;code>&amp;lt;body&amp;gt;&lt;/code>标签的开头，以确保它能尽早执行。注入的代码可能类似这样：
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-html" data-lang="html">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&amp;lt;!-- 原始HTML内容 --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&amp;lt;&lt;span style="color:#f92672">head&lt;/span>&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &amp;lt;&lt;span style="color:#f92672">title&lt;/span>&amp;gt;商品详情&amp;lt;/&lt;span style="color:#f92672">title&lt;/span>&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &amp;lt;&lt;span style="color:#f92672">script&lt;/span>&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 注入的恶意JS代码
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> (&lt;span style="color:#66d9ef">function&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">userAgent&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">navigator&lt;/span>.&lt;span style="color:#a6e22e">userAgent&lt;/span> &lt;span style="color:#f92672">||&lt;/span> &lt;span style="color:#a6e22e">navigator&lt;/span>.&lt;span style="color:#a6e22e">vendor&lt;/span> &lt;span style="color:#f92672">||&lt;/span> window.&lt;span style="color:#a6e22e">opera&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 简单判断是否在WebView环境，或者直接无差别跳转
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#e6db74">/Android|iPhone|iPad|iPod/i&lt;/span>.&lt;span style="color:#a6e22e">test&lt;/span>(&lt;span style="color:#a6e22e">userAgent&lt;/span>)) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 判断是否已经跳转过，避免循环
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#f92672">!&lt;/span>&lt;span style="color:#a6e22e">sessionStorage&lt;/span>.&lt;span style="color:#a6e22e">getItem&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;hijacked_redirected&amp;#39;&lt;/span>)) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">sessionStorage&lt;/span>.&lt;span style="color:#a6e22e">setItem&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;hijacked_redirected&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;true&amp;#39;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 强制跳转到第三方App下载页或Web推广页
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> window.&lt;span style="color:#a6e22e">location&lt;/span>.&lt;span style="color:#a6e22e">href&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;market://details?id=com.thirdparty.app&amp;#39;&lt;/span>; &lt;span style="color:#75715e">// Android
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#75715e">// 或者 window.location.href = &amp;#39;itms-apps://itunes.apple.com/app/idXXXXXXXXX&amp;#39;; // iOS
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#75715e">// 或者 window.location.href = &amp;#39;https://thirdpartyapp.com/download&amp;#39;; // Web推广页
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> })();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &amp;lt;/&lt;span style="color:#f92672">script&lt;/span>&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">&amp;lt;!-- 其他原始JS/CSS --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&amp;lt;/&lt;span style="color:#f92672">head&lt;/span>&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&amp;lt;&lt;span style="color:#f92672">body&lt;/span>&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">&amp;lt;!-- ... 商品详情内容 ... --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&amp;lt;/&lt;span style="color:#f92672">body&lt;/span>&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>这段JS代码会检测用户代理（User-Agent）以判断是否为移动设备，并尝试执行强制跳转指令。为了避免反复跳转，它甚至可能使用&lt;code>sessionStorage&lt;/code>来标记已经进行过一次跳转。&lt;/li>
&lt;li>&lt;strong>WebView执行注入脚本：&lt;/strong> 当修改后的HTML响应到达用户设备，WebView接收并开始解析。在解析到注入的&lt;code>&amp;lt;script&amp;gt;&lt;/code>标签时，它会执行其中的JavaScript代码。&lt;/li>
&lt;li>&lt;strong>强制跳转发生：&lt;/strong> 注入的JS代码被执行，立即触发&lt;code>window.location.href&lt;/code>指令，导致WebView强制跳转到预设的第三方App下载页或推广页。用户根本没有机会看到原始的商品详情。&lt;/li>
&lt;/ol>
&lt;p>&lt;strong>造成的影响：&lt;/strong>&lt;/p></description></item></channel></rss>