Solaris关键缓冲区溢出漏洞导致远程接管CVE-2020-14871

Solaris关键缓冲区溢出漏洞导致远程接管CVE-2020-14871

FireEye Mandiant一直在调查客户环境中受损的Oracle Solaris计算机。
在调查过程中,我们发现了客户系统上的漏洞利用工具,并对其进行了分析,以查看其如何攻击其Solaris环境。

FLARE团队的攻击队分析了此漏洞以确定其工作方式,在不同版本的Solaris上复现了漏洞,然后将其报告给Oracle。

在此博客文章中,我们介绍了该漏洞,提供了一种测试系统是否可能易受攻击的快速方法,并提出了缓解措施和解决方法。来自FLARE团队的Mandiant专家将在2020年11月12日的网络研讨会期间提供有关此漏洞以及UNC1945如何使用此漏洞的更多信息。

漏洞发现

该安全漏洞发生在可插入身份验证模块(PAM)库中。PAM使Solaris应用程序能够对用户进行身份验证,同时允许系统管理员在一个由所有应用程序一致实施的位置中配置身份验证参数(例如,密码复杂性和有效期)。

实际漏洞是位于PAM parse_user_name函数中的经典的基于堆栈的缓冲区溢出。
此功能的缩写形式如下所示。

static int
parse_user_name(char *user_input, char **ret_username)
{
            register char *ptr;
            register int index = 0;
            char username[PAM_MAX_RESP_SIZE];
       /* ... */
            ptr = user_input;
       /* ... */
             /*
             * username will be the first string we get from user_input
             * - we skip leading whitespaces and ignore trailing whitespaces
             */
            while (*ptr != '
static int
parse_user_name(char *user_input, char **ret_username)
{
            register char *ptr;
            register int index = 0;
            char username[PAM_MAX_RESP_SIZE];
       /* ... */
            ptr = user_input;
       /* ... */
             /*
             * username will be the first string we get from user_input
             * - we skip leading whitespaces and ignore trailing whitespaces
             */
            while (*ptr != '\0') {
                  if ((*ptr == ' ') || (*ptr == '\t'))
                               break;
                  else {
                               username[index] = *ptr;
                               index++;
                               ptr++;
                  }
            }
             /* ret_username will be freed in pam_get_user(). */
            if ((*ret_username = malloc(index + 1)) == NULL)
                  return (PAM_BUF_ERR);
            (void) strcpy(*ret_username, username);
            return (PAM_SUCCESS);
}
') {                   if ((*ptr == ' ') || (*ptr == '\t'))                                break;                   else {                                username[index] = *ptr;                                index++;                                ptr++;                   }             }              /* ret_username will be freed in pam_get_user(). */             if ((*ret_username = malloc(index + 1)) == NULL)                   return (PAM_BUF_ERR);             (void) strcpy(*ret_username, username);             return (PAM_SUCCESS); }

parse_user_name函数具有基于堆栈的缓冲区溢出漏洞

只要将长度超过PAM_MAX_RESP_SIZE(512字节)的用户名传递给parse_user_name,就会出现此漏洞。该漏洞可能已经存在数十年了,一个可能的原因是,只有在应用程序尚未将用户名传递给PAM之前将其限制为较小的长度时,该漏洞才可被利用。面对网络的软件并不总是限制用户名长度的一种情况出现在SSH服务器中,这是我们发现的工具使用的利用媒介。

SSH键盘交互式身份验证是一种“直通”身份验证机制,其中SSH协议在服务器的PAM库和客户端之间中继提示和响应。它旨在支持自定义形式的身份验证,例如两因素身份验证,而无需修改SSH协议。通过操纵SSH客户端设置以强制键盘交互式身份验证提示输入用户名,而不是通过常规方式发送用户名,攻击者还可以将无限制的输入传递给PAM parse_user_name函数。

漏洞利用概念证明

为了快速测试不同版本的Solaris是否可能受到攻击,我们开发了一种概念证明漏洞利用程序来触发溢出并使SSH服务器崩溃。标准的OpenSSH客户端提供了触发漏洞所需的所有选项(图1)。

(图1)可以对服务器进行快速测试,以查看它是否容易受到SSH的攻击

服务器易受攻击的指示是SSH客户端显示“身份验证失败;” 如果没有脆弱的PAM库,则SSH服务器如果收到的用户名太长,将反复提示输入用户名。PAM库中的溢出也会导致SSH服务器崩溃,如图2所示。如果SSH服务器在未连接调试器的情况下崩溃,则操作系统会将崩溃转储写入/core。实际上,如果Solaris机器上存在/core文件,并且file命令报告该文件来自sshd,则表明这些漏洞与已利用此漏洞一致。

(图2)SSH服务器在parse_user_name函数中崩溃

存在漏洞的操作系统

  • Solaris 9(某些发行版)
  • Solaris 10(所有发行版)
  • Solaris 11.0
    • 尽管parse_user_name函数在未修补的Solaris 11.1和更高版本中仍然容易受到攻击,但对PAM库的无关更改会在易受攻击的函数收到用户名之前截断该用户名,从而使该问题无法通过SSH加以利用。如果parse_user_name函数在另一个上下文中可以访问,则该漏洞可能变得可利用。
  • Illumos(OpenIndiana 2020.04)

缓解措施和解决方法

2020年10月的重要补丁更新中描述了Oracle针对Solaris 10和11的补丁

由于不再支持Solaris 9,因此Oracle尚未发布补丁程序。

对于Solaris 9以及不方便打补丁的Solaris 10或11系统,建议编辑 /etc/ssh/sshd_config 文件,以添加ChallengeResponseAuthentication no和KbdInteractiveAuthentication no行,然后重新启动SSH服务器。尽管这消除了使用SSH键盘交互式身份验证来利用此漏洞的机会,但是可能还有其他方法可以攻击parse_user_name函数,我们建议仅将此解决方案用作权宜之计,直到可以升级Solaris 9系统或可以修补October补丁为止。访问和安装受支持的Solaris版本。

致谢

Rapid7的Jeffrey Martin为测试此漏洞做出了贡献。

from

Leave a Reply

您的电子邮箱地址不会被公开。 必填项已用*标注