迈向2023:浏览器与操作系统安全特性
引言
2022年已悄然结束,我们不禁展望2023年,思考信息安全领域将如何演变。传统安全边界栈已发生巨变,古老的“城堡与护城河”模型彻底瓦解。从云迁移到浏览器直接交付的高功能应用,再到终端用户启用的影子IT和零信任安全模型,边界概念被彻底重新思考,安全专业人员面临巨大焦虑。
我们必须通过变革适应这些挑战。固守城堡与护城河模型的控制幻想是徒劳的。本文将重点讨论常用的Windows工作站终端。
终端上部署的保护操作系统本身的安全技术取得了显著进步。终端/扩展检测与响应(EDR/XDR)软件能力显著成熟,假设部署和调优成熟,Windows终端上的初始入侵和后利用活动变得极具挑战性。
虽然这对行业来说是极好的消息,但我们必须问自己:最大化桌面操作系统保护是否仍像过去一样重要?换言之,我们必须承认,关键业务数据越来越多地在Web浏览器中管理。
自然推论的问题是:浏览器中是否部署了足够的安全技术?这些保护措施能否与操作系统部署的保护相媲美?这些保护措施是否与操作系统级别的防御部署集成?
Google Chrome与Chromium项目
从Web浏览器市场份额看,Google Chrome明显领先。此外还有基于Google Chromium项目的浏览器,如Opera和Microsoft Edge(显著位居第二)。由此数据可知,Chromium开源项目中的任何安全漏洞都将非常重要,Chrome和Edge浏览器中的专有安全相关代码也至关重要。
Web浏览器市场份额
在此背景下,Chrome和Chromium中实施了哪些安全特性来保护浏览器及其用户?
Google团队创建了一个安全架构图,从进程级别角度很好地识别了攻击面。主要关注的目标区域是浏览器进程和渲染器进程。
Chrome安全架构:进程视角
鉴于上述浏览器架构和进程级别关注点,让我们分解一些为应对浏览器安全关切而编写的保护技术。请注意,以下信息大多研究自Google博客和在线设计文档。Chrome/Chromium浏览器工作中有几个关键的架构基础和特性相关。
- 渲染器沙箱
- 站点隔离(Spectre缓解)
- V8(JavaScript)沙箱(堆利用缓解)
- 改进内存安全
- 用户端安全控制
渲染器沙箱
Chromium项目渲染器沙箱遵循健全的基础安全原则。如前所述,本次讨论将保持在Windows桌面上下文中。这些原则包括:
- 不重新发明轮子。让操作系统对其控制的对象应用安全措施。
- 最小权限原则应用于沙箱化代码和运行沙箱本身的代码。
- 始终假设沙箱化代码是恶意的。
- 最小化性能影响。
- 不使用模拟、代码转换或修补来提供安全。
Windows架构是用户模式实现。至今没有支持的内核驱动程序。沙箱架构分为两个进程:代理进程和目标进程。代理是执行实际工作的目标进程的监督者。
代理进程
代理进程职责包括:
- 为每个目标进程指定策略。沙箱目标拦截在接收时根据此策略评估
- 生成目标进程
- 托管沙箱策略引擎和拦截管理器
- 为目标进程托管沙箱IPC服务
- 代表目标进程执行策略允许的操作
目标进程
目标进程是实际的渲染器本身。职责包括:
- 托管要沙箱化的代码
- 运行沙箱IPC客户端进行消息传递
- 作为沙箱策略引擎客户端
- 执行沙箱拦截。注意,拦截是通过沙箱IPC将Windows API调用转发到代理的方式
沙箱进程架构
沙箱限制依赖于Windows操作系统提供的保护,包括使用:
-
高度受限的安全令牌,实现组限制,无特定权限,并使用“不受信任的完整性级别”。不受信任的完整性级别只能写入具有空DACL或显式强制完整性控制(MIC)级别为不受信任的资源。
-
用于目标进程的Windows作业对象,实现众多限制,包括:
- 禁止每用户系统范围更改
- 禁止创建或切换Windows桌面
- 禁止更改显示设置
- 禁止剪贴板访问
- 禁止Windows消息广播
- 禁止通过SetWindowsHookEx() API调用设置全局钩子
- 禁止访问原子表
- 禁止访问作业对象外的用户句柄
- 限制为一个活动进程(不允许创建子进程)
-
Windows桌面对象:沙箱创建一个与所有目标进程关联的额外桌面。此桌面永远不可见或交互,有效隔离沙箱化进程免受用户交互窥探和向在更高特权上下文操作的窗口发送消息。
站点隔离
站点隔离是一项努力,旨在完全重新架构浏览器安全模型,使其更紧密地与操作系统进程安全边界对齐。站点隔离项目既是对成功攻击渲染引擎的第二道防线,也是缓解CPU推测执行内存泄漏攻击(Spectre)的响应。对于瞬态执行攻击,考虑了缓解策略,包括:
- 移除精确计时器,这对平台操作方面有害
- 实施编译器/运行时扫描缓解措施,被认为不切实际
- 保持数据隔离/不可访问,这最终是站点隔离实现的
“站点”概念不如“源”概念精细。源包括协议方案、主机名和端口。而站点由有效顶级域(eTLD)加上其前的域部分定义,也称为eTLD+1。注意:由于没有算法方法确定eTLD中的域后缀,现在维护了一个公共后缀列表(https://github.com/publicsuffix/list)。
源示例
站点示例1
站点示例2
V8(JavaScript/WASM)沙箱
自2020年中以来,Google的开源JavaScript/Web汇编引擎(V8)实施了堆管理的指针压缩。这意味着V8堆中从一个对象到另一个对象的每个引用成为从堆基址的32位偏移。
因此,压缩指针仅在4GB内存范围内有效,称为指针压缩笼。因此,可利用破坏内存的大多数漏洞只能在此压缩笼内破坏。
存在一些具有原始(绝对)指针指向堆外对象(堆外)的对象。攻击者可以针对这些少数对象(通常是Array Buffer或类型化Array后备存储指针)来破坏堆外内存,这当然不理想,可能导致代码执行。
V8沙箱项目目标是以防止攻击者滥用的方式保护这些剩余的少数对象。总之,此设计通过以下方式实现目标:
- 在初始化期间保留一个大的1TB内存区域(沙箱)。此内存区域包含指针压缩笼以及数组后备存储和其他对象的存储。
- 此沙箱内但V8堆外的所有对象使用40位固定大小偏移而不是原始指针寻址。
- 任何剩余的“堆外”对象必须通过外部指针表引用,该表包含实际指针和对象类型信息,以额外帮助防御类型混淆风格攻击。
改进内存安全
2020年期间,Chromium项目研究并发布,超过70%的高严重性安全缺陷与内存安全相关,其中超过一半是“释放后使用”类型。具体来说,这转化为C/C++语言中指针的错误,导致内存被误解。几乎不用说,这个问题是几十年来影响软件行业的瘟疫。
Chrome一直在探索解决此问题的途径,包括:
- 通过编译时指针正确性检查使C/C++更安全
- 通过运行时指针正确性检查使C/C++更安全
- 调查对部分Chromium代码库使用内存安全语言
在C/C++安全方面,项目探索了使用“Miracle Pointers”,这实际上只是一类算法的术语,这些算法将指针使用包装在模板化内存安全C/C++类中。这些实现的目标是消除最大的“释放后使用”类型漏洞。
在内存安全语言实施方面,团队一直在探索Rust作为代码库部分的潜在替代方案。
用户端安全控制
Chrome附带许多用户端安全特性,可帮助缓解初始浏览器利用尝试的风险。这些包括:
- 安全浏览:阻止列表,警告潜在恶意站点。
- 预测性网络钓鱼保护:扫描页面以查看是否匹配已知虚假或恶意站点。
- 隐身模式:也称为隐私浏览模式。所有浏览历史记录和cookie在隐身模式会话结束时删除。浏览器也不会记住输入表单的任何信息或授予网站的权限。
- 安全检查:用户驱动的浏览器“安全检查”审计。安全检查为您运行一系列基本检查,例如:
- Chrome软件是否完全最新?
- 您保存的密码是否在公开泄露中受损?
- 安全浏览功能是否启用?
- 您是否启用了任何有害扩展?
- 您是否下载了任何已知有害软件?
- 自动更新:Chrome将在软件更新可用时通知。
Chrome扩展
Chrome扩展用于向浏览器添加额外特性和功能。扩展使用与网站相同的技术编写,这些技术是:
- 用于内容标记的HTML
- 用于内容样式的CSS
- 用于脚本逻辑的JavaScript
扩展可以利用一项新兴技术称为WebAssembly(Wasm)。WebAssembly是面向基于堆栈的虚拟机的二进制指令格式,可在浏览器中JavaScript引擎的相同上下文中执行。Google的V8实现实际上既是WebAssembly又是JavaScript引擎。
WebAssembly旨在通过利用目标平台的硬件能力在接近本机性能水平运行。因为它是二进制指令格式,假设编写了相关编译器,不同的高级语言可以编译为WebAssembly。
扩展可以使用浏览器提供的所有JavaScript API,以及访问Chrome API。此额外级别的Chrome API访问允许诸如:
- 更改网站的功能或行为
- 跨不同网站收集信息
- 向Chrome开发工具添加特性
扩展可以分为两个组件:内容呈现组件和服务工作器组件。服务工作器作为某种后台任务运行,可以通过消息传递或浏览器本地存储与呈现组件交互。服务工作器是事件驱动的,可以使用所有Chrome API,但不能直接与Web内容交互。
Chrome扩展正式发布在Chrome Web Store中。安装时,它们允许开发人员通过MANIFEST请求对您的Web浏览器的大量权力和控制。关于扩展要考虑的事项:
- Chrome扩展可以读取和修改网页内容。
- Chrome扩展可以访问cookie、浏览器历史和浏览器数据存储。
- Chrome扩展可以跨网络传输和接收任何数据。
- Chrome扩展可以施加控制其他Chrome扩展。
- Web Store中的Chrome扩展不保证无恶意软件。
- 安装扩展时,您向该扩展的开发人员扩展了大量信任。
Chrome命令行开关
我们可能都习惯于单击Chrome图标并假设Chrome正常启动,信任一切正常。话虽如此,有几个命令行开关可用于更改Chrome启动时的行为。其中一些开关专门禁用或削弱浏览器的安全特性,通常用于测试/开发目的。
我确定了以下开关列表,这些开关我已实验性使用、在恶意软件报告中阅读过,或怀疑可能呈现安全关切。恶意软件杀死Chrome进程然后重新启动Chrome,添加一些命令行开关以更改浏览器行为(例如加载恶意扩展)并不罕见。
--allow-legacy-extension-manifests
:允许浏览器加载缺少现代清单且否则被禁止的扩展。--allow-no-sandbox-job
:允许沙箱化进程在没有分配给它们的Windows作业对象的情况下运行。这具有扩大对通常不可用的Windows API的访问的效果。--allow-unsecure-dlls
:设置时不允许EnableSecureDllLoading()运行。(可能允许您加载任何未签名的DLL。)--disable-breakpad
:禁用崩溃报告。--disable-crash-reporter
:在无头模式下禁用崩溃报告。--disable-extensions-http-throttling
:禁用源自扩展的HTTP(s)请求的net::URLRequestThrottleManager()功能。--disable-web-security
:不强制执行同站点源策略。--hide-crash-restore-bubble
:禁用显示浏览器崩溃/恢复气泡。--load-extension
:启动时从磁盘加载扩展。--load-empty-dll
:每当设置此标志时加载文件“empty-dll.dll”。--proxy-server
:使用指定的代理服务器覆盖系统代理设置。--no-sandbox
:完全禁用渲染器沙箱。--restore-last-session
:崩溃/退出后恢复最后浏览会话。--single-process
:在同一进程中作为浏览器运行渲染器和插件。
ChromeLoader恶意软件是使用PowerShell杀死Chrome进程然后重新启动,加载已丢弃的扩展的示例。
结论
很明显,Google非常重视对渲染器和JavaScript引擎的攻击以及推测执行内存泄漏构成的威胁。因此,他们实施了强大的防御架构,尽力缓解风险。
话虽如此,Chrome浏览器终端是非常复杂的软件架构。在JavaScript和现在WebAssembly领域拥有动态编译环境(即时编译器)总是可能遭受逻辑缺陷,攻击者可以强制编译器/汇编器引擎发出恶意代码。在V8 JavaScript/WebAssembly空间继续堆保护工作在此充当一道防线。
除非整个架构用内存安全语言重写(这 frankly 将是一项巨大努力),否则内存释放后使用缺陷很可能继续被发现。我赞赏围绕边缘工作的努力,通过提议对最有意义的暴露组件重写到内存安全语言来逐步解决问题。
我还认为我们很可能看到Chrome/Chromium团队在控制流防护和控制流执行技术领域更多兴趣,这进一步使浏览器不仅与Windows操作系统安全防御对齐,而且与CPU硬件对齐。
最后,与过去十年信息安全的大部分情况一样,您无法预测终端用户将做什么。如果终端用户下载恶意软件,进而丢弃恶意扩展和脚本以静默重新启动浏览器,扩展授予浏览器的权力暴露了显著的攻击面。我质疑许多这些命令行开关在Chrome发布版本中是否存在合法的操作用例,并建议发布版本消除大部分此能力以进一步减少攻击面。
新年快乐,2023年更安全浏览。