最新实操案例分享:分析Baron Samedit(Sudo CVE-2021-3156)漏洞
2021年1月26日,Qualys发表了一篇博客,描述了他们对sudo中的堆溢出漏洞CVE-2021-3156的发现,他们将其命名为“Baron Samedit”。
Sudo是许多不同的Linux/Unix发行版中的一个核心工具,它允许用户以提升的安全权限运行程序。它是Linux、BSD、macOS、AIX、Solaris和其他系统普遍包含和安装的组件。
用Insure++分析Baron Samedit(CVE-2021-3156)
我将利用这个漏洞演示Parasoft Insure++内存超读和覆盖检测。Insure++是一个内存调试工具,它使用专利的仪器技术来快速识别泄漏和其他内存问题。
与使用传统的调试工具和技术相比,Insure++使发现、理解和修复此类漏洞变得更加容易。
Baron Samedit(CVE-2021-3156)漏洞概述
当sudo(v1.8.2 - v1.9.5p1)的漏洞版本在shell模式下运行命令,且命令行参数以单反斜杠结束时,由于命令行参数的解压缩方式存在缺陷,导致user_args字符串的缓冲区溢出。
当取消最后一个“/”字符的逃逸时,函数将覆盖字符串的空结束符,导致缓冲区溢出。关于该漏洞的详细分析,请查看Qualys博客的原文。当我们分析Insure++的结果时,我会涉及类似的细节。
Insure++的设置
为了复制Insure++中的漏洞,我们需要下载一个漏洞版本的sudo,并使用Insure++进行编译。sudo v1.9.5p1的源码,也就是最新的漏洞版本,可以在sudo网站上找到。解压源码后,确保Insure++在你的PATH上,并在运行configure之前将你的CC设置为“insurance gcc”。
你应该考虑设置一个不同的前缀,以便在适用的情况下不覆盖系统的sudo。从这里开始,像往常一样运行make和make install。
运行开发程序
Qualys的文章提供了一个简单的概念验证命令,展示了缓冲区溢出漏洞。它的内容如下:
sudoedit -s '\' 'perl -e 'print "A" x 65536''
用你编译的路径替换sudoedit,然后运行命令。
我们可以从malloc消息中看出,概念证明的执行是正确的。
分析结果
我们来看看Insure++通过在Insra窗口中检查结果发现了什么。
我们可以看到第一个内存错误是发生在sudoers.c中971行的读溢出。Insra告诉我们,from指针在它指向的两个字节的内存块之外读取了一个字节。
注意内存块是两个字节,因为第一个是“/”字符,第二个是空结束符。堆栈跟踪显示,这发生在set_cmnd()函数中。
下一个内存错误是在第972行的sudoers.c中从一个坏地址读取。由于from指针已经出界,正如我们在第一个内存错误中看到的那样,任何使用from的索引访问都将是一个坏索引。
下一个内存错误是发生在第974行的读溢出。这里,我们从to指针导出界外指针,并将其写入到to指针指向的缓冲区。
请注意,Insure++在前面所有的内存错误中都在跟踪这些内存块的来源。Insure++知道我们正在读取的内存块在sudo.c中main()方法中最初定义为argv参数的边界之外。
下一个内存错误是与之前相同的语句中的写溢出。现在,Insure++在写到to指针指向的缓冲区时触发。请注意,to指针指向的缓冲区的大小是65539字节。我们在概念验证中提供的溢出命令串是一个“/”字符,一个空格,65536个“A”字符,以及一个隐式的空结束符,共65539个字节。
下一个内存错误发生在if检查“/”字符之外。为什么现在会造成写溢出?由于之前的内存错误已经破坏了to指针指向其内存块之外,所有后续对该指针的写操作都将导致写溢出。
这里我们看到了最后的内存损坏,程序null终止了字符串。这绝对是正确的行为!然而,写溢出的发生是因为to指针被损坏,并且已经指向了它应该是的内存块之外。
结语
我们可以看到,Parasoft Insure++让这个内存漏洞的分析变得更加容易。我们能够快速确定读和后续写溢出的位置,知道涉及到哪些变量,并了解无效指针如何影响后续的内存操作。如果结合良好的测试覆盖率和模糊,Insure++可以让很多复杂的内存漏洞变得更加简单,便于理解、诊断和修复。