漏洞分析:OpenSSH用户枚举漏洞(CVE-2018-15473)分析 – 互联网安全新媒体平台

先容

这个破绽虽然不能天生有效用户名列表,然则它可以容许进击者预测用户名。今朝这个OpenSSH用户罗列破绽(CVE-2018-15473)的具体信息已经上传至了GitHub,感兴趣的同砚可以自行查看【传送门】。

在这篇文章中,我们将对该破绽进行深入阐发,并供给一些可行的缓解规划。

技巧细节

这个破绽存在于OpenSSH所实现的一些认证功能之中,首先我们一路看一看Ubuntu OpenSSH的公共密钥认证破绽。

经由过程向一台OpenSSH办事器发送恶意的公共密钥认证消息,进击者将能够获取特定的用户名信息。假如用户不存在,办事器将会向客户端发送认证掉败的消息。假如用户存在,消息将无法解析并终止通信,即通信连接会在没有任何消息回传的环境下断开。关于该破绽的破绽使用代码可以从这个Python PoC脚本中获取:【传送门】。

这个破绽之以是存在,是由于办事器在对消息完备解析之前,用户查询了不存在的用户名。想要修复该破绽也很简单,按进击逻辑反着来就行了:首先对消息进行完备解析,然后再建立通信连接。

测试破绽使用PoC的一种措施便是在调试模式下开启OpenSSH办事器:

然后用已存在的有效用户名运行PoC脚本:

在办事器端将会查看履新错提示:

相关差错信息还可以在/var/log/auth.log中找到:

假如无法精确解析消息,会导致客户端跟办事器端之间的通信中断,而且中断时不会收到办事器发送的提示信息:

留意粉血色标记的着末一个数据包(客户端数据包),这里没有后续的蓝色数据包(办事器数据包)。

当PoC脚本以不存在的用户名运行之后:

不会弹出“imcomplete message”差错提示:

留意通信数据结尾处的蓝色办事器数据包。

这便是该破绽(公共密钥认证破绽)裸露有效用户名的全部流程了。

此中,userauth_pubkey函数是认证功能所实现的此中一个函数,专门用于根据公共密钥来完成身份验证。假如认证掉败,则返回“0”,成功则返回“1”。当办事器端接管到了SSH2_MSG_USERAUTH_REQUEST哀求后,便会调用该函数,之后的结果会用来给客户端回传SSH2_MSG_USERAUTH_FAILURE或SSH2_MSG_USERAUTH_SUCCESS消息。

该函数的运行逻辑为:

1.假如用户名不存在:返回“0”;

2.假如用户名存在但密钥差错:返回“0”;

3.假如用户名存在且密钥精确:返回“1”;

然则有人发明,我们竟然可以在第一步和第二步中心终止userauth_pubkey函数的运行。第一步履行完后,userauth_pubkey函数会从客户端获取消息字符串,假如获取掉败(恶意字符串导致),全部历程都邑终止,并在不发送任何回传消息的环境下关闭连接。

packet_get_string所导致的环境如下:

假如用户名存在,第一步会在法度榜样从消息域中提取完数据落后行。

第一个提取的数据域是一个布尔值(1字节),对应函数为packet_get_char()。假如认证类型为publickey,返回值便是“1”。后续随着的是两个字符串:算法和密钥。在SSH消息中,字符串会以一个“长度-值“键值对进行编码,一个字符串为4个字节。

函数packet_get_string可以从消息中提取字符串,并对其进行验证,这个函数还必要依附另一个函数:ssh_ssh_packet_get_string。

ssh_packet_get_string函数会调用sshpkt_get_string函数,假如返回的值不是“0”,它还会调用fatal函数。函数fatal会记录致命的差错事故,然后终止天生的OpenSSH进程(不回传任何差错信息)。

接下来会履行sshpkt_get_string函数并调用sshbuf_get_string函数:

然后sshbuf_get_string函数会调用sshbuf_get_string_direct:

然后sshbuf_get_string_direct会调用sshbuf_peek_string_direct:

着末,sshbuf_peek_string_direct会进行字符串验证:

假如消息中残剩数据小于4字节,或者说消息中的残剩数据小于字符串长度,则会返回SSH_ERR_MESSAGE_INCOMPLETE 差错消息。这便是我们之前那个Python PoC脚本所要触发的器械。首先,它会跟OpenSSH办事器建立一条加密的通信链接,然后向其发送恶意的SSH2_MSG_USERAUTH_REQUEST消息。经由过程重定义add_boolean函数,消息中的布尔值域会被轻忽。

当函数userauth_pubkey解析了恶意消息之后,首先会读取布尔值域,因为这个域着实是不存在的,是以读取的会是下一个域(函数packet_get_char):加密算法字符串的4字节长度值。然后调用下一个函数packet_get_string来读取加密算法字符串。

下面是解析合法消息的历程:

下面是解析恶意消息的历程:

结果便是,代码解析了一个1907字节的字符串(十六进制为0×00000773),这比全部消息的长度还要长,这会导致ssh_packet_get_string调用fatal函数,并中断OpenSSH进程。

破绽总结

这是一个异常隐蔽的破绽,它不是一个缓冲区溢出漏洞,也不是远程代码履行破绽,更不是差错输入验证破绽。这里不存在任何的缓冲区溢出问题,所有的输入都在应用之提高行了验证。问题便是,输入验证是在进行了一些函数处置惩罚之后完成的。

问题的办理措施也对照简单:替换函数的调用顺序即可,也便是首先辈行输入验证,然后再进行函数处置惩罚就可以了。

* 参考滥觞:nviso,FB小编Alpha_h4ck编译,转载请注明来自.COM

赞(0) 打赏
分享到: 更多 (0)
免责申明:本站所有资料均来自于网络,版权归原创者所有!本站不提供任何保证,不保证真实性,并不承担任何法律责任

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

阿里云优惠网 更专业 更优惠

阿里云优惠券阿里云大礼包