在工業控制系統(ICS)網路中,對通訊協定的深層理解是實現資產管理與安全防禦的基石。Ethernet/IP作為主流工業乙太網協議,其基於通用工業協定(CIP)的物件導向特性,為設備提供了豐富的自我描述能力。本文聚焦於CIP中最基礎的「身份物件」,透過模擬一個Ethernet/IP伺服器,重現設備在網路上的行為特徵,並掌握入侵偵測系統如何利用這些資訊進行資產識別。此過程也揭示了攻擊者如何反向利用公開資訊進行偵察,或研究人員如何建構蜜罐。本分析將從虛擬環境建構延伸至實體PLC互動,完整展示從理論分析到實際應用的方法論,為工控安全研究提供具體指引。

Ethernet/IP伺服器建構與身份物件分析

玄貓認為,深入理解Ethernet/IP協議的身份物件及其屬性,對於資產識別和潛在漏洞偵測至關重要。本節將引導您建構一個Ethernet/IP伺服器,並透過Wireshark分析其通訊,揭示身份物件的細節。

身份物件的重要性:

Ethernet/IP協議透過身份CIP物件接收並傳遞設備的屬性。玄貓專注於此特定物件有幾個原因:

  1. IDS資產偵測基礎:所有入侵偵測系統(IDS)供應商通常都從這個協議和特定的封包開始,以建立其資產偵測引擎。
  2. 蜜罐模擬:一旦我們理解了它的構成方式,就能夠將其複製為蜜罐(Honey Pot),用於誘捕攻擊者。

為了闡釋Ethernet/IP的運作原理,我們將使用在第一章「使用」中安裝的cpppo套件,並從身份物件開始。

建構Ethernet/IP伺服器:

1. 安裝cpppo套件:

確保您的PLC虛擬機已安裝cpppo套件:

pip3 install cpppo
2. 建立enip資料夾與cpppo.cfg設定檔:
  • 在您的Documents資料夾中建立一個名為enip的資料夾。
  • 在此enip資料夾內建立一個名為cpppo.cfg的新檔案,並將以下設定內容放入其中。這些內容定義了身份物件的屬性,您可以根據需要自訂,但目前我們將使用預設設定來運行範例:
[Identity]
# Generally, strings are not quoted
Vendor ID = 1
Device Type = 14
Product Code Number = 51
Product Revision = 16
Status Word = 12656
Serial Number = 1360281
Product Name = 1756-L55/A 1756-M12/A LOGIX5555
State = 255

[TCPIP]
# However, some complex structures require JSON configuration:
Interface Configuration = {
"ip_address": "192.168.1.30",
"network_mask": "255.255.255.0",
"dns_primary": "8.8.8.8",
"dns_secondary": "8.8.4.4",
"domain_name": "industrial.pentest.lab"
}
Host Name = controller
3. 運行Ethernet/IP伺服器:

設定並儲存檔案後,執行以下命令:

python3 -m cpppo.server.enip -v -a 0.0.0.0

如果一切順利,您將看到伺服器啟動並顯示相關日誌。

此圖示:Ethernet/IP伺服器建構流程

@startuml
!define DISABLE_LINK
!define PLANTUML_FORMAT svg
!theme _none_

skinparam dpi auto
skinparam shadowing false
skinparam linetype ortho
skinparam roundcorner 5
skinparam defaultFontName "Microsoft JhengHei UI"
skinparam defaultFontSize 16
skinparam minClassWidth 100

actor "攻擊者 (玄貓)" as attacker
rectangle "PLC 虛擬機" as plc_vm {
component "Python 環境" as python_env
folder "Documents/enip" as enip_folder {
file "cpppo.cfg" as config_file
}
component "cpppo 套件" as cpppo_lib
component "Ethernet/IP 伺服器" as enip_server
}

attacker --> plc_vm : 安裝 `cpppo`
attacker --> enip_folder : 建立 `enip` 資料夾
attacker --> config_file : 建立並配置 `cpppo.cfg`
attacker --> plc_vm : 執行 `python3 -m cpppo.server.enip -v -a 0.0.0.0`

config_file --> cpppo_lib : 載入配置
cpppo_lib --> enip_server : 初始化 Ethernet/IP 伺服器
enip_server --> enip_server : 設定身份物件屬性
enip_server --> enip_server : 設定 TCP/IP 介面
enip_server --> enip_server : 監聽 0.0.0.0

note right of enip_server
伺服器已啟動,等待客戶端連接
end note

@enduml

看圖說話:

此圖示展示了Ethernet/IP伺服器的建構流程攻擊者(玄貓)首先在PLC虛擬機上安裝cpppo套件,並在Documents資料夾內建立enip資料夾,然後在其中建立並配置cpppo.cfg設定檔。這個設定檔定義了伺服器的身份物件屬性TCP/IP介面配置。隨後,玄貓執行Python命令來啟動Ethernet/IP伺服器cpppo套件會載入配置檔,並根據其中的設定初始化伺服器,使其監聽0.0.0.0,等待客戶端的連接。這個流程詳細說明了如何利用cpppo套件在Python環境中快速建構一個Ethernet/IP伺服器,為後續的協議互動和分析奠定基礎。

查詢Ethernet/IP伺服器:

現在,我們在PLC虛擬機上運行了一個Ethernet/IP伺服器。開啟一個SCADA虛擬機的會話,並輸入以下命令:

python3 -m cpppo.server.enip.poll -v TCPIP Identity -a 192.168.1.10

如果一切設定和通訊正常,您將看到伺服器回應的身份物件資訊。

Wireshark分析Ethernet/IP通訊:

現在,在Kali或Windows虛擬機中啟動Wireshark。像在Modbus部分一樣,我們希望監聽通訊。確保SCADA虛擬機仍在輪詢PLC虛擬機,您應該會看到以下輸出:

1. 捕獲身份物件封包:

在Wireshark中,您將看到捕獲到的Ethernet/IP封包,其中包含身份物件的資訊。

  • 展開「成功:身份:獲取所有屬性」(Success: Identity: Get Attributes All)的封包。
  • 您會看到CIP層次後面的「服務:獲取所有屬性(回應)」(Service: Get Attributes All (Response))。
2. 檢視身份物件詳細資訊:

展開此服務後,您將看到我們在PLC虛擬機的Documents/enip/cpppo.cfg檔案中設定的詳細資訊。將其與您的設定檔進行比較。您可以嘗試更改一些選項並重新啟動Ethernet/IP伺服器,以觀察其變化。

身份物件的價值:

玄貓認為,這個物件包含了識別控制器的所有必要資訊。這就是為什麼IDS供應商通常從這個協議開始,因為識別網路上的資產是一個簡單的勝利。透過Wireshark或tcpdump(如第五章「SPANs」所述),我們可以發現潛在的目標,並確定它們是否包含任何已知的漏洞,從而使我們能夠更深入地滲透到環境中。

Koyo CLICK PLC的Ethernet/IP設定:

接下來,我們將啟用實驗室中Koyo CLICK PLC上的Ethernet/IP適配器。然後,我們將使用cpppo工具探測我們的PLC。

啟用Koyo CLICK PLC的Ethernet/IP:

按照以下簡短步驟開始:

  1. 啟動CLICK編程軟體。
  2. 點擊「連接到PLC」按鈕。
  3. 點擊「連接」以連接到IP位址為192.168.1.20的PLC。
  4. 從PLC選項中讀取專案後,點擊「確定」按鈕。

這些步驟是為了將我們帶到Ethernet/IP配置的起點,是對前面章節的簡要回顧。

Koyo CLICK PLC的Ethernet/IP設定與通訊分析

玄貓認為,將理論知識應用於實體設備,並透過網路工具進行驗證,是掌握工業控制系統互動的關鍵。本節將引導您設定Koyo CLICK PLC的Ethernet/IP適配器,並使用cpppo工具探測其身份,同時透過Wireshark分析通訊流量。

設定Koyo CLICK PLC的Ethernet/IP適配器:

1. 進入Ethernet/IP設定介面:
  • 啟動CLICK編程軟體,並連接到您的Koyo CLICK PLC。
  • 在菜單中選擇「設定」(Setup)。
  • 點擊「EtherNet/IP 設定…」(EtherNet/IP Setup…)選項,開啟EtherNet/IP設定視窗。
2. 啟用EtherNet/IP適配器:
  • 在視窗中勾選「啟用EtherNet/IP適配器」(Enable EtherNet/IP Adapter)選項。這將允許您修改和選擇視窗中的選項。
  • 您會注意到可以更改連接數、埠號和超時設定。暫時保持這些設定不變,我們將專注於「輸入(到掃描器)」數據塊。
3. 設定輸入數據塊(Input Data Blocks):
  • Ethernet/IP主站能夠讀取輸入數據塊。
  • 在「開始」(Start)欄位中選擇block1,然後點擊按鈕開啟「位址選擇器」(Address Picker)視窗。
  • 使用左側的「XD」按鈕過濾掉不需要的位址。
  • 為第一個數據塊的起始位址選擇XD0,結束位址選擇XD8
4. 設定輸出數據塊(Output Data Blocks):
  • 接下來,我們將對「輸出(來自掃描器)」數據塊進行相同的設定,但這次我們將使用「YD」位址作為起始和結束位址。
  • 完成位址設定後,您的配置應符合預期。
5. 將專案寫入PLC:
  • 完成設定後,將您的專案寫入Koyo CLICK PLC。

探測Koyo CLICK PLC的Ethernet/IP身份:

回到SCADA虛擬機的終端機視窗,我們將執行以下命令來探測Koyo CLICK PLC的Ethernet/IP身份:

python3 -m cpppo.server.enip.list_services -vv -a 192.168.1.20 --list-identity

如果一切連接和操作正常,您將看到一長串數據流,顯示Koyo CLICK PLC的Ethernet/IP身份資訊。

Wireshark分析Koyo CLICK PLC的Ethernet/IP通訊:

現在,開啟Wireshark並重新運行上述命令,再次分析流量。

1. 捕獲與分析:
  • 由於通訊是從ESXi伺服器流向實體PLC介面,您需要使用我們在第五章「SPANs」中設定的SPAN埠來捕獲上述通訊。
  • 在Wireshark中,您將看到捕獲到的Ethernet/IP封包,其中包含了Koyo CLICK PLC的身份資訊。

玄貓認為,能夠監聽流量並查詢PLC的身份固然有趣,但更重要的是如何改變數值、開啟和關閉燈號、閥門等實際操作。

Ethernet/IP的Get/Set屬性請求與非連接式顯式訊息:

接下來,我們將回到PLC虛擬機,並透過命令列更新來測試我們的Get/Set屬性請求

非連接式顯式訊息(Unconnected Explicit Messages):

在設定之前,玄貓需要快速解釋我們將如何與虛擬Ethernet/IP PLC通訊並發送訊息。我們將使用非連接式顯式訊息。這意味著我們不需要建立預先連接,也不需要預留資源來維持通訊。我們可以發送臨時(ad hoc)通訊,讓PLC透過非連接式顯式訊息消化和處理命令。

顯式訊息使用Lpacket格式,其中包含以下服務欄位:

  • 服務碼(Service Code):指定要執行的操作(例如,獲取屬性、設定屬性)。
  • 類別ID(Class ID):指定目標物件的類別。
  • 實例ID(Instance ID):指定目標物件的特定實例。
  • 屬性ID(Attribute ID):指定目標屬性的ID。
類別、實例與屬性ID:

目前為止,我們只討論了類別0x01(身份類別)。玄貓曾指出存在應用特定物件ID,它們最終也是類別ID。儘管有許多公開建立的類別ID,但由於協議的開放性,用戶可以利用100到199之間的自訂範圍

  • 實例ID(Instance IDs):如果您有多個相同類別的實例,實例ID有助於區分不同的訊息。
  • 屬性ID(Attribute IDs):與實例ID類似,屬性ID允許您區分單個實例的多個特性。

此圖示:Koyo CLICK Ethernet/IP設定與通訊流程

@startuml
!define DISABLE_LINK
!define PLANTUML_FORMAT svg
!theme _none_

skinparam dpi auto
skinparam shadowing false
skinparam linetype ortho
skinparam roundcorner 5
skinparam defaultFontName "Microsoft JhengHei UI"
skinparam defaultFontSize 16
skinparam minClassWidth 100

actor "攻擊者 (玄貓)" as attacker
rectangle "Koyo CLICK PLC" as koyo_plc {
component "CLICK 編程軟體" as click_software
component "EtherNet/IP 適配器" as enip_adapter
database "PLC 數據塊" as plc_data_blocks
}
rectangle "SCADA 虛擬機" as scada_vm {
component "cpppo 客戶端" as cpppo_client
}
cloud "網路" as network {
component "ESXi vSwitch / SPAN 埠" as span_port
}
rectangle "分析工作站" as analysis_ws {
component "Wireshark" as wireshark
}

attacker --> click_software : 連接 PLC
click_software --> enip_adapter : 啟用 EtherNet/IP 適配器
enip_adapter --> plc_data_blocks : 設定輸入 (XD0-XD8)
enip_adapter --> plc_data_blocks : 設定輸出 (YD0-YD8)
click_software --> koyo_plc : 將專案寫入 PLC

attacker --> cpppo_client : 執行 `cpppo.server.enip.list_services ...`
cpppo_client --> network : 發送 EtherNet/IP 身份查詢
network --> enip_adapter : 接收查詢
enip_adapter --> network : 回應身份資訊
network --> cpppo_client : 接收回應

network --> span_port : 流量鏡像
span_port --> wireshark : 捕獲 EtherNet/IP 流量

note right of enip_adapter
處理非連接式顯式訊息
包含服務碼、類別ID、實例ID、屬性ID
end note

@enduml

看圖說話:

此圖示詳細展示了Koyo CLICK PLC的Ethernet/IP設定與通訊分析流程。首先,攻擊者(玄貓)透過CLICK編程軟體連接到Koyo CLICK PLC,啟用其EtherNet/IP適配器,並設定輸入(XD0-XD8)和輸出(YD0-YD8)數據塊,然後將專案寫入PLC。隨後,玄貓在SCADA虛擬機上使用cpppo客戶端發送EtherNet/IP身份查詢請求給PLC。這些通訊流量會經過網路,並透過ESXi vSwitch的SPAN埠Wireshark捕獲並分析。圖中特別指出,EtherNet/IP適配器處理的是非連接式顯式訊息,這些訊息包含了服務碼、類別ID、實例ID和屬性ID等關鍵欄位,這些欄位對於理解EtherNet/IP的物件導向通訊機制至關重要。這個流程不僅展示了實體PLC的配置,也強調了透過cpppo和Wireshark進行深入分析的重要性。

解構Ethernet/IP協議的關鍵元素後可以發現,從虛擬伺服器建構到實體設備探測的完整流程,已揭示其核心運作邏輯與資安價值。本文的精髓不僅在於工具操作,更在於思維模式的突破:從被動接收廠商定義的資產樣貌,轉為主動解構「身份物件」等原子單位。這種從「黑箱」到「白箱」的分析能力,是突破傳統資安工具限制、識別客製化威脅或設計高仿真蜜罐的關鍵,它整合了理論模擬與實務驗證,形成一套可複製的深度洞察方法。

展望未來,IT與OT安防技術的融合將持續深化。掌握底層協議的分析與模擬能力,是評估新型態攻擊路徑、建構更具韌性防禦體系的基石。

玄貓認為,對於追求卓越的技術領袖而言,從協議的原子單位著手進行剖析,不僅是技能的精進,更是從根本上建立全面數位資產掌控權與資安視野的必要修養。