蜜罐技術的核心在於模擬真實系統,誘使攻擊者發動攻擊,從而收集攻擊行為和情報。本文詳細介紹瞭如何使用 Python 和 Scapy 構建 ICMP 和 TCP 蜜罐,包括封包的製作、接收和傳送,並利用多執行緒技術提升蜜罐的處理效能。同時,文章也闡述瞭如何偽造作業系統和 Web 伺服器簽名,以迷惑攻擊者,增加蜜罐的有效性。此外,本文也涵蓋了網頁伺服器足跡分析的技術,藉由分析錯誤處理機制和 HTTP 標頭資訊,收集網頁伺服器的相關資訊,例如作業系統、Web 伺服器軟體版本等,為後續的滲透測試提供基礎。
偽裝陷阱建置:針對攻擊者的蜜罐技術 Chapter 6
ICMP 回應封包製作
在建立蜜罐的過程中,我們需要製作 ICMP 回應封包來應對攻擊者的探測。以下函式展示瞭如何構建 ICMP 回應封包:
def icmp_reply_packet(icmp_header, icmp_data):
try:
dest_addr = '192.168.1.100'
icmp_type = 0 # ICMP echo reply
icmp_code = 0
icmp_identifier = 1
icmp_sequence_number = 1
packet = struct.pack('!BBHHH', icmp_type, icmp_code, icmp_identifier, icmp_sequence_number, 0)
packet += icmp_data
return packet
except Exception as e:
print(f"Error: {e}")
內容解密:
struct.pack用於將資料封裝成二進位制格式,符合 ICMP 封包的結構。icmp_type設定為 0,表示這是一個 ICMP 回應封包。icmp_code通常為 0,表示沒有特定的錯誤碼。icmp_identifier和icmp_sequence_number用於匹配請求和回應。- 將原始的 ICMP 資料附加到封包中,以保持與請求的一致性。
乙太網標頭製作
為了讓封包能夠在網路上傳輸,我們需要新增乙太網標頭:
def ethernet_header(src_mac, dst_mac, ether_type):
eth_header = struct.pack('!6s6sH', src_mac, dst_mac, ether_type)
return eth_header
內容解密:
struct.pack用於構建乙太網標頭,包含源 MAC 地址、目的 MAC 地址和乙太網型別。- 源和目的 MAC 地址均為 6 位元組,乙太網型別(如 IPv4)為 2 位元組。
接收請求封包
以下程式碼用於接收來自網路的請求封包:
def receiver_icmp():
while True:
try:
received_packet = my_socket.recvfrom(2048)
protocol_type = received_packet[0][23]
if protocol_type == 1: # ICMP
icmp_packet = received_packet[0][34:]
# 處理 ICMP 封包
except Exception as e:
print(f"Error: {e}")
內容解密:
- 使用原始通訊端接收網路封包。
- 檢查封包的協定型別,確認是否為 ICMP。
- 處理接收到的 ICMP 封包。
傳送 ICMP 回應
當接收到 ICMP 請求時,我們需要發送回應:
def sender_icmp(data_tuple):
while True:
try:
icmp_packet = icmp_reply_packet(data_tuple[0], data_tuple[1])
my_socket.send(data_tuple[2], icmp_packet)
except Exception as e:
print(f"Error: {e}")
內容解密:
- 使用
icmp_reply_packet函式生成 ICMP 回應封包。 - 將回應封包傳送給請求者。
多執行緒處理
為了同時處理接收和傳送,我們使用多執行緒:
r = threading.Thread(target=receiver_icmp)
s = threading.Thread(target=sender_icmp)
r.start()
s.start()
內容解密:
- 建立兩個執行緒,分別負責接收和傳送 ICMP 封包。
- 同時啟動這兩個執行緒,以實作平行處理。
TCP層偽裝回應
對於 TCP 層的掃描,我們同樣需要提供偽裝回應。這裡我們使用 Scapy 函式庫來簡化 TCP 封包的構建:
from scapy.all import *
def receiver_tcp():
my_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP)
while True:
try:
packet = my_socket.recvfrom(2048)
# 處理 TCP 封包
except Exception as e:
print(f"Error: {e}")
內容解密:
- 使用 Scapy 處理 TCP 層的掃描請求。
- 對特定的埠(如 554、128 或 80)進行監聽,並回應 SYN-ACK 或 RST-ACK。
傳送 TCP 回應
根據接收到的 TCP 請求,傳送適當的回應:
def sender_tcp(flags, src_ip, dst_ip, src_port, dst_port, seq, ack):
packet = IP(src=src_ip, dst=dst_ip)/TCP(sport=src_port, dport=dst_port, flags=flags, seq=seq, ack=ack)
send(packet)
內容解密:
- 使用 Scapy 建立 TCP 封包,並設定相應的旗標(SYN-ACK 或 RST-ACK)。
- 傳送該封包給請求者。
多執行緒處理 TCP 回應
同樣地,我們使用多執行緒來處理 TCP 請求和回應:
r = threading.Thread(target=receiver_tcp)
r.start()
for _ in range(3):
t = threading.Thread(target=sender_tcp)
t.start()
內容解密:
- 建立多個執行緒來處理 TCP 請求和回應。
- 同時啟動這些執行緒,以實作平行處理。
第6章:蜜罐 – 為攻擊者築造陷阱
在前面的輸出中,我們使用了 Scapy 和 Python 程式碼(第3章,掃描滲透測試)。Scapy 和 Python 程式碼都使用了三次握手過程。輸出結果表明,埠 22 和 80 是開放的。
對 nmap 偽造作業系統簽名回應
在本文中,我們將建立一個偽造的作業系統簽名。使用以下 Scapy 程式碼,我們可以識別受害者機器的作業系統:
from scapy.all import IP, TCP, send
# 定義目標 IP 和埠
target_ip = "192.168.1.100"
open_port = 80
closed_port = 22
# 傳送七個 TCP/IP 偽造的封包並評估回應
# 詳細資訊請參閱網頁:https://nmap.org/book/osdetect.html
內容解密:
- Scapy 程式碼的作用:Scapy 是一個強大的封包處理工具,可以用於傳送自定義的封包。在這裡,我們使用它來模擬 Nmap 的作業系統檢測行為。
- 三次握手過程:在建立 TCP 連線時,客戶端和伺服器之間會進行三次握手。Scapy 可以用來傳送 SYN 封包,並接收伺服器的回應,以此來判斷埠是否開放。
- 偽造作業系統簽名:透過傳送特定的 TCP/IP 封包並分析伺服器的回應,Nmap 可以猜測遠端主機的作業系統。我們可以透過 Scapy 模擬這個過程,並傳回一個偽造的作業系統簽名。
偽造 Web 伺服器回應
在本文中,您將學習如何建立一個偽造的 Web 伺服器簽名。這是應用層程式碼。本文的程式碼與前面的程式碼無關。為了取得伺服器簽名或 Banner Grabbing,我將使用 ID Serve 工具。
Python 程式碼:偽造 Web 伺服器
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
import logging
class FakeWebServer(BaseHTTPRequestHandler):
def send_response(self, code, message=None):
self.send_response_only(code, message)
self.send_header('Server', 'Fake Server')
self.end_headers()
def do_GET(self):
self.send_response(200)
self.wfile.write("Hello, World!")
def run(server_class=HTTPServer, handler_class=FakeWebServer, port=8080):
server_address = ('', port)
httpd = server_class(server_address, handler_class)
print('Starting httpd...')
httpd.serve_forever()
run()
內容解密:
FakeWebServer類別的作用:這個類別繼承自BaseHTTPRequestHandler,用於處理 HTTP 請求。在這裡,我們重寫了send_response方法,以傳送自定義的伺服器簽名。do_GET方法的作用:當接收到 GET 請求時,這個方法會被呼叫。它傳送一個 200 OK 的回應,並傳回 “Hello, World!"。run函式的作用:這個函式啟動了一個 HTTP 伺服器,監聽在指定的埠上。
紀錄檔處理
import logging
logging.basicConfig(filename='honeypot.log', level=logging.INFO)
logger = logging.getLogger(__name__)
# 設定紀錄檔格式
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger.setLevel(logging.INFO)
內容解密:
- 紀錄檔的作用:紀錄檔可以用於記錄客戶端的請求資訊,包括 IP 地址、請求時間等。
logging模組的使用:Python 的logging模組提供了一個靈活的紀錄檔系統,可以用於記錄不同級別的資訊。
第7章:對 Web 伺服器和 Web 應用程式進行足跡勘察
到目前為止,我們已經閱讀了四章,從資料鏈路層到傳輸層的相關內容。現在,我們將轉向應用層滲透測試。在本章中,我們將介紹以下主題:
- 對 Web 伺服器進行足跡勘察的概念
- 資訊收集簡介
- HTTP 標頭檢查
- 使用 BeautifulSoup 解析器從 smartwhois.com 蒐集網站資訊
- 網站的 Banner Grabbing
- 加固 Web 伺服器
對 Web 伺服器進行足跡勘察的概念
滲透測試的概念不能一步到位,因此被分為幾個步驟。足跡勘察是滲透測試的第一步,攻擊者試圖蒐集有關目標的資訊。在當今世界,電子商務正在迅速發展。因此,Web 伺服器已成為駭客的主要目標。為了攻擊 Web 伺服器,我們必須首先了解 Web 伺服器是什麼。我們還需要了解 Web 伺服器託管軟體、託管作業系統以及在 Web 伺服器上執行的應用程式。在獲得這些資訊後,我們可以構建我們的漏洞利用。獲得這些資訊被稱為對 Web 伺服器進行足跡勘察。
網頁伺服器與網頁應用程式的足跡分析
介紹資訊收集
在本文中,我們將嘗試透過錯誤處理技術來收集有關網頁軟體、作業系統和在網頁伺服器上執行的應用程式的資訊。從駭客的角度來看,從錯誤處理中收集資訊並不是很有用。然而,從滲透測試人員的角度來看,這是非常重要的,因為在提交給客戶的滲透測試最終報告中,您必須指定錯誤處理技術。
錯誤處理的邏輯
錯誤處理的邏輯是嘗試在網頁伺服器中產生錯誤,該錯誤傳回程式碼 404,並檢視錯誤頁面的輸出。我編寫了一個小的程式碼來取得輸出。我們將逐行瀏覽以下程式碼:
程式碼解析
import re
import random
import urllib2
url2 = raw_input("Enter the URL: ")
r = chr(random.randint(97, 123))
url3 = url2 + r
http_r = urllib2.urlopen(url3)
content = http_r.read()
flag = 0
i = 0
list1 = []
addr = "<address>"
file_text = open("result.txt", "a")
while flag != 1:
http_r = urllib2.urlopen(url3)
if http_r.code == 404:
file_text.write(".................")
file_text.write(url2)
file_text.write(".................")
file_text.write(content)
for match in re.finditer(addr, content):
i = i + 1
s = match.start()
e = match.end()
list1.append(s)
list1.append(e)
if i > 0:
print "Coding is not good"
if len(list1) > 0:
a = list1[0]
b = list1[1]
print content[a:b]
flag = 1
elif http_r.code == 200:
print "Web page is using Custom Error Page"
break
內容解密:
- 匯入必要的模組:程式碼首先匯入了
re、random和urllib2三個模組,分別用於正規表示式、生成隨機數和URL相關的操作。 - 取得使用者輸入的URL:
url2 = raw_input("Enter the URL: ")這行程式碼要求使用者輸入一個URL,並將其儲存在url2變數中。 - 生成隨機字元並建構新的URL:程式碼生成一個隨機的小寫字母,並將其附加到使用者輸入的URL後面,形成新的URL
url3。 - 開啟新的URL並讀取內容:使用
urllib2.urlopen(url3)開啟新的URL,並將傳回的HTTP回應物件儲存在http_r中。然後,content = http_r.read()將回應的內容讀取到content變數中。 - 檢查HTTP狀態碼:程式碼檢查
http_r.code以確定HTTP請求的狀態。如果狀態碼為404,表示頁面未找到,程式碼將進一步處理內容。 - 查詢特定標籤並提取資訊:使用正規表示式在
content中查詢<address>標籤,並將其起始和結束位置儲存在list1中。如果找到該標籤,則提取標籤之間的內容並列印預出來。 - 處理自定義錯誤頁面:如果HTTP狀態碼為200,但頁面內容包含自定義錯誤訊息,程式碼會列印預出相應的訊息。
檢視HTTP頭部資訊
透過檢視網頁的頭部資訊,可以獲得與錯誤處理類別似的輸出。有時,伺服器錯誤輸出可以透過程式設計來更改,但是檢查頭部可能提供很多資訊。以下是一個簡單的程式碼範例:
程式碼解析
import urllib2
url2 = raw_input("Enter the URL: ")
http_r = urllib2.urlopen(url2)
print http_r.headers
內容解密:
- 匯入必要的模組:程式碼匯入了
urllib2模組,用於URL相關的操作。 - 取得使用者輸入的URL:與前面的例子類別似,要求使用者輸入一個URL。
- 開啟URL並列印頭部資訊:使用
urllib2.urlopen(url2)開啟URL,並將傳回的HTTP回應物件儲存在http_r中。然後,print http_r.headers將HTTP回應的頭部資訊列印預出來。