PWA(Progressive Web Apps)安全

admin 2023年12月6日13:18:50评论6 views字数 8198阅读27分19秒阅读模式

为了将现有的 Web 应用程序扩展到移动和桌面环境,越来越多的 Web 开发人员正在创建其 Web 应用程序的渐进式 Web 应用程序 (PWA) 版本。 PWA 最初由 Google 于 2015 年提出,利用最新的 Web 标准为移动和桌面应用程序提供类似本机的体验。          

         
PWA 结合了 Web 和本机应用程序的最佳部分来创建以下应用程序:

  • 性能有所提高;

  • 无需安装或更新;

  • 独立于任何应用商店;

  • 安全性由浏览器处理;

  • 平台独立;

  • 易于开发;

  • 离线时也可使用;

  • 允许推送通知;


考虑到所有这些好处,大型科技公司进入 PWA 领域也就不足为奇了。一些示例包括 Outlook Web Access、Twitter Lite 和 Pinterest。您可以通过在浏览器中访问它们并单击 URL 栏中的“添加到主屏幕”按钮或 + 图标(取决于浏览器和操作系统)来轻松查看这些内容。浏览器将提示您安装该应用程序。如果您同意,该应用程序将像您的手机或桌面上的本机应用程序一样安装。如果是手机,主屏幕上将添加一个新的应用程序图标,而桌面会在已安装应用程序列表中显示一个新条目:    

PWA(Progressive Web Apps)安全

PWA(Progressive Web Apps)安全

PWA(Progressive Web Apps)安全

          

PWA(Progressive Web Apps)安全

PWA(Progressive Web Apps)安全

                  

尽管 PWA 有很多好处,但使用这种方法也有一些缺点:

  • PWA 无法在移动设备(指纹扫描仪、NFC、蓝牙等)和桌面设备(蓝牙、Touch Bar 等)上使用硬件特定功能。PWA 受限于浏览器的功能,而用 Electron 或 React Native 编写的本机应用程序或跨平台桌面应用程序能够利用native  API;    

  • 本机应用程序允许更高级的安全措施,例如证书固定和应用程序商店安全验证和多因素身份验证。

新技术通常意味着新的攻击媒介。因此,研究此类 Web 应用程序的安全性可能会很有趣。由于 PWA 实际上是丰富的 Web 应用程序,因此所有已知的 Web 攻击仍然适用。尽管如此,PWA 利用了新技术和新功能,同时也承担了自己的安全责任。

          

PWA 的结构

          

如上一节所述,渐进式 Web 应用程序是丰富的 Web 应用程序,利用不同类型的新 Web 技术来创建更强大的应用程序。人们可能不会将 PWA 视为一种新型应用程序,而是将 PWA 视为普通的 Web 应用程序,并添加了 HTML5 中指定的以下功能:

  • manifest;

  • service worker。

manifest是一个 JSON 文件,它提供下载应用程序并将其呈现给用户的必要信息,就好像它是本机应用程序一样。它包括 PWA 的名称、描述、图标和显示选项等信息。

另一方面,Service Worker 为 PWA 添加了更多功能。这是一个在网页后台运行的 JavaScript 文件,允许开发人员向其 PWA 添加更多“类似应用程序”的功能。Service Worker 的一些功能包括推送通知、离线浏览(通过缓存实现)和后台同步。         
         
我们将在以下部分中仔细研究这两个概念。

PWA 与跨平台桌面应用程序

与 PWA 类似,用 Electron 编写的跨平台桌面应用程序正在普及。一些流行的例子是 Slack、Github Desktop 和 Visual Studio Code。但这些混合桌面应用程序和 PWA 之间有什么区别?

一方面,PWA 是纯粹的 Web 应用程序。它们的客户端代码仅由 JavaScript 和 HTML 组成,并且它们从运行它们的浏览器继承了所有可用性、性能和安全功能。         
Electron 应用程序是用 JavaScript、HTML 以及native代码编写的。他们利用 Chromium 的渲染引擎、Node.js 和native APIs 进行本机操作。         
因此,桌面应用程序能够使用操作系统的所有功能,而 PWA 则位于浏览器环境中并受到浏览器功能的限制。
   

虽然 PWA 似乎更受限制且灵活性较差,但与跨平台桌面应用程序相比,它们的简单性有几个好处:

  • 安装 PWA 是无缝的,并且会自动更新应用;

  • 安全性由(受到良好保护的)浏览器处理;

  • PWA 的规模通常要小得多;

  • PWA 可用于构建移动应用程序。

浏览器支持

PWA 不依赖于单一 API,而是使用各种技术来提供无缝的 Web 体验。PWA 背后的主要驱动力是 Service Worker。目前,移动和桌面上的所有主要浏览器都支持 Service Worker 。

PWA(Progressive Web Apps)安全

支持 Service Workers 的浏览器

另一方面,网络应用程序Manifest添加了“添加到主屏幕”功能,并且自定义应用程序图标 在移动浏览器上得到了广泛支持 。然而,在PC桌面端上,目前只有 Chrome 支持此功能。

Manifest

每个 PWA 都包含一个 Web 应用程序Manifest,该Manifest定义了当应用程序“安装”在用户的移动设备或桌面上时 PWA 的外观。这些属性包括名称、背景颜色、应用程序图标、显示选项等方面。当访问已导入Manifest的网站时,浏览器中将显示一个新选项,允许用户将 PWA 添加到主屏幕作为应用程序图标。         
         
Twitter 网络应用程序Manifest的简化版本:
   

Plaintext                  
{                   
   "background_color":"#ffffff",                  
   "description":"It's what's happening. From breaking news and entertainment, sports and politics, to big events and everyday interests.",                  
   "display":"standalone",                  
   "icons":[                   
      {                   
         "src":"https://abs.twimg.com/responsive-web/web/icon-default.3c3b2244.png",                  
         "sizes":"192x192",                  
         "type":"image/png"                  
      },                  
      ...                  
   ],                  
   "name":"Twitter",                  
   "short_name":"Twitter",                  
   "start_url":"https://twitter.com/?utm_source=homescreen&utm_medium=shortcut",                  
   "theme_color":"#ffffff",                  
   "scope":"/"                  
}

PWA 有不同的显示模式,可以在Manifest中声明。默认模式是将 PWA 显示为独立应用程序。在这里,PWA 看起来和感觉就像一个本机应用程序。另一种可能性是使用“浏览器”模式,其中将保留标准浏览器体验,包括 URL 栏。

Manifest声明了一个“start_url”参数,这是启动应用程序时将打开的 URL。这可以是绝对 URL,也可以是相对 URL。对于相对 URL,该域与安装 PWA 的域相同。         
         
此Manifest中另一个有趣的条目是范围。范围定义了 PWA 的边界。任何在此范围内的 URL 都将由 PWA 处理。这与 iOS 的
Apple-App-Site-Association 和 Android 的 App Links 非常相似,它们允许移动应用程序在网络上访问特定的 URL 时处理它们。请注意,如果用户导航到此范围之外,例如通过单击应用程序内的链接,则请求的页面将在现有 PWA 窗口中呈现,除非将“target=”_blank””添加到链接标记中。         
         
通过在 HTML 文档的 head 部分创建链接标记来部署 Web 应用程序Manifest。例如:
   

<link rel="manifest" href="./manifest.json">


在这里,Manifest托管在同一源上,因为它指定了相对路径。但是,也可以通过指定绝对路径将Manifest托管在外部源(例如内容分发网络 (CDN))上。在这种情况下,应该正确实现 CORS,以便 PWA 能够从外部资源获取Manifest。PWA 在获取Manifest时通过在链接标记中添加 crossorigin=”use-credentials” 属性来包含凭据,或者外部资源通过在其服务器中包含“Access-Control-Allow-Origin: *”来允许跨源请求回复。

如果 HTML 文档中声明了指向Manifest的多个链接,浏览器将使用第一个出现的链接。因此,能够利用目标 Web 应用程序中的跨站点脚本 (XSS) 漏洞的攻击者将无法覆盖Manifest。另一方面,如果应用程序没有配置Manifest,攻击者可以链接恶意Manifest。虽然潜在影响有限,但当应用程序作为 PWA“安装”在桌面或手机上时,攻击者可以控制名称、描述和图标。

某些浏览器支持新的“manifest-src”CSP 指令,该指令可能会限制可从中获取 Web 应用程序Manifest的域。可以在此处 找到支持的浏览器列表 。例如,以下 CSP 配置将仅从站点自己的源加载Manifest:

Plaintext                  
Content-Security-Policy: manifest-src ‘self’

Service workers

PWA 背后的主要驱动力是 Service Worker。在最基本的形式中,Service Worker 是前端和 Web 应用程序其余部分之间的可编程代理。它允许开发人员通过拦截从 Web 应用程序内部发起的每个请求来挂钩传出请求的某些功能。虽然它驻留在浏览器中,但它在单独的线程上执行,并且无法直接访问 DOM 或 UI。其主要目的是执行非 UI 任务,例如缓存、处理通知和提高性能。

有关 Service Worker 内部工作原理的详细指南超出了本博文的范围。相反,我们将介绍最重要的方面及其安全影响。更多信息可以在Google Web Fundamentals 上找到 。

为了安装 Service Worker,应使用 navigator.serviceWorker API 进行注册,并将 Service Worker JavaScript 文件作为参数传递。    

                
if ('serviceWorker' in navigator) {                  
  navigator.serviceWorker.register('/sw.js').then(
function(registration) {                  
    //service worker successfully installed                  
  }).
catch(function(err) {                  
    //service worker install failed                  
  });                         
}

register 方法仅接受相对 URL,因为Service workers必须驻留在与 Web 应用程序相同的域中。这意味着 XSS 漏洞不足以安装恶意 Service Worker,除非攻击者能够在同一源上托管恶意 Service Worker。

一旦Service Worker被注册,Service Worker的'install'和'activate'事件就会被触发,开发者可以在其中实现一些初始化功能,例如预缓存。预缓存允许应用程序已经缓存某些内容,以使应用程序响应更快。例如,OWA 已经可以缓存收件箱中的所有电子邮件,因为这些电子邮件很可能在启动应用程序后立即打开。

安装完成后,Service Worker 可以处于以下 3 种状态之一:

  • 获取/消息:Service Worker线程在不同的线程中主动运行,并根据 Web 应用程序执行的每个网络请求触发“获取”/“消息”事件。在这里,开发人员可以为每个请求精细地实现缓存并返回缓存的响应以支持离线可用性。

  • 空闲:Service Worker 正在等待传入事件;

  • 已终止:Service Worker 空闲 30 秒后,将终止。但是,一旦收到新事件,它就会变得空闲。Chrome 还可以检测长时间运行的Service Worker线程并终止它们。

          

          

一旦安装了 Service Worker,它就能够拦截同源和跨源请求。在应用程序内发起每个请求时,会在已安装的 Service Worker 内部触发“fetch”事件。典型的实现是配置一个Service Worker线程来侦听此事件并缓存特定的(经常使用的)资源。例如,音乐播放器应用的 PWA 版本可能会拦截并缓存您最常播放的 10 首歌曲,以便在您离线时可以使用它们。

以下代码片段显示了Service workers在控制台中记录所有请求的 URL 并随后利用浏览器的缓存存储来缓存之前未缓存的所有响应的示例。    

SQL                  
self.addEventListener('fetch', (event) => {                  
 
var request = event.request;                  
  //Logging each request to the console                  
  console.log(request.url)                  
                 
  //Tell the browser to wait for newtwork request and respond with below                  
  event.respondWith(                  
    //If request is already in cache, return it                  
    caches.match(request).then((response) => {                  
     
if (response) {                  
       
return response;                  
      }                  
      //if request is not cached, add it to cache                  
     
return fetch(request).then((response) => {                  
       
var responseToCache = response.clone();                  
        caches.open(cacheName).then((cache) => {                  
            cache.put(request, responseToCache).
catch((err) => {                  
              console.warn(request.url + ': ' + err.message);                  
            });                  
          });                  
       
return response;                  
      });                  
    })                  
  );                  
});

          

PWA(Progressive Web Apps)安全

Service Worker 在 Google Chrome 控制台中记录所有请求的 URL。

虽然 PWA 通常严重依赖缓存存储来提高性能和离线可用性,但开发人员应避免在缓存内存储机密信息。如果它们确实存储了任何机密信息,则由应用程序及时删除任何机密条目,因为浏览器不会删除它们(除非已达到缓存存储的最大数量)。例如,如果用户选择注销应用程序,则应清除本地缓存。Service Worker 可以访问缓存存储和 IndexedDB 来存储数据。    

PWA(Progressive Web Apps)安全

驻留在 Google Chrome 缓存存储中的请求和响应

请注意,Service Worker 遵循同源策略 (SOP),它在与其调用者相同的上下文中运行。因此,当发出跨源请求时,资源所在的源应该允许跨源请求(即通过在其服务器响应中添加“Access-Control-Allow-Origin: *”)。

Service Worker 由 Web 应用程序安装,无需任何客户端许可或不显示通知。再加上 Service Worker 无限期存在,并且一旦关闭浏览器就不会被删除,用户通常不知道是否为 Web 应用程序安装了某个 Service Worker。         
在 Chrome 中,用户可以打开开发人员工具并单击“应用程序”>“Service Workers”来查询所有已安装的 Service Worker。对于每个 Service Worker,都会显示域、源文件和状态。在这里,用户可以取消注册任何不需要的 Service Worker。         
如果您想一般禁用 Service Worker,可以通过禁用 chrome://settings 中的存储来完成。

PWA(Progressive Web Apps)安全

Google Chrome 开发者工具中的 Service Workers 选项卡    

恶意server workers

如前所述,Service Worker 充当 Web 应用程序的前端和后端之间的网络代理。对于攻击者来说,这确实是一个非常强大且有趣的目标,因为它可以让他劫持连接或提供修改后的响应。因此,最重要的是该 Service Worker 是可信的并且不能被攻击者修改。如果攻击者在某个时刻能够控制 Service Worker,则会导致持续的中间人 (MiTM) 攻击。为了最大限度地减少 Service Worker 的暴露,它们只能在通过 HTTPS 提供服务的页面上注册,以确保接收到的 Service Worker 未被篡改。

尽管如此,以下两种攻击媒介可能允许攻击者在受害者的浏览器中安装针对特定域的恶意 Service Worker:

XSS 和文件上传

对于这种攻击,Web 应用程序应该容易受到 XSS 攻击,并允许用户上传自己的文件并通过同一域上的链接直接访问它们。当网站实施非常安全的内容安全策略(不允许内联脚本且仅允许来自许多白名单资源的脚本)时,可以使用此方法。由于 Service Worker 也无法从外部域加载,因此还需要上传文件。如果应用程序满足这两个条件, 则可以利用 影子工作者来利用该应用程序。Shadow Workers 项目是恶意 Service Worker 和 C&C 服务器的组合。如果攻击者能够在受害者的浏览器中安装 Service Worker,则攻击者可以通过 Service Worker 代理并以受害者身份浏览受感染的应用程序。此外,Service workers还包括后利用模块,例如允许攻击者执行本地主机端口扫描。

休眠service worker

在休眠 Service Worker 攻击中,用户在不知情的情况下在本地主机的特定端口上安装了恶意 Service Worker。这可以通过社会工程让受害者运行恶意代码或在服务于不同目的的项目上隐藏恶意脚本来实现。从那时起,Service Worker 在本地主机上仍然有效,并且将处于空闲状态,直到它被显式取消注册为止。之后,当用户在本地主机和同一端口上运行不同的应用程序时,休眠服务将变为活动状态,并允许攻击者执行 MiTM 攻击。

请注意,Service workers强制通过 HTTPS 安装,但 localhost 是严格安全策略的例外,以允许轻松开发。    

 HackerOne 的漏洞报告中记录了休眠 Service Worker 攻击 ,其中恶意 Service Worker 安装在 http://localhost:8080 上以攻击 Augur 客户端。

影响

为了限制恶意服务器工作人员的影响,内置了以下安全功能:

  • Service Worker 无权访问 DOM(因此也无权访问 Cookie);相反,Service Worker 可以通过响应通过 postMessage 接口发送的消息来与其控制的页面进行通信,这些页面可以在需要时操作 DOM。然而,应用程序应该支持这一点才能工作。

  • Service Worker 只能出于缓存目的访问 Cache Storage 和 indexedDB,而不能访问本地或会话存储;

  • Service workers无法读取和设置一组 禁止的标头 (它们可能包括会话标识符或其他有价值的信息)。

          

              

原文始发于微信公众号(暴暴的皮卡丘):PWA(Progressive Web Apps)安全

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年12月6日13:18:50
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   PWA(Progressive Web Apps)安全http://cn-sec.com/archives/2269886.html

发表评论

匿名网友 填写信息