Modbus Protokolü Açıklıklarının İstismar Edilmesi

Merhabalar Arkadaşlar,

Geçmiş yazılarımızda Kritik Altyapıların Siber Güvenliğinden ve EKS/SCADA Güvenliğinden bahsetmiştik. Yazılarımızda da EKS/SCADA ortamında yapılabilecek bir siber saldırı örneğini göstereceğimizi söylemiştik. Bugün EKS/SCADA protokollerinden biri olan Modbus protokolünün açıklıklarından faydalanarak bir PLC üzerine saldırı senaryosu gerçekleştireceğiz. Amacımız saldırıyı ve saldırgan davranışının nasıl işlediğini öğrenmek olduğu için saldırımızı bir PLC’yi simüle edecek olan ModbusPal simülatörünü kullanarak gerçekleştireceğiz. Saldırgan ise Kali Linux işletim sistemini kullanacak.

EKS/SCADA Güvenliği yazımızda EKS/SCADA sisteminde kullanılan protokollerden bahsetmiş ve bu protokollerin içinde Modbus’u da saymıştık. TCP/IP üzerinden yapılan iletişimde Modbus en çok kullanılan protokollerden biridir. Saldırıyı anlayabilmek için birazcık protokolü inceleyeceğiz. Malumunuz ağ (network) bilgisi olmadan siber güvenliği anlayabilmek pek mümkün değildir.

Alttaki şekilde görüldüğü üzere mesaj yapısı temel olarak bir fonksiyon kodu ve veriden oluşmaktadır. Buna Protokol Veri Birimi (Protocol Data Unit, PDU) adı verilir. Kullanılan Modbus protokolünün tipine göre (TCP/IP, seri hat, diğer) mesajın önüne ve arkasına ek birimler eklenebilir. Ek birimler eklenmiş haldeki mesaja ise Uygulama Veri Birimi (Application Data Unit, ADU) adı verilir.

Temel bir mesajlaşma şekli ise üstteki şekilde görüldüğü gibidir. Modbus protokolü Ana Cihaz/Bağımlı Cihaz (Master/Slave) yapısını kullandığından Ana Cihaz fonksiyon kodu ile beraber veri talebini gönderir Bağımlı Cihaz ise talebe uygun olarak cevabı gönderir ve Ana Cihaz cevabı alır. Burada kulağa sanki Ana Cihaz sunucuymuş gibi gelse de sanılanın aksine Ana Cihaz istemci (Client), Bağımlı Cihaz sunucu (server)’dur.

Fonksiyon kodu bağımlı cihaza (slave) hangi fonksiyonu gerçekleştirmesi gerektiğini belirtir. Bu fonksiyona ait hangi bilgilerin ne kadarlık bölümünün işleneceği ise data  bölümünde belirtilir. Modbus protokolünde ana cihaz (master), bağımlı cihaza (slave) aşağıdaki fonksiyonlardan herhangi birini içeren bir komut verdiğinde bağımlı cihaz (slave) hiçbir kimlik doğrulaması ya da yetki sorgulaması yapmadan bu komutu uygular. Çünkü EKS protokolleri tasarlanırken en önemli etken hızdır. Biz de işte bu açıklıktan faydalanacağız ve bağımlı cihaza, bir ana cihazmışız gibi komut göndereceğiz ve bağımlı cihazın talebimizi yerine getirip getirmediğini göreceğiz.

Aşağıda ise protokol içinde sık sık kullanılan ve bizim de saldırıda kullanacağımız fonksiyon kodları ve hangi görevi yerine getirdikleri verilmiştir. Ayrıca açıklamada bulunmayacağım çünkü tablo zaten yeterli.

Bir diğer bahsedeceğimiz husus Modbus protokolündeki veri yapısıdır. Modbus veri modeli, bir dizi ayırt edici özelliklere sahip tablosal bir yapıdan meydana gelir ve veriler bu dört tablo içerisinde saklanır. İlk iki satırdaki tablolar Dijital Girişler (Coil) ve Dijital Çıkışlar (Contact)  olarak adlandırılır. Tek bit saklayabilirler. Dijital Girişler (Coil) okuma/yazma yapabilirken, Dijital Çıkışlar (Contact) sadece okuma yapabilirler. Son iki satırdaki tablolar Giriş Kaydediciler (Input Registers) ve Saklayıcı Kaydediciler (Holding Registers) olarak adlandırılır. 16 bit (word) boyutunda veri saklayabilirler. Giriş Kaydediciler (Input Registers) sadece okuma yapabilirken, Saklayıcı Kaydediciler (Holding Registers) okuma/yazma yapabilirler.

Son olarak bizim Modbus TCP/IP’nin kullandığı paket yapısına göz atıp protokolle ilgili bilgilendirmemizi bitirelim.

Görüldüğü gibi Modbus TCP/IP uygulama veri birimi için protokol veri biriminin önüne MBAP (Modbus Application Protocol) başlığı eklenmiştir. Başlık toplamda 7 byte’dan oluşmaktadır ve sırasıyla şu alanları içerir;

İşlem Tanımlayıcı (Transaction Identifier, 2 Btye) : İstemci tarafından aynı TCP bağlantısı üzerinden bir önceki cevap beklenmeden birden fazla mesaj gönderildiği durumda bu tanımlama alanı işlem eşleştirmek için kullanılır. Sunucu bu bilgiyi istemcinin talebinden alarak cevaba kopyalar.

Protokol Tanımlayıcı (Protocol Identifier, 2 Btye): Modbus protokolü için bu değer 0’dır. İstemci tarafından tanımlanır ve sunucu bu bilgiyi talep içerisinden öğrenerek cevaba kopyalar.

Uzunluk (Lenght, 2 Btye): Uzunluk alt birimi mesajın devamındaki (birim tanımlayıcı da dâhil) veri uzunluğunu ifade eder. İstemci, bu değeri göndereceği talep için tanımladığı gibi sunucu da cevabı için tanımlar.

Birim Tanımlayıcı (Unit Identifier, 1 Btye): Modbus TCP ağı üzerindeki bir cihazla, Modbus seri hat üzerindeki bir bağımlı cihazı ağ geçidi kullanarak haberleştirmek için kullanılır. Modbus TCP sunucu uygulamasında bu değer 00 ya da FF şeklinde ayarlanır, sunucu tarafından önemsenmez ve cevaba aynı değer kopyalanır.

Protokolle ilgili vereceğimiz bilgiler bu kadar. Bu bilgilerin emin olun tamamı gerekli çünkü önemli olan saldırıyı yapmak değil altında yatan temel mantığı anlayabilmek. Ancak o zaman savunmayı da bilebilir ya da daha esnek saldırı teknikleri geliştirebiliriz. Önce şurada bulunan adresten ModbusPal simülatörümüzü indirebiliriz.

Çift tıklayarak açılabilir fakat ModbusPal bir java dosyası olduğu için komut satırından indirdiğimiz konuma gidip:

java -jar ModbusPal.jar

komutunu da çalıştırabiliriz.

ModbusPal’ı çalıştırmadan önce uygulama üzerinden Modbus Slaves -> Add seçeneği ile toplamda 247 adete kadar bağımlı cihaz (slave) ekleyebiliriz. Çünkü 1 ana cihaz en fazla 247 bağımlı cihazı yönetebilir. Aşağıda Add seçeneğini seçtikten sonra 1 adet bağımlı cihaz ekliyoruz ve A1 ismini veriyoruz. Daha sonra bu cihaz için 10 adet Holding Register ve 10 adet Coil değeri giriyoruz. Hatırlarsanız Coil’ler için sadece bit boyutunda veri girebilirken, Holding Registers için Word (2 Byte) boyutunda veri girebiliriz. Artık temsili PLC’mizde bazı değerler girildi. Biz bu değerleri önce okuyacağız sonra da manipüle edeceğiz. Unutmayın ki kritik altyapılarda kullanılan sistemlerde bu değerler suyun seviyesi ya da basıncı, motorun çalışması gereken hız ya da bir nükleer reaktör santrifüjünün dönüş hızı demek olabilir. Yani burada değiştirdiğimiz değerin gerçek dünyada mutlaka bir karşılığı olacak. İşte kritik altyapıları kritik yapan en önemli yer burası.

“Run” butonuna bastığımızda artık temsili PLC’miz 502. porttan yayın yapmaya başlar. Arzu ederseniz farklı protokollerin kullandığı farklı portlar için port numarasını elle değiştirebilirsiniz. ModbusPal simülatörünün, üzerinde çalıştığı bilgisayarın program çalışmadan önceki ve sonraki açık portlarını aşağıda paylaşıyorum. Dikkat ederseniz ilk fotoğrafta program çalışmadan önce 502. port kapalıydı.

nmap ile saldırgan 502 nolu portu açık olan bilgisayarları tarayarak aşağıdaki gibi Modbus çalıştıran cihaz(lar)ı bulur.

Artık hedef IP’yi bildiğimize göre sıra geldi istismar etmeye. Bunun için metasploiti kullanacağız. Bunun için komut satırını açarak

msfconsole

komutunu giriyoruz. Metasploit üzerinde bir çok açıklık için exploit kütüphanesi bulunduğu gibi bir de yardımcı/destekleyici ögeler diyebileceğimiz auxiliary kütüphanesi bulunur. Biz bu auxiliary kütüphanesinden Modbus Client’ı kullanacağız. Bunun için msfconsole’da;

msf > use auxiliary/scanner/scada/modbusclient

komutuyla ilgili modüle geçiş yapıyoruz. Dileyenler Modbus ile ilgili başka neler kullanabilirim diye bakmak için msfconsole’da;

msf > search modbus

komutuyla eriştikleri diğer auxiliary modülleriyle neler yapabileceklerine kendileri göz gezdirebilirler. Kaldığımız yerden devam edelim. Artık Modbus Client modülündeyiz.

msf auxiliary(modbusclient) > show actions 

msf auxiliary(modbusclient) > show options 

komutlarını kullanarak modülü nasıl kullanacağımızı ve belirlememiz gereken parametreleri öğrenebiliriz. show actions komutunu verdiğimizde gördüğümüz seçenekler yukarıda bahsettiğimiz fonksiyon kodlarında belirtilen fonksiyonlardır. Şimdi artık yapmamız gereken gerekli parametreleri girmek. Önce Coil değerlerini okuyalım. Bunun için set action READ_COILS komutunu veriyoruz ve daha sonra başlangıç adresi olarak 0, okunacak veri sayısını 10 ve hedef adres olarak da daha önceden tespit ettiğimiz 192.168.1.26 IP adresini veriyoruz. Biz örnek olması açısından 1’den 10’a kadar değer girdiğimiz için ilk 10 adresi okumayı deniyoruz. Ama DATA_ADDRESS ve NUMBER seçenekleri ile istediğimiz adresten başlayarak istediğimiz sayı kadar veriyi okuyabiliriz.

Gördüğümüz gibi PLC’ye yetkil kullanıcı tarafından girilen değerler, saldırgan tarafından rahatlıkla görüntülenebildi. Şimdi de aynı işlemi Holding Registers için yapalım.

Girilen tüm Holding Register değerleri de saldırgan tarafından rahatça okundu. Sıra geldi bu değerleri değiştirmeye. Aşağıda WRITE_REGISTER fonksiyonu ile herhangi belirlenen adrese herhangi bir datanın yazılması gösterilmiştir. Örnek olarak 75 sayısını 4. adrese yazacağız. Bu işlem bir PLC’ye ait bir alana basit bir yazma işlem gibi görünebilir. Ancak yapılan değişiklik, EKS üzerinde ya da fiziksel sistem üzerinde bir değişiklik yaratacak ve sistemin istenmeyen biçimde çalışmasına sebep olacaktır. Bu, bazen büyük maddi kayıplara bazen de yaralanmalara hatta can kaybına dahi sebep olabilir. O yüzden bu gibi testleri kesinlikle ve kesinlikle canlı sistem üzerinde YAPMAYINIZ!

Yazma işlemini de gerçekleştirdik, dilerseniz işlemi yaptıktan sonra ModbusPal üzerinde 5. adrese (Modbus Client modülünde indeks 0’dan başlarken, ModbusPal’de indeks 1’den başlar) 75 sayısının yazıldığını görebiliriz. Böylece Modbus protokolünde bir kimlik doğrulama (authentication) ve yetkilendirme (authorization) mekanizmaları olmadığını görmüş olduk. Fakat protokolün zaafiyetleri bunlarla bitmiyor. Haberleşme aynı zamanda açık metin (clear text) sağlandığı için ortadaki adam saldırısı ile hattı dinleyen bir kişi yapılan işlemler ve verilen cevapları görebilir, veriyi ele geçirebilir ve hatta isterse veriyi değiştirerek gönderebilir. Aşağıdaki Wirehark görüntüsünde de en son yaptığımız işlemin yani bir Register’a yeni bir değer girilmesi işlemini görüntüleyebiliyoruz. Hatırlarsanız bu işleme ait fonksiyon kodu 6’ydı, verinin yazılacağı adres 4’tü ve verimiz de 75’ti yani hexadecimal düzende 4b. Bu bilgilerin hepsini aşağıdaki paket bilgilerinde görüntüleyebiliyoruz. Ayrıca Modbus/TCP’nin başına eklenen MBAP Header’a ait bilgiler de yine pakette mevcut.

Sorularınız varsa yazının altına yorum olarak bırakabilirsiniz. Bir başka yazıda görüşmek üzere…

Bilgi Sitemleri Planlama ve Yönetimi, Ağ Yöneticisi, CCNA R&S, Siber Güvenlik İlgilisi ve Araştırmacısı.