OpenSSH用户枚举漏洞(CVE-2018-15473)分析

当履行一个不存在的用户名的PoC脚本时:

没有发生“incomplete message”的报错信息:

办事器也返回给客户端一条信息:

留意着末的蓝色(办事器)数据包

简介

OpenSSH用户罗列破绽(CVE-2018-15473)已经经由过程Github公开(https://github.com/openbsd/src/commit/779974d35b4859c07bc3cb8a12c74b43b0a7d1e0)只管该破绽不能用来天生有效的用户名列表,但依旧可以拿来罗列预测用户名

在本文中,我们将具体阐发该破绽的使用和警备技术

技巧细节

该破绽涉及到多个OpenSSH中的用户身份验证函数首先我们来钻研下Ubuntu下OpenSSH中的公钥认证中的这个破绽

经由过程向OpenSSH办事器发送一个差错款式的公钥认证哀求,可以判断是否存在特定的用户名假如用户名不存在,那么办事器会发给客户端一个验证掉败的消息假如用户名存在,那么将由于解析掉败,不返回任何信息,直接中断通讯相关的破绽使用PoC脚本链接如下:http://www.openwall.com/lists/oss-security/2018/08/16/1

这里涉及的破绽发生在解析哀求前就收到的用户名不存在的哀求修复破绽的要领也很简单:改动下判断逻辑,先解析信息,再建立通讯

用来测试该PoC的要领如下:先在调试模式下启动OpenSSH办事器,

然后运行带有已知用户名的脚本:

在办事器端可以看到报错信息:

这个报错信息也可以在/var/log/auth.log目录下找到:

解析哀求掉败会导致办事器在不返回任何信息的环境下中断客户端和办事器间的通讯:

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

这便是使用公钥身份认证中的破绽来判断用户名是否存在的历程

经由过程阐发OpenSSH源码中的userauth_pubkey函数,可以发明它对公钥身份认证的历程如下:收到SSH2_MSG-USERAUTH_REQUEST(公钥类型)发来的数据后,调用函数进行验证,验证掉败时返回0,验证成功时返回1然后将结果(SSH2_MSG_USERAUTH_FAILURE或SSH2_MSG_USERAUTH_SUCCESS)发还给客户端

函数的相关逻辑如下:

假如是未知用户名 -> 0

假如是差错密码的已知用户名 -> 0

假如是精确密码的用户名 -> 1

破绽提交者找到的是在第一步和第二步之间,能够设法竣事userauth_pubkey函数的履行,从而在第一步userauth_pubkey函数获取客户端发来的信息字符串时,构造特定款式的字符串,在不返回任何信息的环境下竣事并关闭这一通讯连接

这里的关键是packet_get_string函数:

假如存在该用户名,那么第一步后会从消息中提取有效字符串

第一部分packet_get_char()函数提取的字符串是一个布尔变量(1字节),之后是两个字符串:算法和对应的密钥在SSH信息中,字符串以长度–值的配对要领编码:一个字符串包孕4字节(字符串长度)的开首和包孕字符串内容的可变大年夜小的字节数(根据之前声明的长度)这里的长度采纳大年夜真个要领进行编码:先声明紧张的4字节最高有效字节,再添加次要的有效字节

packet_get_string函数在验证的同时,也认真提守信息中的字符串,从而用于验证信息的长度是否精确这个函数也依附其他函数:

首先是函数中的定义到的ssh_packet_get_string:

ssh_packet_get_string函数调用sshpkt_get_string函数,假如该函数返回的值不是0,那么调用fatal函数Fatal函数记录发生的报错信息,然后不返回任何信息,直接遣散天生的OpenSSH进程

现在再看下涉及的另一组函数:sshpkt_get_string调用了sshbuf_get_string:

[1] [2]下一页

sshbuf_get_string调用了sshbuf_get_string_direct:

sshbuf_get_string_direct调用sshbuf_peek_string_direct:

着末sshbuf_peek_string_direct对字符串进行验证:

假如剩下的数据长度小于4字节(也便是不能包孕字符串长度的声明)或者剩下的数据长度小于字符串的长度,那么会返回SSH_ERR_MESSAGE_INCOMPLETE差错(可以在日志中找到该信息)

总的来讲,函数这一历程如下:先用packet_get_string函数来提守信息中的字符串,假如碰到特定的恶意款式字符串,那么会发生一个严重的报错,从而关闭OpenSSH进程

这也便是Python编写的PoC脚本触发道理:先创建与OpenSSH办事器连接的加密哀求,然后发送恶意构造的SSH2_MSG_USERAUTH_REQUEST(公钥款式)哀求信息脚本中将Paramiko的add_boolean函数从新定义为一个空函数,Paramiko是Python顶用于SSH通讯的模块经由过程从新定义add_boolean函数,从而省略了信息中的布尔字段(也便是算法和字符串值之前的内容)

当userauth_pubkey函数解析该恶意构造的信息时,会先读取布尔字段,假如缺少了该字段,那么会读取下一个字段的第一位字节(packet_get_char函数):也便是算法字符串中的4位最高有效字节之后pakcet_get_string函数会调用来读取(并验证)算法字符串这一历程将会由于缺少布尔字节而发生差错

下面是一个精确款式的信息解析历程:

假如是缺少布尔字节的恶意款式信息,那么解析函数在事先不知道的环境下,先将第一位字节解析为布尔字节,使得信息整体左移了一位

这会导致考试测验解析一个1907字节长度的信息(0x00000773的十六进制),也便是跨越实际信息长度的信息那么ssh_packet_get_string函数就会调用fatal函数来停止OpenSSH进程

破绽总结

这是一个异常奇妙的破绽,由于它没有涉及到可以远程代码履行的缓冲区溢出漏洞和输入的验证历程

在全部历程中既没有缓冲区溢出,应用到的输入内容也都相符验证要求独一的问题是可能出于机能需求的斟酌,在一些函数处置惩罚后才进行对输入的验证,先判断用户名是否存在,假如不存在,那么就没需要进一步验证它的后续哀求历程

假如用户名存在,再对后续哀求进行验证,那么会导致不返复书息就中断连接这样就可以用来罗列一个用户名是否存在

这个问题的办理措施也很简单:改变下顺序,在调用其他函数前先对所有输入进行验证

在其他的身份验证函数中也有可能存在类似的问题,一个粗暴的,简单的判断措施是:反省所有类似”authctc -> valid”的表达式

同样的问题也呈现在基于主机的身份认证中(相关链接如下:https://github.com/openbsd/src/commit/779974d35b4859c07bc3cb8a12c74b43b0a7d1e0)

Kerberos身份认证中也存在该问题:

SSH1 RSA身份认证中也可能存在该问题(斟酌到现在的OpenBSD中都已经竣事应用,我们就没有进一步进行反省)

留意备注信息中也提到该风险问题

总结

假如你还在应用OpenSSH,那么在新的官方修复补丁推送前,禁用易受进击的身份认证机制例如关闭公钥身份认证后,能够有效地防止PoC脚本和类似的恶意款式认证哀求进击

也可以反省日志中的报错信息来判断该破绽是否遭到使用例如Ubuntu下,会有”incomplete message”的报错信息然而根据OpenSSH版本的不合,报错信息也会有一些差别同样对恶意款式的哀求进行改动,比如说构造一个字符串跨越最大年夜容许值长度的恶意信息,也有可能会孕育发生其他的报错信息

在默认的设置设置设备摆设摆设中,你只会收到一个简单的报错信息,不会记录客户真个IP地址是以你可以经由过程调剂日志等级(LogLevel),从INFO改为VERBOSE,从而创建包孕客户端IP地址等详细信息的日制但要留意这会天生更大年夜的日志文件,是以还必要监控日志是否跨越容量限定

上一页[1] [2]

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

评论 抢沙发

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

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

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