Modbus TCP paketindeki 'Force Single Coil' isteği (Function Code 05) fiziksel dünyada bir vananın kapanması, bir motorun durması veya bir soğutma sisteminin devre dışı kalması demektir; ağ trafiğinde bu ham hex kodunu gördüğünde, eğer bu planlı bir bakım değilse, fiziksel felakete giden yolda geri sayım başlamış demektir.
Endüstriyel Kontrol Sistemleri (ICS) ve Operasyonel Teknoloji (OT) dünyası, klasik IT dünyasından çok farklı kurallarla oynuyor. Biz IT tarafında 'Confidentiality' (Gizlilik) derken, OT tarafındaki dostlarımız 'Availability' (Erişilebilirlik) ve 'Safety' (Güvenlik/Emniyet) için uykularından vazgeçiyor. Bir database sunucusuna yama yaparken 'reboot' etmek can sıkar ama bir PLC'yi (Programmable Logic Controller) reboot etmek, hattaki 10 milyon dolarlık üretimin çöpe gitmesi veya daha kötüsü, bir patlama riskidir.
Protokollerin Masumiyeti ve Kimliksizlik Sorunu
OT dünyasında kullanılan protokollerin (Modbus, Profinet, EtherNet/IP, BACnet) çoğu 70'li ve 80'li yıllarda tasarlandı. O zamanlar 'güvenlik' denilince akla sadece fiziksel çitler ve kilitli kapılar geliyordu. Bu yüzden bu protokollerin ezici çoğunluğunda 'authentication' (kimlik doğrulama) diye bir kavram yok.
Eğer bir saldırgan olarak testCompany içindeki OT ağına sızdıysan ve PLC'ye erişebiliyorsan, ona 'dur' demen için bir şifreye ihtiyacın yok. Sadece doğru paketi, doğru adrese göndermen yeterli.
Örneğin, standart bir Modbus TCP paket yapısına bakalım (Zararsızlaştırılmış/Defanged):
# Modbus TCP Header (MBAP)
Transaction ID: 0x0001
Protocol ID: 0x0000
Length: 0x0006
Unit ID: 0x01
# Modbus PDU
Function Code: 0x05 (Write Single Coil)
Reference Number: 0x0010 (Vana Adresi)
Data: 0xFF00 (ON/Kapat)
Bu paketi 127.0.0.1 (lokal simülasyon) üzerindeki bir PLC'ye gönderdiğinde, PLC sorgusuz sualsiz o vanayı kapatır. İşte bu yüzden OT ağında segmentasyon 'olsa iyi olur' değil, 'olmazsa olmaz'dır.
Purdue Modeli Sadece Kağıt Üzerinde mi Kaldı?
Segmentasyon denilince hepimizin aklına Purdue Modeli gelir. Seviye 0'dan (fiziksel sensörler) Seviye 5'e (kurumsal ağ) kadar uzanan o meşhur piramit. Ancak sahada gördüğümüz manzara genelde 'Flat Network' faciası oluyor. Muhasebedeki bir bilgisayarın, üretim bandındaki PLC'ye ping atabildiği bir dünyada 'Air-gap' (hava boşluğu) bir efsaneden ibarettir.
Gerçek bir sızma testinde (Red Team operasyonunda), OT ağına girmek için genelde kurumsal ağdaki bir zafiyet kullanılır. Çift NIC (Network Interface Card) barındıran bir mühendislik istasyonu (Engineering Station) saldırgan için altın değerindedir. Bir ayağı kurumsal ağda, diğer ayağı üretim ağında olan bu makineler, bizim için en verimli köprülerdir.
Keşif: Nmap ile PLC Patlatmak
IT ağında nmap -A -T4 çalıştırmak standart bir işlemdir. Ama OT ağında bunu yaparsan, o çok hassas olan eski nesil PLC'lerin TCP stack'ini kilitleyebilir ve üretimi durdurabilirsin. Sahadaki mühendis seni elinde bir anahtarla kovalamadan önce şunu öğrenmelisin: OT dünyasında 'Active Scanning' tehlikelidir. Biz genelde 'Passive Listening' (Ağı dinleme) yöntemini tercih ederiz.
Eğer illa bir tarama yapılacaksa, protokol spesifik scriptler kullanılmalıdır. Örneğin, Modbus cihazlarını tespit etmek için çok daha 'narin' bir yaklaşım gerekir:
# Sadece 502 portuna yönelik, cihaz bilgisini çeken narin bir tarama
nmap -p 502 --script modbus-discover 127.0.0.1
Scapy ile OT Trafiği Manipülasyonu
Bir Red Teamer olarak, bazen hazır araçlar yetmez. Kendi paketini manipüle etmen gerekir. Python ve Scapy burada devreye giriyor. Aşağıdaki pseudo-kod, bir PLC'nin register değerini okumak için nasıl bir paket oluşturulabileceğini gösteriyor (Eğitim amaçlıdır):
from scapy.all import *
# Defanged Modbus Request
def send_fake_modbus_query(target_ip):
# MBAP Header + Function Code 03 (Read Holding Registers)
# Unit ID: 1, Start Addr: 0, Quantity: 10
packet = IP(dst=target_ip)/TCP(dport=502)/Raw(load="\x00\x01\x00\x00\x00\x06\x01\x03\x00\x00\x00\x0a")
print(f"[*] Sending packet to {target_ip}...")
response = sr1(packet, timeout=2, verbose=0)
if response:
print("[+] Response received!")
# Burada dönen hex verisi analiz edilerek sensör değerleri okunabilir
else:
print("[-] No response.")
# send_fake_modbus_query("127.0.0.1")
Defans Hattı: Ne Yapmalı?
"Sedat, hep saldırıyı anlattın, peki nasıl korunacağız?" dediğini duyar gibiyim. OT güvenliği IT güvenliğine benzemez ama temel prensipler aynıdır:
- Görünürlük (Visibility): Ağında ne olduğunu bilmediğin şeyi koruyamazsın. Hangi PLC, hangi firmware sürümüyle, hangi protokolü konuşuyor? Bunların envanteri çıkarılmalı.
- DPI (Deep Packet Inspection): Standart firewall'lar sadece IP ve Port'a bakar. OT dünyasında bize 'Protokolü anlayan' firewall'lar lazım. "Bu IP, bu PLC'ye 502 portundan gelebilir ama sadece 'Read' yapabilir, 'Write' yapamaz" diyebilmelisin.
- IDS/IPS Kuralları: Olağandışı trafikleri yakalamak için Snort veya Suricata gibi araçlara OT imzaları eklenmeli. Örneğin, mesai saatleri dışında gelen bir 'Stop CPU' komutu anında alarm üretmeli.
Örnek bir Suricata kuralı (Pseudo):
alert tcp any any -> any 502 (msg:"KRİTİK: Modbus Write Single Coil Tespit Edildi!"; content:"|05|"; offset:7; depth:1; sid:1000001; rev:1;)
Sonuç Niyetine Değil, Tecrübe Niyetine
OT güvenliği, sadece siber güvenlikçilerin değil, elektrik-elektronik ve makine mühendislerinin de ortak paydası olmak zorunda. Bir sızma testi sırasında testCompany fabrikasında yanlışlıkla bir fırının derecesini değiştirdiğinde, bunun sadece bir 'ekran görüntüsü' olmadığını, gerçek hayatta birilerinin zarar görebileceğini unutma.
Siber güvenlik burada sadece 'hack' değil, bir can güvenliği meselesidir. Bir dahaki sefere bir PLC panosu gördüğünde ona sadece bir bilgisayar olarak değil, fiziksel dünyanın işletim sistemi olarak bak.
Stay safe, stay geek.
