漏洞简介
Memcached是一个广泛使用的高速缓存系统,近期研究者发现小于1.4.33的版本存在3个整数溢出漏洞,通过这几个漏洞攻击者可以触发堆溢出导致crash。官方在11月1日发布了升级公告。漏洞作者已经提供了很详细的描述,在这里仅做简单的整理和验证。
后面验证了阿里云ApsaraDB for Memcache不受漏洞影响,并分析了原因。这个案例深刻告诉我们,对于用户输入,一定要做全面的检查。
漏洞分析
漏洞仅仅在binary时会触发。本质都是没有对用户输入的协议做严格全面的边界检查,导致在调用item.c
中的do_item_alloc()
函数时, 传入的参数nbytes是个负值,导致堆栈溢出。
item *do_item_alloc(char *key, const size_t nkey, const int flags,
const rel_time_t exptime, const int nbytes,
const uint32_t cur_hv) {
size_t ntotal = item_make_header(nkey + 1, flags, nbytes, suffix, &nsuffix);
}
ntotal大小的内存用来存放item、flags、key、value。当nbytes为负值,导致ntotal偏小,导致溢出。
CVE-2016-8704
当执行Append (opcode 0x0e), Prepend (opcode 0x0f), AppendQ (0x19), PrependQ (opcode 0x1a) 命令时会进入这样如下代码路径:
case PROTOCOL_BINARY_CMD_APPEND:
case PROTOCOL_BINARY_CMD_PREPEND:
if (keylen > 0 && extlen == 0) {
bin_read_key(c, bin_reading_set_header, 0);
} else {
protocol_error = 1;
}
break;
这里并仅检查了keylen和extlen的值,并没有检查bodylen。
complete_nread_binary()
后,即当从socket中读取和解析完header、extlen、key后,注意此时value还没从socket中读取,程序进入了process_bin_append_prepend()
函数中,
key = binary_get_key(c);
nkey =