STATEMENT
声明
由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,雷神众测及文章作者不为此承担任何责任。
雷神众测拥有对此文章的修改和解释权。如欲转载或传播此文章,必须保证此文章的完整性,包括版权声明等全部内容。未经雷神众测允许,不得任意修改或者增减此文章内容,不得以任何方式将其用于商业目的。
NO.1 SpectreRSB:
基于RSB机制的瞬态执行漏洞
在本文中,我们将为读者介绍基于返回堆栈缓冲区(RSB)推测机制的瞬态执行漏洞的相关概念和原理,并深入分析相关的示例代码。
NO.2
SpectreRSB漏洞简介
SpectreRSB漏洞是一种基于返回堆栈缓冲区(RSB)的瞬态执行漏洞变种。而所谓返回堆栈缓冲区(RSB),其实就是一个硬件堆栈,用于跟踪先前call指令的返回地址,当遇到ret指令时,由于软件栈的访问速度较慢,处理器就会先把RSB的顶部的地址用作返回地址,进行推测地执行。当软件栈中的返回地址取回时,如果与RSB的顶部的地址一致,则接受推测执行的结果;如果不一致,则撤销推测执行的结果,并根据软件栈给出的返回地址继续执行。
由于在瞬态执行过程中,可以越界访问内存,并且在完成回滚后,访问的内存数据还会留在缓存中,因此,攻击者就可以设法让RSB与软件栈的返回地址不一致(如篡改软件栈),触发瞬态执行,越界访问机密信息并进行编码,然后,通过缓存侧信道来解码瞬态执行过程中访问的数据。
也就是说,这里的关键是理解函数过程中软件栈和RSB的变化情况,以及如何篡改软件栈,从而触发瞬态执行;至于机密信息的编码和缓存侧信道,与前面介绍的方法是一样的,这里就不再赘述。
NO.3
函数调用过程中软件调用栈和RSB的变化
RSB是处理器中的一个硬件堆栈缓冲区,每当执行call指令的时候,相应的返回地址都会压入做个内部的硬件堆栈中(通常情况下,它可以保存16个条目),以便将来预测返回地址。当遇到ret指令时,处理器就使用RSB的栈顶元素来预测返回地址,通常情况下,它的预测准确度是非常高的。
下面,我们举例说明函数调用过程中,RSB和软件栈的变化过程,具体如下图所示。
图1 软件调用栈与RSB在函数调用过程中的变化
当main函数调用函数F1时,会将相关参数压入栈中,然后,执行call指令。众所周知,call指令将执行两个动作:首先,将返回值(这里为0x00006210)压入栈中,同时,也将这个返回地址压入RSB中;然后,将函数F1的地址送入EIP寄存器中,这样,就会在下一个时钟周期来临时,跳转到F1中。进入函数F1后,会首先保存ERP寄存器的值,然后,将指向栈顶的ESP的值,送入ERP,这时,两个寄存器都指向保存原来的ERP值的内存地址,然后,将ESP的值减去一定数目(栈是向低地址方向生长的),也就是为当前函数F1的局部变量分配内存空间。之后,继续调用函数F2,并重复上述过程,最后,软件调用栈和RSB就变成了上面图1的样子。
需要注意的是,如果没有参数的话,就不用压入栈了;局部变量也是如此。不过,根据我的观察,有时候在最外层的函数中,并不会保存ERP寄存器。这可能会视具体的编译器和优化选项而定。
函数调用之后,通常是要返回的,那么,我们就来看看返回过程中,软件调用栈与RSB的变化情况。
NO.4
函数返回过程中软件调用栈和RSB的变化
函数返回时,其顺序与调用顺序正好相反,也就是最后调用的那个函数首先返回。就本例来说,F2会首先返回。那么,在返回过程中,它会做些什么呢?
首先,让指向栈顶的ESP寄存器的值等于ERP寄存器的值,这时,它们都指向F调用栈中保存EBP原值的内存地址,然后,弹出栈顶元素,保存至ERP寄存器。这时,ERP寄存器指向F1调用栈中保存ERP原值的内存位置,而EIP寄存器正好指向保存函数F2的返回地址的内存位置。
当执行ret指令时,在没有RSB的情况下,会弹出栈顶元素(就是返回地址),并将其送至EIP寄存器,这样就完成了F2函数返回的动作。我们知道,这里说的是软件栈,从软件栈将返回地址载入处理器是很费时间的,为了提高处理器的运算速度,后来引入了硬件实现的RSB,所以,遇到ret指令时,直接弹出RSB栈顶的元素(实际上,就是猜的返回地址),并把它送入EIP寄存器,先执行从这个猜测地址开始的代码。同时,还会从软件调用栈中,也就是从内存中读取返回地址,等将其载入处理器时,可能已经经过了几百甚至更多个时钟周期了。好了,现在,处理器会比较这两个返回地址,如果一致,就采纳提前执行的结果,并继续往下执行;如果不一致,则撤销提前执行的运算结果,并返回到从软件调用栈取回的内存地址处,重新开始运行。
之后,继续从F1返回,过程与上面所说类似。
图2 软件调用栈与RSB在函数返回过程中的变化
大部分情况下,由于软件调用栈和RSB遇到call指令就同步压入返回地址,遇到ret指令就同步弹出返回地址,所以,RSB的准确率还是非常高的。但是,某些情况下,比如,由于RSB通常只能存放16个或更少的返回地址,所以,如果嵌套调用16个以上的函数,两者就会发生不匹配的情况。或者,如果攻击者直接修改软件调用栈的话,两者还是会发生不匹配的情况。
一旦软件调用栈和RSB给出的返回地址不一致,那么,根据RSB提前执行的指令的结果就需要撤销,这就是我们前面文章所说的瞬态执行。而在瞬态执行的情况下,有时候是能够绕过许多安全限制的,比如越界读取等。
那么,如何才能修改软件调用栈呢?
NO.5
如何修改软件调用栈
下面,我们先来看一个示例代码:
示例代码清单1:
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
int a=0;
void f2() {}
void f1()
{
f2();
a=a+1;
}
int main()
{
f1();
a=a+2;
printf("a = %d",a);
}
很明显,上面的代码的输出结果为3。那么,如何才能在函数f2中不对变量a进行操作,而使得输出结果为2呢?为此,可以修改软件调用栈,使得函数f2返回时,直接回到f1的返回地址,这样,就能满足上述要求了。
为此,我们先来看看f2的汇编代码:
图3 函数f2的反汇编结果
我们看到,这里没有对EBP寄存器进行保存,所以,它现在还是指向函数f1调用栈中保存EBP寄存器值的内存。这时,软件调用栈的布局大致如下所示:
图4 调用函数f2后,堆栈布局示意图
为了跳过f1中其余的代码,我们需要从f2返回时,直接跳转到main函数中,也就是跳转到f1的返回地址。为此,我可以将EBP当前的值赋给ESP寄存器,相当于跳过f2的返回地址,然后,弹出栈顶元素,送入EBP寄存器,这是该寄存器的值指向main调用栈中保存EBP原值的内存,而ESP寄存器指向f1的返回地址,所以,f2函数返回时,使用的返回地址实际上是f1的返回地址。为了完成上面所说的操作,只需在f1函数中添加如下所示两行汇编代码即可:
示例代码清单2:
void f2()
{
asm volatile(
"mov %rbp, %rsp \n"
"pop %rbp \n"
);
}
图5 修改前后的程序输出
如图5所示,调用f2后,直接返回到了main函数中,而非f1函数中!
NO.6
SpectreRSB漏洞利用代码PoC
下面给出一个利用SpectreRSB漏洞的PoC示意代码。首先,通过篡改软件调用栈,使得其中的返回地址与RSB中的返回地址不符。这时,由于从RSB中取返回地址非常快,所以,程序会先根据RSB给出的返回地址(该地址处存放的正好是攻击者设计好的瞬态指令)推测性地执行,这样,程序就可以不紧不慢地继续从软件调用栈中取返回地址了。由于推测执行能够绕过某些安全限制,所以,瞬态指令能够越界读取一个字节的内存,这时这个内存地址中的内容将会读入缓存,即使瞬态执行结果被撤销,它仍会留在缓存中。大概几百个,或者更多个时钟周期过后,软件调用栈中的返回地址已经取回,发现RSB给出的返回地址是错误的,所以,立即撤销推测执行的结果,并重新从正确的返回地址(该地址处存放的正好是实现缓存侧信道的指令)处开始执行。这样,就能够越界读取内存信息了。
下面,是一个简单的示例代码。
图6 SpectreRSB漏洞PoC示意代码
为了帮助读者理解,我们来过一遍代码。上述代码执行时,系统首先会调用main函数。这时,会压入main函数的参数和它的返回地址,即0x00000080。注意,这个返回地址将同时压入软件调用栈和硬件实现的RSB,具体如图所示:
图7 调用main函数,在软件调用栈和RSB中压入其返回地址
进入main函数后,需要保存EBP寄存器的值,并在栈中为局部变量分配一段内存空间。
图8 进入main函数后,在软件调用栈中保存EBP的值,并为局部变量分配内存空间
完成上述工作后,开始调用执行瞬态指令的speculative函数。在跳转到这个函数的代码之前,需要将其参数和返回地址压入软件调用栈中,同时,也会将其返回地址压入RSB中,具体如图所示:
图9 调用speculative函数时,在软件调用栈中压入其参数和返回地址,同时将返回地址压入RSB中
进入speculative函数后,保存EBP寄存器的值,并在栈中为局部变量分配一段内存空间,具体如下图所示:
图10 进入speculative函数后,在软件调用栈中保存EBP寄存器的值,并为局部变量分配内存空间
然后,开始调用破坏软件调用栈的pollute函数。为此,需要先将其参数和返回地址压入软件调用栈,同时,还会将返回地址压入RSB中,具体如图所示:
图11 调用pollute函数时,先在软件调用栈中压入其参数和返回地址,同时将其返回地址压入RSB中
进入后,首先保存EBP寄存器的值,这时,软件调用栈和RSB的内容如下所示:
图12 进入pollute函数后,在软件调用栈中保存EBP寄存器的值
保存EBP寄存器的值之后,让该寄存器保存ESP寄存器的值,也就是说,现在这两个寄存器都指向栈顶:
图13 在pollute函数中,让寄存器EBP和ESP都指向栈顶
然后,执行一条pop指令,也就是从栈顶弹出一个元素,或者说,让栈顶指针往后退一步:
图14 在pollute函数中,从软件调用栈顶弹出一个元素
继续执行后面的4条pop指令,从栈顶弹出4个元素(其中包括pollute函数的返回地址)。这时,EBP寄存器指向main调用栈中保存EBP原值的元素,而ESP寄存器指向speculative函数的返回地址:
图15 在pollute函数中,连续从软件调用栈顶弹出元素,直到露出speculative函数的返回地址为止
这时,利用clflush指令将栈顶的元素,也就是ESP寄存器所指向的内存,也就是speculative函数的返回地址从缓存中逐出,这样的话,只能从内存读取读取该地址。为什么要这么做?因为这么做的话,会更加耗时,从而为瞬态执行争取更多的时间。
如您所见,执行返回指令时,软件调用栈顶部的返回地址,已经与RSB顶部的返回地址不一致了。
图16 在pollute函数返回时,软件调用栈顶部的返回地址已经与RSB顶部的返回地址不一致了
当pollute函数返回时,由于RSB的动作较快,所以,处理器会先跳转到0x00000022处,推测执行瞬态指令:读取一字节的机密数据值,并将其作为数组的下标,访问相应的数组元素。
图17 利用RSB返回的预测地址,瞬态执行读取机密数据的指令,并将读取的数据编码为数组的下标
等到处理器取到内存调用栈顶的返回地址时,发现预测的返回地址是错误的,所以,撤销之前的执行结果,重新从0x00000032处开始执行。我们从图中可以看出,这里的代码是在测量数组元素的读取时间。也就是说,这里的代码是根据缓存计时侧信道恢复出瞬态指令读取的机密数据。
NO.7 缓解措施
对瞬态执行攻击的防御方法,主要围绕以下四个方面进行:
- 限制瞬态指令的执行,或减小瞬态执行的时间窗口;
- 限制瞬态指令越权访问数据;
- 使微架构状态不受瞬态执行的影响,从而令隐蔽信道的发送端无效(无法编码);
- 降低隐蔽信道的精度,相当于降低隐蔽信道接收端的能力(无法解码)。
其中,前面两条用于防止触发瞬态执行,后面两条用于阻止侧信道攻击。
NO.8 小结
在本文中,我们为读者详细介绍了基于返回堆栈缓冲区(RSB)推测机制的瞬态执行漏洞的相关概念和原理,并深入分析相关的示例代码,希望对大家理解这个漏洞的原理和防御有所帮助。
RECRUITMENT
招聘启事
安恒雷神众测SRC运营(实习生) 【任职要求】
————————
【职责描述】
1. 负责SRC的微博、微信公众号等线上新媒体的运营工作,保持用户活跃度,提高站点访问量;
2. 负责白帽子提交漏洞的漏洞审核、Rank评级、漏洞修复处理等相关沟通工作,促进审核人员与白帽子之间友好协作沟通;
3. 参与策划、组织和落实针对白帽子的线下活动,如沙龙、发布会、技术交流论坛等;
4. 积极参与雷神众测的品牌推广工作,协助技术人员输出优质的技术文章;
5. 积极参与公司媒体、行业内相关媒体及其他市场资源的工作沟通工作。
1. 责任心强,性格活泼,具备良好的人际交往能力;
2. 对网络安全感兴趣,对行业有基本了解;
3. 良好的文案写作能力和活动组织协调能力。
简历投递至
设计师(实习生)
————————
【职位描述】
负责设计公司日常宣传图片、软文等与设计相关工作,负责产品品牌设计。
【职位要求】
1、从事平面设计相关工作1年以上,熟悉印刷工艺;具有敏锐的观察力及审美能力,及优异的创意设计能力;有 VI 设计、广告设计、画册设计等专长;
2、有良好的美术功底,审美能力和创意,色彩感强;
3、精通photoshop/illustrator/coreldrew/等设计制作软件;
4、有品牌传播、产品设计或新媒体视觉工作经历;
【关于岗位的其他信息】
企业名称:杭州安恒信息技术股份有限公司
办公地点:杭州市滨江区安恒大厦19楼
学历要求:本科及以上
工作年限:1年及以上,条件优秀者可放宽
简历投递至
安全招聘
————————
公司:安恒信息
岗位:Web安全 安全研究员
部门:战略支援部
薪资:13-30K
工作年限:1年+
工作地点:杭州(总部)、广州、成都、上海、北京
工作环境:一座大厦,健身场所,医师,帅哥,美女,高级食堂…
【岗位职责】
1.定期面向部门、全公司技术分享;
2.前沿攻防技术研究、跟踪国内外安全领域的安全动态、漏洞披露并落地沉淀;
3.负责完成部门渗透测试、红蓝对抗业务;
4.负责自动化平台建设
5.负责针对常见WAF产品规则进行测试并落地bypass方案
【岗位要求】
1.至少1年安全领域工作经验;
2.熟悉HTTP协议相关技术
3.拥有大型产品、CMS、厂商漏洞挖掘案例;
4.熟练掌握php、java、asp.net代码审计基础(一种或多种)
5.精通Web Fuzz模糊测试漏洞挖掘技术
6.精通OWASP TOP 10安全漏洞原理并熟悉漏洞利用方法
7.有过独立分析漏洞的经验,熟悉各种Web调试技巧
8.熟悉常见编程语言中的至少一种(Asp.net、Python、php、java)
【加分项】
1.具备良好的英语文档阅读能力;
2.曾参加过技术沙龙担任嘉宾进行技术分享;
3.具有CISSP、CISA、CSSLP、ISO27001、ITIL、PMP、COBIT、Security+、CISP、OSCP等安全相关资质者;
4.具有大型SRC漏洞提交经验、获得年度表彰、大型CTF夺得名次者;
5.开发过安全相关的开源项目;
6.具备良好的人际沟通、协调能力、分析和解决问题的能力者优先;
7.个人技术博客;
8.在优质社区投稿过文章;
岗位:安全红队武器自动化工程师
薪资:13-30K
工作年限:2年+
工作地点:杭州(总部)
【岗位职责】
1.负责红蓝对抗中的武器化落地与研究;
2.平台化建设;
3.安全研究落地。
【岗位要求】
1.熟练使用Python、java、c/c++等至少一门语言作为主要开发语言;
2.熟练使用Django、flask 等常用web开发框架、以及熟练使用mysql、mongoDB、redis等数据存储方案;
3:熟悉域安全以及内网横向渗透、常见web等漏洞原理;
4.对安全技术有浓厚的兴趣及热情,有主观研究和学习的动力;
5.具备正向价值观、良好的团队协作能力和较强的问题解决能力,善于沟通、乐于分享。
【加分项】
1.有高并发tcp服务、分布式等相关经验者优先;
2.在github上有开源安全产品优先;
3:有过安全开发经验、独自分析过相关开源安全工具、以及参与开发过相关后渗透框架等优先;
4.在freebuf、安全客、先知等安全平台分享过相关技术文章优先;
5.具备良好的英语文档阅读能力。
简历投递至
岗位:红队武器化Golang开发工程师
薪资:13-30K
工作年限:2年+
工作地点:杭州(总部)
【岗位职责】
1.负责红蓝对抗中的武器化落地与研究;
2.平台化建设;
3.安全研究落地。
【岗位要求】
1.掌握C/C++/Java/Go/Python/JavaScript等至少一门语言作为主要开发语言;
2.熟练使用Gin、Beego、Echo等常用web开发框架、熟悉MySQL、Redis、MongoDB等主流数据库结构的设计,有独立部署调优经验;
3.了解docker,能进行简单的项目部署;
3.熟悉常见web漏洞原理,并能写出对应的利用工具;
4.熟悉TCP/IP协议的基本运作原理;
5.对安全技术与开发技术有浓厚的兴趣及热情,有主观研究和学习的动力,具备正向价值观、良好的团队协作能力和较强的问题解决能力,善于沟通、乐于分享。
【加分项】
1.有高并发tcp服务、分布式、消息队列等相关经验者优先;
2.在github上有开源安全产品优先;
3:有过安全开发经验、独自分析过相关开源安全工具、以及参与开发过相关后渗透框架等优先;
4.在freebuf、安全客、先知等安全平台分享过相关技术文章优先;
5.具备良好的英语文档阅读能力。
简历投递至
END
长按识别二维码关注我们