CVE-2020-28243 SaltStack Minion本地特权提升漏洞分析

文章来源:嘶吼专业版

0x00 前言

近期,我在SaltStack的Salt中发现了一个命令注入漏洞,当master调用restartcheck时,该漏洞允许通过特制的进程名称对minion进行特权提升。

受影响的版本:自2016.3.0rc2到3002.5之间的所有版本

CVSS评分:7.0 高危

官方公告:

https://saltproject.io/security_announcements/active-saltstack-cve-release-2021-feb-25/

PoC:

https://github.com/stealthcopter/CVE-2020-28243

在这篇文章中,我将重点介绍以下几部分内容:

1、发现:我是如何发现这个漏洞的?

2、漏洞详情:为什么这个漏洞有效?

3、利用方式:应该如何利用这个漏洞?

4、安全问题:包括容器逃逸、未经身份验证的远程代码执行

5、时间节点:这一过程花了多长时间?

0x01 关于SaltStack Salt

SaltStack Salt是一个流行工具,用于自动化和保护基础结构,其使用过程分为两个角色。其中,一个系统设置为master,负责控制连接到该系统的其他系统。其中的一个或多个系统被设置为minion,与master连接并响应其发出的任意命令。

master和minion通常都是以root身份在其安装的系统上运行。

0x02 漏洞发现

在查看SaltStack的源代码并寻找安全漏洞的过程中,我选择使用Bandit(一个针对Python应用程序的安全扫描程序)运行源代码,并查看其发现的问题。

我以为会看到很少的漏洞,因为SaltStack的代码库较大,并且已经维护了几年的时间。但是,从下面的截图中可以看到,Bandit展示的问题数量比我预期的还要多,其中包括117个高危问题。

Bandit针对SaltStack Salt的检测报告:

当然,其中的很多问题都是误报,或者对我们来说意义不大,并且可能需要花费大量时间来逐一进行分析。为了快速找到关键漏洞,我决定将精力聚焦在几个子进程实例可能产生的命令注入漏洞。我将Popen与代码库中的shell=True结合使用。

在分析其中的一些漏洞的过程中,我尝试了多种方法,起初都无法控制这些漏洞。但后来,我发现可以利用进程名称,以一种非常巧妙的欺骗手段来控制它们。

这也就是我们正在寻找的漏洞。

0x03 漏洞详情

minion在重新启动检查的过程中存在命令注入漏洞。当某个进程打开的文件描述符以(deleted)为结尾时(需要加上前面的空格),攻击者可以通过精心设计进程名称的方式实现命令注入。这样一来,就允许任意用户在minion任何未明确禁止的目录中创建文件,实现到root的本地特权提升。

3.1 漏洞代码

存在漏洞的代码位于restartcheck.py的第615行,其中使用shell=True和被攻击者操纵的命令来调用subprocess.Popen。

cmd = cmd_pkg_query + package

paths = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)

根据操作系统的不同,软件包是由进程名称组成的,cmd_pkg_query可能如下:

Debian:dpkg-query --listfiles

RedHat:repoquery -l

NILinuxRT:opkg files

如果我们能够插入bash控制字符到进程名称中(例如; | &&等),就可以在代码到达上述一行时触发注入。

但是,要到达这一行代码,进程首先需要打开文件处理程序,打开以(deleted)为结尾的文件,并且该文件必须位于未明确禁止的目录中。

被禁止的目录列表请参考这里。这个列表可能会排除掉一些我们可能会尝试的位置,例如/tmp和/dev/shm。但是,特权较低的用户可能会访问一些常用的位置,例如:

/var/crash

/var/spool/samba

/var/www

3.2 进程名称

在我们的研究过程中,事实证明,要可靠地修改进程名称是一件比较难的事情。并且,ps列出的进程名称可能会与Python psutil库返回的名称不同。

在Linux中,进程名称可以包含任何字符(除null外)。任何用户都可以在系统上启动进程,并且进程本身可以设置进程的名称。因此,它们就成为了命令注入漏洞的良好目标,因为开发人员不太可能会想到进程名称包含特殊字符或注入的场景。

我们可以使用exec -a直接设置进程名称。但是,这种方式在busybox或sh shell中是不起作用的,并且在使用psutil时似乎没有显示出相同的名称。当然,我们也可以通过直接操作procfs来修改进程名称,但是这种方法也会导致结果不一致。

因此,我们最后找到的最简单、最准确的方法是重命名正在运行的二进制文件或脚本。由于Linux的文件名中不能包含/字符,所以就限制了我们可以注入的命令。不过,使用Base64编码可以忽略此限制,如下所示:

# 如果我们想将shadow文件复制到/tmp,我们可以运行

 cp /etc/shadow /tmp/shadow

# 将其转换为Base64字符串

echo cp /etc/shadow /tmp/shadow | base64 -w0

# 转换结果

Y3AgL2V0Yy9zaGFkb3cgL3RtcC9zaGFkb3cK

# 我们需要运行的新命令

echo Y3AgL2V0Yy9zaGFkb3cgL3RtcC9zaGFkb3cK|base64 -d|sh -i

0x04 漏洞利用

PoC脚本exploit.sh的用法:

为了成功利用这个漏洞,需要使用一个未被SaltStack明确禁止的可写目录。在不带参数运行PoC脚本后,将会搜索符合该限制的目录。

示例脚本输出了潜在可写入的目录:

随后,使用-w标志加上选定的可写目录,使用-c标志加上命令,将会创建一个进程,在该进程的名称中包含命令注入和一个打开的文件处理程序,当master进入该文件处理程序时,漏洞将被处罚,并调用restartcheck。

我们逐步执行漏洞利用过程以展示这一漏洞。为了尝试,我们可以以root用户身份创建一个简单的文件。首先,带上特定标志运行脚本。

运行漏洞脚本,其中标记了进程名称和文件处理程序:

既然已经确定恶意进程正在运行,并且名称中已经注入了命令,同时也打开了文件处理程序,那么我们就可以在SaltStack的master发出restartcheck.restartcheck命令。完成此操作后,可以检查根目录中是否存在被黑的文件。

上图证明漏洞利用已经成功,我们可以以root用户身份执行代码。

不错,接下来我们可以做一些更酷的事情。如何获得一个root Shell呢?在下面的视频中,我们通过复制find二进制文件,并将其设置为suid,最终成功获得了root身份的Shell。

视频:https://asciinema.org/a/382327

对于其他场景中,下图从master视角展现了漏洞利用的过程。

来自master POV的命令注入,其中标出了注入的对应行:

0x05 其他安全问题

上面讨论了在本地利用漏洞实现到root用户特权提升的场景。但是,在此过程中我们还应该考虑一些其他安全问题。

5.1 容器逃逸

我们在主机上已经列出了容器化的进程,因此可以从容器内部执行这一漏洞利用,从而在主机上以root用户身份实现命令执行。

上图展示进程在容器中启动,下图为主机上使用ps列出的容器进程:

5.2 非特权远程代码执行

尽管不太可能,但这样的漏洞还是有机会被不具备本地Shell访问权限的攻击者利用。原因在于,在某些情况下,远程用户可以影响进程的名称。

0x06 时间节点

SaltStack的响应速度非常快,我发现和披露该漏洞的完整时间节点如下。

2020年11月5日 发现漏洞

2020年11月5日 通知SaltStack

2020年11月5日 SaltStack开始调查

2020年11月6日 分配CVE ID

2020年11月7日 SaltStack确认漏洞

2020年11月18日 SaltStack通知计划在1月发布修复程序

2021年1月22日 宣布将于2月4日发布安全修复程序

2021年2月4日 安全修复程序发布日期延迟至2月25日

2021年2月25日 已发布安全修复程序(+91天)

0x07 总结

在开发和维护过程中,要保证代码的安全性已经是非常复杂的工作了。不难理解,开发人员很难想到恶意进程名称的这个维度。如果大家有任何问题或者反馈,欢迎在Twitter上与我联系。同时,这也是我的第一个CVE,还请大家温柔一些。

参考及来源:https://sec.stealthcopter.com/cve-2020-28243/

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容