蜜罐技術的核心在於模擬真實系統,誘使攻擊者發動攻擊,從而收集攻擊行為和情報。本文詳細介紹瞭如何使用 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}")

內容解密:

  1. struct.pack 用於將資料封裝成二進位制格式,符合 ICMP 封包的結構。
  2. icmp_type 設定為 0,表示這是一個 ICMP 回應封包。
  3. icmp_code 通常為 0,表示沒有特定的錯誤碼。
  4. icmp_identifiericmp_sequence_number 用於匹配請求和回應。
  5. 將原始的 ICMP 資料附加到封包中,以保持與請求的一致性。

乙太網標頭製作

為了讓封包能夠在網路上傳輸,我們需要新增乙太網標頭:

def ethernet_header(src_mac, dst_mac, ether_type):
    eth_header = struct.pack('!6s6sH', src_mac, dst_mac, ether_type)
    return eth_header

內容解密:

  1. struct.pack 用於構建乙太網標頭,包含源 MAC 地址、目的 MAC 地址和乙太網型別。
  2. 源和目的 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}")

內容解密:

  1. 使用原始通訊端接收網路封包。
  2. 檢查封包的協定型別,確認是否為 ICMP。
  3. 處理接收到的 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}")

內容解密:

  1. 使用 icmp_reply_packet 函式生成 ICMP 回應封包。
  2. 將回應封包傳送給請求者。

多執行緒處理

為了同時處理接收和傳送,我們使用多執行緒:

r = threading.Thread(target=receiver_icmp)
s = threading.Thread(target=sender_icmp)
r.start()
s.start()

內容解密:

  1. 建立兩個執行緒,分別負責接收和傳送 ICMP 封包。
  2. 同時啟動這兩個執行緒,以實作平行處理。

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}")

內容解密:

  1. 使用 Scapy 處理 TCP 層的掃描請求。
  2. 對特定的埠(如 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)

內容解密:

  1. 使用 Scapy 建立 TCP 封包,並設定相應的旗標(SYN-ACK 或 RST-ACK)。
  2. 傳送該封包給請求者。

多執行緒處理 TCP 回應

同樣地,我們使用多執行緒來處理 TCP 請求和回應:

r = threading.Thread(target=receiver_tcp)
r.start()
for _ in range(3):
    t = threading.Thread(target=sender_tcp)
    t.start()

內容解密:

  1. 建立多個執行緒來處理 TCP 請求和回應。
  2. 同時啟動這些執行緒,以實作平行處理。

第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

內容解密:

  1. Scapy 程式碼的作用:Scapy 是一個強大的封包處理工具,可以用於傳送自定義的封包。在這裡,我們使用它來模擬 Nmap 的作業系統檢測行為。
  2. 三次握手過程:在建立 TCP 連線時,客戶端和伺服器之間會進行三次握手。Scapy 可以用來傳送 SYN 封包,並接收伺服器的回應,以此來判斷埠是否開放。
  3. 偽造作業系統簽名:透過傳送特定的 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()

內容解密:

  1. FakeWebServer 類別的作用:這個類別繼承自 BaseHTTPRequestHandler,用於處理 HTTP 請求。在這裡,我們重寫了 send_response 方法,以傳送自定義的伺服器簽名。
  2. do_GET 方法的作用:當接收到 GET 請求時,這個方法會被呼叫。它傳送一個 200 OK 的回應,並傳回 “Hello, World!"。
  3. 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)

內容解密:

  1. 紀錄檔的作用:紀錄檔可以用於記錄客戶端的請求資訊,包括 IP 地址、請求時間等。
  2. 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

內容解密:

  1. 匯入必要的模組:程式碼首先匯入了 rerandomurllib2 三個模組,分別用於正規表示式、生成隨機數和URL相關的操作。
  2. 取得使用者輸入的URLurl2 = raw_input("Enter the URL: ") 這行程式碼要求使用者輸入一個URL,並將其儲存在 url2 變數中。
  3. 生成隨機字元並建構新的URL:程式碼生成一個隨機的小寫字母,並將其附加到使用者輸入的URL後面,形成新的URL url3
  4. 開啟新的URL並讀取內容:使用 urllib2.urlopen(url3) 開啟新的URL,並將傳回的HTTP回應物件儲存在 http_r 中。然後,content = http_r.read() 將回應的內容讀取到 content 變數中。
  5. 檢查HTTP狀態碼:程式碼檢查 http_r.code 以確定HTTP請求的狀態。如果狀態碼為404,表示頁面未找到,程式碼將進一步處理內容。
  6. 查詢特定標籤並提取資訊:使用正規表示式在 content 中查詢 <address> 標籤,並將其起始和結束位置儲存在 list1 中。如果找到該標籤,則提取標籤之間的內容並列印預出來。
  7. 處理自定義錯誤頁面:如果HTTP狀態碼為200,但頁面內容包含自定義錯誤訊息,程式碼會列印預出相應的訊息。

檢視HTTP頭部資訊

透過檢視網頁的頭部資訊,可以獲得與錯誤處理類別似的輸出。有時,伺服器錯誤輸出可以透過程式設計來更改,但是檢查頭部可能提供很多資訊。以下是一個簡單的程式碼範例:

程式碼解析

import urllib2
url2 = raw_input("Enter the URL: ")
http_r = urllib2.urlopen(url2)
print http_r.headers

內容解密:

  1. 匯入必要的模組:程式碼匯入了 urllib2 模組,用於URL相關的操作。
  2. 取得使用者輸入的URL:與前面的例子類別似,要求使用者輸入一個URL。
  3. 開啟URL並列印頭部資訊:使用 urllib2.urlopen(url2) 開啟URL,並將傳回的HTTP回應物件儲存在 http_r 中。然後,print http_r.headers 將HTTP回應的頭部資訊列印預出來。