作者
恒安嘉新水滴攻防安全实验室
一、背景
年01月26日,sudo发布安全通告,修复了一个类Unix操作系统中sudo命令基于堆的缓冲区溢出漏洞(CVE--,该漏洞被命名为“BaronSamedit”),该漏洞可导致本地权限提升,从而允许任何本地用户获得root权限,无需进行身份验证,且攻击者不需要知道用户密码,sudo是一个功能强大的工具,其允许普通用户执行root权限命令,大多数基于Unix和Linux的操作系统都包含sudo。
目前漏洞利用EXP已公开,本次基于公开细节进行漏洞的利用分析。
二、漏洞复现环境
ubuntu18.04
sudo1.8.21p2
三、源码分析
3.1代码下载
首先要下载源码,这里配置了apt的source源之后直接使用aptsourcesudo就可以获取一份源码,需要注意的是,现阶段获取的源码都是打过patch的,想要没打过patch的源码需要自己手动解压一下
sudo_1.8.21p2.orig.tar.gz
3.2漏洞点分析
漏洞点产生在./plugins/sudoers/sudoers.c:处
for(size=0,av=NewArgv+1;*av;av++)size+=strlen(*av)+1;if(size==0
(user_args=malloc(size))==NULL){sudo_warnx(U_("%s:%s"),__func__,U_("unabletoallocatememory"));debug_return_int(-1);}if(ISSET(sudo_mode,MODE_SHELL
MODE_LOGIN_SHELL)){for(to=user_args,av=NewArgv+1;(from=*av);av++){while(*from){if(from[0]==\\!isspace((unsignedchar)from[1]))from++;*to++=*from++;}*to++=;}*--to=\0;}
这里的NewArgv里存放的是sudo命令的参数,
首先遍历参数,确定size进行malloc
但是注意下方
if(from[0]==\\!isspace((unsignedchar)from[1]))from++;*to++=*from++;
如果from==\,并且下一个byte不是空格的话,就会from++,指向下一个字符
:if(sudo_mode(MODE_RUN
MODE_EDIT
MODE_CHECK)):if(ISSET(sudo_mode,MODE_SHELL
MODE_LOGIN_SHELL))
其中触发条件是MODE_SHELL或者MODE_LOGIN_SHELL,并且此时设置了MODE_RUN,MODE_EDIT,MODE_CHECK的其中一个
如果可以使构造出参数最后是一个\的话,就可以使其指向下一个字符,也就是\x00,将其存下来之后又*from++跳了过去,现在from指向了下一个参数,就可以导致溢出出现,这也就是最初的POC中的后半部分
\`perl-eprint"A"x`
使用\跳过\x00,然后进行溢出
但是只有这个点还不够,这里没有判断是因为正常情况下到这一步时是经过转义的参数,也就是\后面应该还有其他字符,来看一下转义部分的代码
sudo-1.8.21p2/src/parse_args.c:
if(ISSET(mode,MODE_RUN)ISSET(flags,MODE_SHELL)){char**av,*cmnd=NULL;intac=1;if(argc!=0){/*shell-c"