ForesightNews文章 2024年08月29日
技术详解 | CertiK 揭示秘密修复的 Solana 核心漏洞
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

Solana 虚拟机(SVM)是 Solana 区块链的核心组件之一,负责执行智能合约和去中心化应用程序。近期,CertiK 团队分析了 Solana 虚拟机中存在的严重指令漏洞,该漏洞可能导致 SVM 崩溃,甚至可能被恶意利用,造成严重的安全风险。

😁 **漏洞存在于 rbpf SVM 虚拟机中的`callx regs`指令:** 该指令用于在智能合约执行过程中跳转到指定地址,但由于其对输入参数的校验不足,攻击者可以构造恶意指令,导致 SVM 虚拟机崩溃。 漏洞的核心原因在于,`callx regs`指令在计算跳转地址时,没有对传入的`target_pc`值进行正确的内存对齐操作,导致程序可能跳转到一个不一致的地址,从而引发崩溃。 攻击者可以通过精心构造的 ELF 文件,控制`program_vm_addr`的值,使其与`target_pc`值不对齐,从而触发该漏洞。 该漏洞的修复主要集中在对`target_pc`值的处理上,首先获取相对地址,确保其正确对齐,然后进行越界检查,最后计算出正确的跳转地址。

😊 **漏洞的危害:** 该漏洞可能导致 SVM 虚拟机崩溃,使运行恶意合约的 Solana 节点无法正常使用。 此外,攻击者还可以利用该漏洞,通过精心构造的内存数据,获取到一个能控制的任意跳转地址,从而执行任意命令,篡改合约执行数据,造成严重的安全风险。

😉 **Solana 团队采取了秘密修复措施:** Solana 团队在发现该漏洞后,迅速采取了秘密修复措施,通过私人渠道联系了知名网络运营商,并提供了补丁,使运营商能够独立验证和应用更改。 这一做法有效地防止了漏洞被恶意利用,保护了链上资产和用户利益。 尽管如此,该漏洞的发现也提醒我们,安全漏洞可能存在于任何软件系统中,需要持续关注和改进安全措施。

🤔 **关于 SVM 虚拟机漏洞的思考:** SVM 虚拟机是许多区块链平台的重要组成部分,其安全性至关重要。 该漏洞的发现,提醒我们必须重视底层代码的安全性,并加强对安全漏洞的测试和修复。 同时,我们也需要关注区块链平台的安全性,并不断提升安全意识,才能更好地保护用户资产和网络安全。

🚀 **Solana 团队的快速响应:** Solana 团队对该漏洞的快速响应和秘密修复措施,体现了其对安全问题的重视和快速解决问题的能力。 这对于保障 Solana 生态系统的稳定发展和用户信任至关重要。

😭 **漏洞的生命周期:** 该漏洞的生命周期可能长达 2 年以上,这说明安全漏洞可能存在于软件系统中很长一段时间,需要持续关注和改进安全措施。 同时,也提醒我们,安全漏洞的发现和修复需要一个持续的过程,需要不断加强安全测试和漏洞修复工作。

😈 **恶意攻击者的可能性:** 虽然 Solana 团队及时修复了该漏洞,但我们不能排除恶意攻击者可能已经利用该漏洞进行攻击的可能性。 因此,需要持续关注和监控网络安全,及时发现和处理潜在的安全风险。

😇 **Solana 的未来:** 随着类似 SVM 虚拟机漏洞的减少,Solana 将变得更加稳定和安全。 这将吸引更多开发者和用户加入 Solana 生态系统,推动 Solana 的发展。

🙏 **安全意识的重要性:** 该漏洞的发现,再次强调了安全意识的重要性。 无论是开发者还是用户,都需要不断提升安全意识,加强安全防护措施,才能更好地保护自身利益和网络安全。

🤨 **对 Solana 虚拟机的改进:** 该漏洞的发现,也为 Solana 虚拟机提供了改进的方向。 例如,可以加强对`callx regs`指令的校验,避免类似漏洞的出现。

💖 **对区块链安全的研究:** 该漏洞的发现,也为区块链安全的研究提供了新的方向。 例如,可以研究如何更好地检测和修复智能合约中的漏洞,提高区块链平台的安全性。

💔 **对用户资产的保护:** 该漏洞的发现,提醒我们必须重视用户资产的保护。 无论是开发者还是用户,都需要不断提高安全意识,加强安全防护措施,才能更好地保护自身利益和网络安全。

😎 **对 Solana 生态系统的贡献:** 该漏洞的发现和修复,将有助于提高 Solana 生态系统的安全性,吸引更多开发者和用户加入,推动 Solana 的发展。

😭 **对安全测试的重要性:** 该漏洞的发现,再次强调了安全测试的重要性。 无论是开发者还是用户,都需要不断进行安全测试,及时发现和修复安全漏洞,才能更好地保护自身利益和网络安全。

  1. Solana 漏洞起因8 月 9 日,Solana 验证者和客户端团队齐心协力解决了一个严重的安全漏洞。Solana 验证者 Laine 表示,这一过程始于 8 月 7 日,当时 Solana 基金会通过私人渠道联系了知名网络运营商。此次联系是秘密修补漏洞策略的一部分,旨在防止漏洞被以任何方式利用。补丁通过 Anza 工程师的 GitHub 存储库提供,使运营商能够独立验证和应用更改。这次秘密修复的详情可以在 GitHub 存储库最近一次发布的 Mainnet-beta(https://github.com/anza-xyz/agave/compare/v1.18.21...v1.18.22)中找到,唯一的改变是 rbpf SVM 虚拟机,从 8 月 9 日的 rbpf SVM 虚拟机唯一 pull(https://github.com/solana-labs/rbpf/pull/583)可以定位到漏洞所在,虽然这一过程是秘密进行的,但是依然是通过开源存储库,Solana 顺利地过渡了这次安全性危机。这个漏洞究竟有多大危害,以至于让 Solana 团队如此重视?CertiK 团队对这一漏洞进行了深入分析。漏洞存在于 rbpf SVM 虚拟机中,SVM(Solana Virtual Machine)是 Solana 区块链生态系统的核心组件之一,负责执行智能合约和去中心化应用程序。其核心原理是利用即时编译技术实现高性能的智能合约执行。由于 Solana 的高吞吐量和低延迟特性,SVM 在 Solana 中扮演着至关重要的角色,为开发者提供了一个高效的去中心化应用开发环境,并且对 Solana 的安全性起着重要作用。本文将会详细分析漏洞的核心原理与影响。2. SVM 虚拟机存在严重的指令漏洞SVM 是 Solana 区块链平台的关键组成部分,用于提供高效、安全的执行环境,用于运行智能合约和分布式应用程序。SVM 的设计采用了 rbpf 字节码解释器(interpreter)和即时编译器(JIT),通过全局状态和智能合约接口实现与区块链网络的交互。关于 SVM 虚拟机如何加载运行 elf 智能合约可以参考上一次 CertiK 对 rbpf 的漏洞分析章节中关于 SVM 运行模式介绍。这次漏洞的核心补丁是 commit(https://github.com/solana-labs/rbpf/pull/583)对 rbpf SVM 虚拟机的修复。漏洞的根源在于精心构造的callx regs指令会导致 rbpf SVM 虚拟机崩溃。接下来,我们将分析callx regs指令如何引发如此严重的影响。首先,我们需要了解 SVM 虚拟机中SBF指令callx regs的运行模式和基础信息:a. SBF 指令基本的寻址SBF指令的基本结构如下图所示,其中program_vm_addr是 SVM 虚拟机中指令的起始地址。对于 SBFV1 版本的智能合约,program_vm_addr计算公式为text_section.sh_addr.saturating_add(ebpf::MM_PROGRAM_START)text_section.sh_addr是 ELF 头部的text address。在 SVM 虚拟机中,每条SBF指令的大小为ebpf::INSN_SIZE,即 8 字节。下图中的 program.len表示 n+1 条SBF指令的总大小。b. Callx regs 的运行模式在 SVM 虚拟机中,callx regs指令的运行模式如下:target_pc是传入 callx指令的寄存器值,并作为 SVM 虚拟机中的程序计数器(PC)偏移量。在执行callx regs时,两个关键检查用于确保寄存器值不越界。检查程序起始地址:确保target_pc不小于程序的起始地址。program_vm_addr代表SBF程序的起始地址。检查条件是program_vm_addr <= target_pc,确保target_pc不低于程序的起始地址,从而避免程序跳转到非法地址。检查程序结束地址:确保target_pc不超过程序的最大地址。program.MaxAddr代表SBF指令在程序中的起始地址加上整个程序的指令大小。检查条件是target_pc < program.MaxAddr,确保target_pc在程序的有效范围内,避免越界访问。如果这两个条件都满足,则程序会安全地跳转到指定的 PC 地址。c. 漏洞的 root cause通过前文对SBF指令基本寻址和callx regs运行模式的了解,我们可以分析 JIT 模式下callx regs存在漏洞的关键原因。首先先分析下在 JIT 模式中SBF指令寻址映射到 x86 机器码的过程,JitProgram结构体包含了两个重要成员:pc_section:存储每个SBF指令映射到 x86 机器码在text_section中的偏移地址。这个字段提供了从指令到机器码的映射,使得在执行SBF指令时可以快速找到对应的机器码位置。text_section:存储 x86 机器码的内存区域。它包含了即时编译生成的机器码,供处理器在运行时执行。即使在执行 x86 机器码时,也需要根据SBF 指令寻址到相应的机器码。例如,callx target_pc指令中,target_pc可以通过索引pc_section数组寻址到相应的 x86 机器码偏移。如果target_pc偏移的换算过程出现问题,导致从 pc_section取得的偏移不正确,可能会导致获取的执行的 x86 机器码不一致。在JitProgram中初始化pc_sectiontext_section的流程如下:确定页面大小:通过get_system_page_size()获取系统的页面大小,这通常是内存管理的基本单位。pc_loc_table_sizepc_loc_table_sizePC * 8的大小,其中pc是传入的指令数量。此大小四舍五入到页面大小的倍数,因为pc_section存储的是text_section中对于 x86 机器码地址偏移,usize类型的地址大小在 64 位系统中刚好是 8 字节。over_allocated_code_sizeover_allocated_code_sizecode_size四舍五入到页面大小的倍数。这样做是为了确保分配足够的内存来存放 x86 机器码。分配内存:通过allocate_pages分配的内存总大小是pc_loc_table_size + over_allocated_code_sizeallocate_pages返回一个裸指针,指向分配的内存区域。初始化pc_sectionpc_section是一个可变切片,指向内存的起始部分,用于存放pc个 x86 机器码地址。通过std::slice::from_raw_parts_mut创建,raw.cast::<usize>()将裸指针转换为*mut usize类型,切片的长度为 pc,每个元素的大小为 8 字节。初始化text_sectiontext_section是另一个可变切片,指向分配内存区域的后半部分,用于存放 x86 机器码。它从pc_loc_table_size位置开始,到内存的末尾。这通过raw.add(pc_loc_table_size)确定起始地址(跳过pc_section存储大小),大小为over_allocated_code_sizepc_section用于存储指令计数器位置表,大小为pc * 8,而text_section用于存储 x86 机器码,大小为code_size,所有内存分配都以页面大小对齐。JitProgram的每一次compile``SBF指令时候都会将偏移的text_section地址存储到pc_section中,而text_section保存了 x86 机器码的偏移地址:在callx regs指令中,通过传入的target_pc计算出相对地址后跳转到存储在pc_section中的 x86 机器码地址。在 JIT 模式中,通过计算target_pc - program_vm_addr获取相对地址。JIT 模式下通过获取的相对地址和self.result.pc_section.as_ptr() as i64数组指针地址相加可以获取pc_section数组中存储的text_section地址。其中self.result.pc_section.as_ptr() as i64获取的是pc_section裸指针的数组基地址,pc_section是一个&[usize]类型的切片,想要正确索引pc_section数组的值,获取的裸指针地址索引偏移必须是 8 字节的整数倍。在了解完 callx regs 的寻址方式,接着分析造成漏洞 root cause 的地方。漏洞的根本原因在于获取相对地址的过程。callx regs指令的处理流程如下:1. 获取target_pc的值作为绝对地址。2. 绝对地址按照 8 字节对齐。3. 判断绝对地址是否越界。4. 获取相对地址。5. 通过相对地址和pc_section数组指针地址计算最终跳转的 x86 机器码地址。漏洞的关键点在于第 4 步,合约中program_vm_addrtarget_pc的值传入可控,target_pc的值为callx regs的值,而program_vm_addr的值需要根据 ELF 格式经过精心构造并且绕过 SVM 虚拟机对 ELF 格式的安全检查,就可以控制program_vm_addr的值。这里起始地址program_vm_addr值的构造需要注意 SVM 虚拟机中的主要几个检查:1. 这个检查代码的目的是计算 ELF 文件中入口点(Entrypoint)相对于文本段(text section)的偏移量,并检查这个偏移量是否是指令大小ebpf::INSN_SIZE的整数倍,目的是确保入口点(Entrypoint)在 ELF 文件的文本段(text section)中对齐到正确的指令边界,由于text_section.sh_addr用作program_vm_addr的偏移,所以这里得和入口点(Entrypoint)的偏移对齐:2. 检查入口点header.e_entry是否在.text节的虚拟地址范围内。如果入口点不在该范围内,返回ElfError::EntrypointOutOfBounds错误。target_pc作为绝对地址在第二步中按照 8 字节对齐,是 8 的整数倍,target_pc个位数只要小于 8,执行对齐操作后将为 0,大于等于 8 将为 8,传入正常的program_vm_addr与 8 字节对齐的值将不会造成越界,只要获取到的program_vm_addr为并不与 8 字节对齐且小于 8,target_pc减去program_vm_addr,可以获取到不与 8 字节对齐的相对地址,这里获取到的可控的相对地址范围为(relative address < number_of_instructions * INSN_SIZE),相对地址将会用作索引pc_section数组,这里计算方式是直接获取self.result.pc_section.as_ptr() as i64裸指针进行切片地址索引,未与 8 字节对齐的相对地址将会导致pc_section数组基指针引用错误,将会获取到一个越界地址,而越界的范围需要小于number_of_instructions * INSN_SIZE,这个非法地址将会导致后续 call 跳转到一个不一致的地址,假如访问到非法地址程序系统将会抛出段错误Segmentation fault,这将导致 SVM 虚拟机直接崩溃,如果通过精心构造的内存数据,可能会获取到一个能控制的任意跳转地址,后续甚至执行任意命令!d. 漏洞修复漏洞修复后的补丁对比如下:1. 绝对地址:获取target_pc的值作为绝对地址。2. 计算相对地址:首先通过减去program_vm_addr来获取相对地址。这一步确保了后续操作能够正确处理内存对齐问题。3. 内存对齐:将相对地址按照 8 字节进行内存对齐。4. 越界检查:判断对齐后的相对地址是否越界。5. 获取跳转地址:最终计算出PC跳转的地址。修复漏洞的关键在于第一步,通过首先获取相对地址并确保其正确对齐,从而避免了之前未对齐带来的问题。3. SVM 漏洞 x86 代码调试与复现在这一章节,我们将通过分析代码和漏洞调试来复现问题。存在漏洞的合约 POC 构造如下:a. SBF 指令构造假设rax = target_pctarget_pc = 0x100000129,以下是相关指令的构造,这里的 r1 在 SVM 中为 rax:这些包含的SBF指令被编译成 ELF 合约,版本为 SBFV1。text_section.sh_addr通过以下计算得出:通过readelf工具,可以查看编译出的包含上述SBF指令的执行合约 ELF 文件的头部信息,其中.text段的地址为0x121,这里通过正常的合约编译出来的 ELF 结构并不能完全控制.text部分,需要精心修改.text段的addressEntrypoint的偏移,然后修复相应的 ELF 结构,才能得到能正确执行的合约。最终的program_vm_addr计算如下:在上述代码中,program_vm_addr的最终值为0x100000121。b. SBF 指令构造在 JIT 模式下,将SBF指令翻译为 x86_64 汇编指令如下:在调试器中,rsi计算出的target_pc值为0x100000129,这里的target_pc只需要小于number_of_instructions * INSN_SIZE。获取target_pc后,进入call地址检查流程,最终得到call_address:在调试器中获取到相对地址,relative address = absolute address - program_vm_addr如下:获取pc_section数组的基地址:0x7ffff7e9a000``pc_section数组的基地址0x7ffff7e9a000中连续保存了 3 个SBF指令映射到 x86 机器码的地址分别是:0x7ffff7e9b6d00x7ffff7e9b6d40x7ffff7e9b6e5,但是引用地址0x7ffff7e9a007获取的值是0x7ffff7e9b6d400,这是个无效的非法地址。最后直接call越界的非法内存地址,造成段错误Segmentation faultc. 补丁 commit存在漏洞的commit补丁如下:4. SVM 虚拟机指令漏洞影响Callx 指令在智能合约中至关重要。内存越界常常成为底层漏洞的根源,而在 SVM 虚拟机中,尤其是在 Solana 链上,这种漏洞可能导致 SVM 崩溃,使运行恶意合约的 Solana 节点无法正常使用,如果通过恶意攻击者进行精心构造的内存布局甚至会导致任意代码执行,篡改合约执行数据。此外,这个漏洞的生命周期可能长达 2 年以上。Solana 对这一漏洞的秘密处理非常有效,成功保护了链上资产和用户利益。随着类似 SVM 虚拟机漏洞的减少,Solana 也将变得更加稳定。

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

Solana SVM 漏洞 安全 区块链 智能合约 CertiK
相关文章