Netatalk缓冲区溢出漏洞(CVE-2018-1160)的发现与利用
最近,我发现并报告了一个Netatalk缓冲区溢出漏洞(CVE-2018-1160),这个漏洞非常古老,允许远程未经身份验证的攻击者覆盖某些结构数据。利用该漏洞,我成功绕过身份验证,并获得对AFP卷的完全控制。本文将主要分析我们是如何发现并利用这个漏洞的。
漏洞利用视频:https://youtu.be/SCGzlz4DJLg
关于Netatalk
Netatalk是苹果归档协议(Apple Filing Protocol,AFP)的一种实现。该项目自身非常古老,在Sourceforge的第一次导入最早可以追溯到2000年,但该项目的实际年龄比这还要更长。从main.c中,我们可以看到相应的注释:
/*
* Copyright © 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
*/
如今,Netatalk已经不再像以前那样受欢迎,其他的一些网络文件共享协议已经超过了AFP(例如SMB)。但是,我们仍然看到Netatalk在Sourceforge中具有非常多的下载量,它在许多Linux发行版本的官方存储库中都有一个软件包。我也在很多路由器和NAS上都发现了Netatalk,因此该协议仍然存在于我们周围。
我想说的是,假如Shodan可以搜索AFP,你一定会发现十亿台Netatalk服务器,但实际上Shodan没有这个功能。不过,请大家相信我,真的有这么多用户。
漏洞概述
自从2000年最初引入Sourceforge以来,Netatalk的漏洞一直就没有引起充分的重视。
这个错误其实非常简单,以下是Netatalk 3.1.11版本中的代码:
/* parse options */
while (i cmdlen) {
switch (dsi->commands[i++]) {
case DSIOPT_ATTNQUANT:
memcpy(&dsi->attn_quantum, dsi->commands + i + 1,
dsi->commands[i]);
dsi->attn_quantum = ntohl(dsi->attn_quantum);
case DSIOPT_SERVQUANT: /* just ignore these */
default:
i += dsi->commands[i] + 1; /*forward past length tag + length */
break;
}
}
大家可能看得还不是很明显。那么我来强调一个前提,如果说dsi->attn_quantum这个4字节整数和dsi->commands是由攻击者控制的,那么大家应该就一目了然了。
接下来,我们分析memcpy。攻击者控制的两个参数负责将数据复制到整型变量中。攻击者控制源(dsi->commands + i + 1)和大小(dsi->commands[i])。由于dsi->commands是char数组,因此size参数的最大值限制为255。
在开始寻找“AAAAAAAAAAAAAAAAAAAAAAAA”之前,我们首先检查实际上可以覆盖的内容。以下代码来自include/libatalk/dsi.h:
#define DSI_DATASIZ 65536
/* child and parent processes might interpret a couple of these
* differently. */
typedef struct DSI {
struct DSI *next; /* multiple listening addresses */
AFPObj *AFPobj;
int statuslen;
char status[1400];
char *signature;
struct dsi_block header;
struct sockaddr_storage server, client;
struct itimerval timer;
int tickle; /* tickle count */
int in_write;
int msg_request; /* pending message to the client */
int down_request; /* pending SIGUSR1 down in 5 mn */
uint32_t attn_quantum, datasize, server_quantum;
uint16_t serverID, clientID;
uint8_t *commands; /* DSI recieve buffer */
uint8_t data[DSI_DATASIZ]; /* DSI reply buffer */
size_t datalen, cmdlen;
...
由于数据阵列中存在大量“黑洞”,因此我们只能覆盖datasize、server_quantum、serverID、clientID、命令指针以及部分数据。
污点分析
人们总是想要知道我是如何发现这个漏洞的。他们总是想听到“污点分析”(Taint Analysis)这个词。当他们听到“中间语言”时,可能会叹气。人们希望能看到种子语料库,并希望能听到前沿研究的内容。
我在从奥斯汀飞往费城的3个小时航班上发现了这个漏洞。当时,我刚开完一个会议,准备飞回家,路途上网络不是太好,我没有什么可以做的。因此,我在笔记本电脑上安装了Netatalk源,尝试绕过NAS项目。一开始,我从阅读main源代码起步。
PoC
该漏洞具有一个独特的特点,其中一个被覆盖的变量server_quantum会被反射到攻击者那里。经过分析,下面代码将向服务器发送一个格式正确的DSI Open Session请求。
import socket
import struct
import sys
if len(sys.argv) != 3:
sys.exit(0)
ip = sys.argv[1]
port = int(sys.argv[2])
最近,我发现并报告了一个Netatalk缓冲区溢出漏洞(CVE-2018-1160),这个漏洞非常古老,允许远程未经身份验证的攻击者覆盖某些结构数据。利用该漏洞,我成功绕过身份验证,并获得对AFP卷的完全控制。本文将主要分析我们是如何发现并利用这个漏洞的。
漏洞利用视频:https://youtu.be/SCGzlz4DJLg
关于Netatalk
Netatalk是苹果归档协议(Apple Filing Protocol,AFP)的一种实现。该项目自身非常古老,在Sourceforge的第一次导入最早可以追溯到2000年,但该项目的实际年龄比这还要更长。从main.c中,我们可以看到相应的注释:
/*
* Copyright © 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
*/
如今,Netatalk已经不再像以前那样受欢迎,其他的一些网络文件共享协议已经超过了AFP(例如SMB)。但是,我们仍然看到Netatalk在Sourceforge中具有非常多的下载量,它在许多Linux发行版本的官方存储库中都有一个软件包。我也在很多路由器和NAS上都发现了Netatalk,因此该协议仍然存在于我们周围。
我想说的是,假如Shodan可以搜索AFP,你一定会发现十亿台Netatalk服务器,但实际上Shodan没有这个功能。不过,请大家相信我,真的有这么多用户。 www.wnhack.com
漏洞概述
自从2000年最初引入Sourceforge以来,Netatalk的漏洞一直就没有引起充分的重视。
这个错误其实非常简单,以下是Netatalk 3.1.11版本中的代码:
/* parse options */
while (i cmdlen) {
switch (dsi->commands[i++]) {
case DSIOPT_ATTNQUANT:
memcpy(&dsi->attn_quantum, dsi->commands + i + 1,
dsi->commands[i]);
dsi->attn_quantum = ntohl(dsi->attn_quantum);
case DSIOPT_SERVQUANT: /* just ignore these */
default:
i += dsi->commands[i] + 1; /*forward past length tag + length */
break;
}
}
大家可能看得还不是很明显。那么我来强调一个前提,如果说dsi->attn_quantum这个4字节整数和dsi->commands是由攻击者控制的,那么大家应该就一目了然了。
接下来,我们分析memcpy。攻击者控制的两个参数负责将数据复制到整型变量中。攻击者控制源(dsi->commands + i + 1)和大小(dsi->commands[i])。由于dsi->commands是char数组,因此size参数的最大值限制为255。
在开始寻找“AAAAAAAAAAAAAAAAAAAAAAAA”之前,我们首先检查实际上可以覆盖的内容。以下代码来自include/libatalk/dsi.h:
#define DSI_DATASIZ 65536
/* child and parent processes might interpret a couple of these
* differently. */
typedef struct DSI {
struct DSI *next; /* multiple listening addresses */
AFPObj *AFPobj;
int statuslen;
char status[1400];
char *signature;
struct dsi_block header;
struct sockaddr_storage server, client;
struct itimerval timer;
int tickle; /* tickle count */
int in_write;
int msg_request; /* pending message to the client */
int down_request; /* pending SIGUSR1 down in 5 mn */
uint32_t attn_quantum, datasize, server_quantum;
uint16_t serverID, clientID;
uint8_t *commands; /* DSI recieve buffer */
uint8_t data[DSI_DATASIZ]; /* DSI reply buffer */
size_t datalen, cmdlen;
...
由于数据阵列中存在大量“黑洞”,因此我们只能覆盖datasize、server_quantum、serverID、clientID、命令指针以及部分数据。
污点分析
人们总是想要知道我是如何发现这个漏洞的。他们总是想听到“污点分析”(Taint Analysis)这个词。当他们听到“中间语言”时,可能会叹气。人们希望能看到种子语料库,并希望能听到前沿研究的内容。
我在从奥斯汀飞往费城的3个小时航班上发现了这个漏洞。当时,我刚开完一个会议,准备飞回家,路途上网络不是太好,我没有什么可以做的。因此,我在笔记本电脑上安装了Netatalk源,尝试绕过NAS项目。一开始,我从阅读main源代码起步。
PoC
该漏洞具有一个独特的特点,其中一个被覆盖的变量server_quantum会被反射到攻击者那里。经过分析,下面代码将向服务器发送一个格式正确的DSI Open Session请求。
import socket
import struct
import sys
if len(sys.argv) != 3:
sys.exit(0)
ip = sys.argv[1]
port = int(sys.argv[2])