天天看點

Memcached指令執行漏洞(CVE-2016-8704、CVE-2016-8705、CVE-2016-8706)原理和對阿裡雲Memcache影響分析

後面驗證了阿裡雲apsaradb for memcache不受漏洞影響,并分析了原因。這個案例深刻告訴我們,對于使用者輸入,一定要做全面的檢查。

漏洞僅僅在binary時會觸發。本質都是沒有對使用者輸入的協定做嚴格全面的邊界檢查,導緻在調用<code>item.c</code>中的<code>do_item_alloc()</code>函數時, 傳入的參數nbytes是個負值,導緻堆棧溢出。

ntotal大小的記憶體用來存放item、flags、key、value。當nbytes為負值,導緻ntotal偏小,導緻溢出。

當執行append (opcode 0x0e), prepend (opcode 0x0f), appendq (0x19), prependq (opcode 0x1a) 指令時會進入這樣如下代碼路徑:

這裡并僅檢查了keylen和extlen的值,并沒有檢查bodylen。

<code>complete_nread_binary()</code>後,即當從socket中讀取和解析完header、extlen、key後,注意此時value還沒從socket中讀取,程式進入了<code>process_bin_append_prepend()</code>函數中,

這裡<code>keylen</code>做過合法性檢查,<code>bodylen</code>沒有,是以<code>itme_alloc()函數中</code>的參數中<code>key</code>、<code>nkey</code>可以保證合法性,但<code>vlen</code>無法保證。

poc代碼:

當進入<code>process_bin_append_prepend()</code>函數中,nkey 250、vlen -250, 調用<code>item_alloc()</code>, 觸發漏洞。

當進行set (opcode 0x01),add (opcode 0x02), replace (opcode 0x03) ,setq (opcode 0x11), addq (opcode 0x12) ,replaceq (opcode 0x13)作時會進入如下代碼路徑:

在這裡需滿足bodylen &gt;= (keylen + 8),這裡要注意的是各變量類型,bodylen 為uint32_t。

<code>complete_nread_binary()</code>後,即當從socket中讀取和解析完header、extlen、key後,注意此時value還沒從socket中讀取,程式進入<code>process_bin_update()</code>:

bodylen為無符号整形,在指派給整形的vlen時會做類型轉換,若bodylen過大, vlen 會變成一個負數,進而調用<code>item_alloc()</code>觸發漏洞。

poc:

<code>dispatch_bin_command()</code>中 keylen為250,bodylen為 4294967248,通過了檢查。<code>process_bin_update()</code>中 nkey為250,vlen 為 -306,調用<code>item_alloc()</code> 觸發漏洞。

當進行 sasl_auth 操作,進入下面代碼步驟:

這裡隻檢查了extlen 和keylen,沒有對bodylen進行檢查。

<code>complete_nread_binary()</code>後,即當從socket中讀取和解析完header、extlen、key後,注意此時value還沒從socket中讀取,進入<code>process_bin_sasl_auth()</code>函數:

隻要bodylen 小于keylen,vlen 變為負值。

poc:

<code>process_bin_sasl_auth()</code>中 nkey為32,vlen 為 -31,調用<code>item_alloc()</code>觸發漏洞。

阿裡雲apsaradb for memcache,底層不是用的官方memcached,而且基于自研的tair,相容memcached協定。對于使用者輸入的協定,做了嚴格的邊界檢查,避免了上述漏洞。相關部分僞代碼如下:

使用上述的poc代碼測試apsaradb for memcache,對應連接配接會被server端直接close()掉。

繼續閱讀