OpenSSH 6.9 p1认证绕过

OpenSSH 6.9p1以及6.9p1以下的版本存在身份认证绕过和用后释放漏洞。

受影响产品:OpenSSH (http://www.openssh.com)

受影响版本:6.9p1以及6.9p1以下版本

漏洞:存在于PAM特权分离代码中

漏洞影响

研究人员在PAM特权分离代码中找到了两个漏洞。其中一个漏洞允许一名拥有普通权限的远程攻击者成功执行身份验证,然后攻击者就可以伪装成其他的用户。唯一额外的先决条件就是攻击者必须得到一个有效的用户账号,并且这个账号可以通过SSH来登录系统。

背景

OpenSSH 是 SSH (Secure SHell) 协议的免费开源实现。SSH协议族可以用来进行远程控制, 或在计算机之间传送文件。而实现此功能的传统方式,如telnet(终端仿真协议)、 rcp ftp、 rlogin、rsh都被认为是极其不安全的,并且它们还会使用明文来传送密码。OpenSSH提供了服务端后台程序和客户端工具,用来加密远程控件和文 件传输过程中的数据,并由此来代替原来的类似服务。

所谓特权分离(Privilege Separation),实际上是OpenSSH的一种安全机制,类似于chroot能够提供的安全性。这个特性是默认开启的,配置文件中的 UsePrivilegeSeparation 指令可以开启或关闭这个特性。使用此特性的关键之处在于设置一个空目录,并将此目录的权限设置为”000″,宿主设置为”root”。然后还需要设置一个 用于特权分离的非特权用户,比如sshd,并将此用户的家目录设置为这个空目录。然后在运行配置脚本的时候,用户可以根据自己的需要来指定目录和用户。

OpenSSH 在5.9版本中引入了特权分离机制。权限分离会将一个普通进程分解为两部分:一个没有特权的子进程和一个有特权的监视进程。没有特权的子进程会完成大部分 的工作,并处理所有的网络数据。监视进程会与这个子进程进行通信,并执行所有需要特殊权限的操作。这种机制的设计理念就是为了防止程序在非特权状态下的运 行出现错误,进而防止整个系统受到攻击。我们在这里给大家提供了一个非常优秀的技术介绍,即“Preventing Privilege Escalation”。

子进程与监视进程通过socketpair进行通信。协议还定义了一些不同的监视请求以及应答类型可供这两个进程在交换信息时使用。完整的参数列表可以在monitor.c文件中找到。

监视请求有其指定的标识符,用来控制监视进程何时以及怎样发送请求。比如说,MON_ONCE标识规定请求只能发送一次,并且在其被监视进程接收到之后,就 会立刻被禁用掉。MON_AUTH标识规定这个请求是与身份认证进程有关的。完整的标识符列表也可以在monitor.c文件中找到。

特权分离机制中的PAM身份认证绕过

当用户启用了OpenSSH的PAM支持之后,一些额外的监视请求也就随之启动了,具体信息可以在monitor.c文件中得到:

在协议发送任何与PAM有关的监视请求之前,没有特殊权限的子进程会发送MONITOR_REQ_PWNAM请求,并验证用户通过网络提交的用户名是否有 效。如果用户存在,并且监视进程会在当前的身份验证内容中对用户名和密码的结构体数据(struct Authctxt *authctxt)进行缓存处理,然后将相应数据返回给子进程。

然后,子进程会发送MONITOR_REQ_PAM_START请求来启用PAM身份验证,这个请求会让监视进程为当前用户建立一个新的身份验证对话,并通过调用PAM的API函数pam_start()来对用户的身份进行验证。

接下来,子进程会发送PAM相关的监视请求,即MONITOR_REQ_PAM_INIT_CTX,这个请求会初始化监视进程中当前的PAM身份验证信息。

有趣的是,子进程会将当前用户的用户名与这个请求再次发送给监视进程,然后监视进程会根据它所接收到的用户名来重写之前存储在身份验证进程中的用户名。

在PAM身份验证的过程中,同样的用户名会发送两次,但这并不能说明什么问题。然而,攻击者如果能够控制这个没有特殊权限的子进程,并让这个进程发送不同的用户名,这就会导致监视进程在匹配用户数据的时候发生错误。

PAM特权分离机制中的用后释放漏洞

监视进程会发送PAM身份验证请求,而这个请求是由没有特殊权限的子进程发送的,这样便会暴露出额外的攻击面,但是,我们不仅需要考虑处理程序中的漏洞,我们还需要了解到底是哪种请求会导致程序出现错误,并引发出这些有趣的漏洞。

研究人员在处理MONITOR_REQ_PAM_FREE_CTX请求的程序中发现了其中的一个漏洞:

在上述代码中,可以free_ctx函数。然后sshpam_free_ctx()函数可以在auth-pam.c中查看到:

但是,对于一个受攻击者控制的子进程来说,它仍然有可能发送MONITOR_REQ_PAM_FREE_CTX请求,这将会释放存储在PAM中的内容,然后进程就会调用其他的PAM监视请求,这样变会引起一次UAF。

被释放的结构体定义在auth-pam.c文件中,结构体数据如下:

正如上面所描述的情况,这个结构体并不包含任何形式的指针变量,而那些指针可能成为利用这个用后释放漏洞的理想条件。但是,这个结构体却存储了另外两个有趣 的值,这两个值分别为pam_psock和pam_csock。这两个文件可以对进程与PAM身份验证系统之间的通信socket数据进行验证。

为了利用这个用后释放漏洞,你可以尝试将监控进程释放的内存数据用一个伪造的结构体替换掉,但这个伪造的结构体也必须包含pam_psock和pam_csock。

漏洞缓解

这两个漏洞在OpenSSH 7.0中得到了修复,用户可以安装OpenSSH 7.0来解决这一问题。

漏洞披露时间轴

  • 2015-08-10 研究人员将漏洞信息报告给了openssh@openssh.com
  • 2015-08-11 OpenSSH 7.0发布,并在这一版本中修复了这两个漏洞。

致谢

感谢Blue Frost安全公司的Moritz Jodeit发现了这两个漏洞。

[via@360安全播报]