一、漏洞简介



1、漏洞编号和类型


CVE-2018-15473 SSH 用户名(USERNAME)暴力枚举漏洞

2、漏洞影响范围


OpenSSH 7.7及其以前版本

3、漏洞利用方式


由于SSH本身的认证机制存在缺陷,导致攻击者可以使用字典,暴力枚举SSH存在的用户名(Username)

4、漏洞修复方式


升级openssh

二、漏洞原理及其利用分析



1、漏洞原理


参考国外文献:http://www.openwall.com/lists/oss-security/2018/08/15/5

观察下列openssh代码

  1. 87 static int
  2. 88 userauth_pubkey(struct ssh *ssh)
  3. 89 {
  4. ...
  5. 101 if (!authctxt->valid) {
  6. 102 debug2("%s: disabled because of invalid user", __func__);
  7. 103 return 0;
  8. 104 }
  9. 105 if ((r = sshpkt_get_u8(ssh, &have_sig)) != 0 ||
  10. 106 (r = sshpkt_get_cstring(ssh, &pkalg, NULL)) != 0 ||
  11. 107 (r = sshpkt_get_string(ssh, &pkblob, &blen)) != 0)
  12. 108 fatal("%s: parse request failed: %s", __func__, ssh_err(r));

可以看出来,当用户不可用时,连接userauth_pubkey会直接返回,如果用户可用,则会进入下一个条件判断,调用fatal函数。所以在username可用于不可用两种情况下,可以看出来这个函数的返回是不同的

2、PoC原理


PoC地址:https://github.com/Rhynorater/CVE-2018-15473-Exploit

可以看下这段代码,这就是判断username是否可用的原理

  1. try:
  2. transport.auth_publickey(username, paramiko.RSAKey.generate(1024))
  3. except BadUsername:
  4. return (username, False)
  5. except paramiko.ssh_exception.AuthenticationException:
  6. return (username, True)

由此可见,一切就在paramiko这个库的transport.auth_publickey这个函数中

  1. def auth_publickey(self, username, key, event=None):
  2. """
  3. Authenticate to the server using a private key. The key is used to
  4. sign data from the server, so it must include the private part.
  5. If an ``event`` is passed in, this method will return immediately, and
  6. the event will be triggered once authentication succeeds or fails. On
  7. success, `is_authenticated` will return ``True``. On failure, you may
  8. use `get_exception` to get more detailed error information.
  9. Since 1.1, if no event is passed, this method will block until the
  10. authentication succeeds or fails. On failure, an exception is raised.
  11. Otherwise, the method simply returns.
  12. If the server requires multi-step authentication (which is very rare),
  13. this method will return a list of auth types permissible for the next
  14. step. Otherwise, in the normal case, an empty list is returned.
  15. :param str username: the username to authenticate as
  16. :param .PKey key: the private key to authenticate with
  17. :param .threading.Event event:
  18. an event to trigger when the authentication attempt is complete
  19. (whether it was successful or not)
  20. :return:
  21. list of auth types permissible for the next stage of
  22. authentication (normally empty)
  23. :raises:
  24. `.BadAuthenticationType` -- if public-key authentication isn't
  25. allowed by the server for this user (and no event was passed in)
  26. :raises:
  27. `.AuthenticationException` -- if the authentication failed (and no
  28. event was passed in)
  29. :raises: `.SSHException` -- if there was a network error
  30. """
  31. if (not self.active) or (not self.initial_kex_done):
  32. # we should never try to authenticate unless we're on a secure link
  33. raise SSHException('No existing session')
  34. if event is None:
  35. my_event = threading.Event()
  36. else:
  37. my_event = event
  38. self.auth_handler = AuthHandler(self)
  39. self.auth_handler.auth_publickey(username, key, my_event)
  40. if event is not None:
  41. # caller wants to wait for event themselves
  42. return []
  43. return self.auth_handler.wait_for_response(my_event)

根据PoC的代码,在username可用时,auth_publickey的函数会抛出异常,但是抛出的类型AuthenticationException,通过阅读这个函数的代码,返现只有self.auth_handler = AuthHandler(self)、self.auth_handler.auth_publickey(username, key, my_event), return self.auth_handler.wait_for_response(my_event)三条语句有可能会抛出这个异常,运行PoC测试发现,在最后一句话中抛出了异常(测试方法很简单的点灯法,节点前后print信息即可判断),跟踪进入这个函数wait_for_response。

  1. def wait_for_response(self, event):
  2. max_ts = None
  3. if self.transport.auth_timeout is not None:
  4. max_ts = time.time() + self.transport.auth_timeout
  5. while True:
  6. event.wait(0.1)
  7. #print self.transport.is_active()
  8. if not self.transport.is_active():
  9. e = self.transport.get_exception()
  10. #print "e:",e
  11. if (e is None) or issubclass(e.__class__, EOFError):
  12. e = AuthenticationException('Authentication failed.')
  13. raise e
  14. if event.is_set():
  15. break
  16. if max_ts is not None and max_ts <= time.time():
  17. raise AuthenticationException('Authentication timeout.')
  18. if not self.is_authenticated():
  19. e = self.transport.get_exception()
  20. if e is None:
  21. e = AuthenticationException('Authentication failed.')
  22. # this is horrible. Python Exception isn't yet descended from
  23. # object, so type(e) won't work. :(
  24. if issubclass(e.__class__, PartialAuthentication):
  25. return e.allowed_types
  26. raise e
  27. return []

这里有三个点可以抛出Authentication异常,经过修改打印信息获取到,异常抛出在下面的这个地方。

  1. if (e is None) or issubclass(e.__class__, EOFError):
  2. e = AuthenticationException('Authentication failed.')
  3. raise e

当用户不可用时,也是在这个点位抛出异常,但是没有进上文那个判断,所以e应该不是None,也不是EOFerror, 我们屏蔽掉BadUsername,回归到最近本的Python异常,发现返回的是这个Authencation Failed2异常,

  1. def wait_for_response(self, event):
  2. max_ts = None
  3. if self.transport.auth_timeout is not None:
  4. max_ts = time.time() + self.transport.auth_timeout
  5. while True:
  6. event.wait(0.1)
  7. #print self.transport.is_active()
  8. if not self.transport.is_active():
  9. e = self.transport.get_exception()
  10. #print "e:",e
  11. if (e is None) or issubclass(e.__class__, EOFError):
  12. e = AuthenticationException('Authentication failed1.')
  13. raise e
  14. if event.is_set():
  15. break
  16. if max_ts is not None and max_ts <= time.time():
  17. raise AuthenticationException('Authentication timeout.')
  18. if not self.is_authenticated():
  19. e = self.transport.get_exception()
  20. if e is None:
  21. e = AuthenticationException('Authentication failed2.')
  22. # this is horrible. Python Exception isn't yet descended from
  23. # object, so type(e) won't work. :(
  24. if issubclass(e.__class__, PartialAuthentication):
  25. return e.allowed_types
  26. raise e
  27. return []

彻掉后event事件被置位了,可以看出,而且根据下文中auth_publickey函数的注释部分可以看到的确如此,当身份验证完成时触发事件,根据漏洞原来描述,当username不可用时,openssh的函数就返回了,身份验证完成,触发了事件,因而跳出了while循环,又因为身份验证失败,所以进入了下一个判断,exception的对象e是None,于是就成了一个新的AuthenticationException异常。而username可用时,并没有完成身份认证,event没有触发,所以在while循环中因为认证失败跑出了异常。当然PoC中定义自定义异常,来区别这两个异常,从而做到判断,但是从程序过程中可以看到两个地方的的确在网络通信上是有差别的。

  1. """
  2. Authenticate to the server using a private key. The key is used to
  3. sign data from the server, so it must include the private part.
  4. If an ``event`` is passed in, this method will return immediately, and
  5. the event will be triggered once authentication succeeds or fails. On
  6. success, `is_authenticated` will return ``True``. On failure, you may
  7. use `get_exception` to get more detailed error information.
  8. Since 1.1, if no event is passed, this method will block until the
  9. authentication succeeds or fails. On failure, an exception is raised.
  10. Otherwise, the method simply returns.
  11. If the server requires multi-step authentication (which is very rare),
  12. this method will return a list of auth types permissible for the next
  13. step. Otherwise, in the normal case, an empty list is returned.
  14. :param str username: the username to authenticate as
  15. :param .PKey key: the private key to authenticate with
  16. :param .threading.Event event:
  17. an event to trigger when the authentication attempt is complete
  18. (whether it was successful or not)
  19. :return:
  20. list of auth types permissible for the next stage of
  21. authentication (normally empty)
  22. :raises:
  23. `.BadAuthenticationType` -- if public-key authentication isn't
  24. allowed by the server for this user (and no event was passed in)
  25. :raises:
  26. `.AuthenticationException` -- if the authentication failed (and no
  27. event was passed in)
  28. :raises: `.SSHException` -- if there was a network error
  29. """

SSH用户枚举漏洞(CVE-2018-15473)原理学习的更多相关文章

  1. 【推荐】CentOS修复OpenSSH用户枚举漏洞

    注:以下所有操作均在CentOS 6.8 x86_64位系统下完成. #漏洞说明# OpenSSH(OpenBSD Secure Shell)是OpenBSD计划组所维护的一套用于安全访问远程计算机的 ...

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

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

  3. 漏洞复现-CVE-2018-15473-ssh用户枚举漏洞

          0x00 实验环境 攻击机:Win 10 0x01 影响版本 OpenSSH 7.7前存在一个用户名枚举漏洞,通过该漏洞,攻击者可以判断某个用户名是否存在于目标主机 0x02 漏洞复现 针 ...

  4. SMTP用户枚举原理简介及相关工具

    前言 SMTP是安全测试中比较常见的服务类型,其不安全的配置(未禁用某些命令)会导致用户枚举的问题,这主要是通过SMTP命令进行的.本文将介绍SMTP用户枚举原理以及相关工具. SMTP SMTP命令 ...

  5. Linux启动或禁止SSH用户及IP的登录

    启动或禁止SSH用户登录 一般情况下,在使用Linux操作系统都不会去机房来操作机器,都是使用一些第三方的工具来操作. 比如使用SSH Secure File Transfer Client工具来传输 ...

  6. Linux启动或禁止SSH用户及IP的登录,只允许密钥验证登录模式

    启动或禁止SSH用户登录 一般情况下,在使用Linux操作系统都不会去机房来操作机器,都是使用一些第三方的工具来操作. 比如使用SSH Secure File Transfer Client工具来传输 ...

  7. Linux启动与禁止SSH用户及IP的登录

    以下就针对SSH方面讨论一下.假设有人特别关注Linux环境的安全性,第一就从login方面来进行讨论 1:Linux启动或禁止SSH root用户的登录 2:Linux限制SSH用户 事实上这些东西 ...

  8. SSH免密登陆配置过程和原理解析

    SSH免密登陆配置过程和原理解析 SSH免密登陆配置过很多次,但是对它的认识只限于配置,对它认证的过程和基本的原理并没有什么认识,最近又看了一下,这里对学习的结果进行记录. 提纲: 1.SSH免密登陆 ...

  9. linux查看ssh用户登录日志与操作日志

    linux查看ssh用户登录日志与操作日志 2013-11-01转载   ssh用户登录日志 linux下登录日志在下面的目录里:  代码如下 复制代码 cd /var/log 查看ssh用户的登录日 ...

随机推荐

  1. 软渲染 SoftRender

    弄了这几年OpenGL对管线还是算比较熟悉,写起来也比较顺,不过每个顶点都要经过一堆变换,着实感到效率的重要.(矩阵乘顶点没有SSE加速啊)装个B,半天的成果..(主要很多东西都写好了直接拿来) // ...

  2. 关于js中namespace命名空间模式

    命名空间有助于减少程序中所需要的全局变量的数量,并且同时有助于避免命名冲突或过长的名字前缀. 关于命名空间的例子: /** * 创建全局对象MYAPP * @module MYAPP * @title ...

  3. categorys源码

    CREATE TABLE `category` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `editdate` char(20) NOT NUL ...

  4. 114自定义UITableViewCell(扩展知识:为UITableViewCell添加动画效果)

    关键操作: 效果如下: ViewController.h #import <UIKit/UIKit.h> @interface ViewController : UITableViewCo ...

  5. 12 go实现几中基本排序算法

    include 冒泡排序 插入排序 快速排序 选择排序 这4种算法的内涵不再做解释了 github地址 冒泡排序算法 func maoPao(intSlice []int) []int { /* 冒泡 ...

  6. 多个Tomcat之间实现Session共享

    对于高访问量.高并发量的网站或web应用来说,目前最常见的解决方案应该就是利用负载均衡进行server集群,例如比较流行的nginx+memcache+tomcat.集群之后比如我们有N个Tomcat ...

  7. GridFS实现原理

    GridFS在数据库中,默认使用fs.chunks和fs.files来存储文件. 其中fs.files集合存放文件的信息,fs.chunks存放文件数据. 一个fs.files集合中的一条记录内容如下 ...

  8. flume 增量上传日志文件到HDFS中

    1.采集日志文件时一个很常见的现象 采集需求:比如业务系统使用log4j生成日志,日志内容不断增加,需要把追加到日志文件中的数据实时采集到hdfs中. 1.1.根据需求,首先定义一下3大要素: 采集源 ...

  9. OpenSift源代码编译过程记录

    本文记录了在CentOS6.5上编译Sift的开源实现OpenSift的编译过程,同一时候记录了编译过程中的几个问题. sift的理论已经有非常多了,以下会给出链接: 1.Requirements a ...

  10. CSS3制作美丽的3D表单

    <!DOCTYPE HTML> <html lang="en-US"> <head> <meta charset="UTF-8& ...