Posted on December 19th, 2014
back

Son zamanlarda giderek SCADA zafiyetlerin daha da artması her ne kadar çok büyük bir tehlike arz ediyor olsa da hâlâ yazılımcılar tarafından yeterince önemsenmiyor. Stuxnet (Merak etmeyin, ismi sadece bir kez geçecek yazıda.) ve Duqu zararlılarının etkileri hâlâ daha etkisini sürdürmekte. Hâl böyle olunca biz de SignalSEC ekibi olarak yazılımcıların tehlikeyi kavrayabilmesi adına Siemens SCADA yazılımı üzerindeki CVE-2012-2598 kodlu iki güvenlik açığının nasıl exploit edilebildiğini göstermeye karar verdik.

Zafiyet 1 : Directory Traversal

Siemens SCADA yazılımının bir parçası olan CCDiagAgent programı, bu yazıda göreceğimiz iki zayıflığın kaynağı. Öncelikle basit olandan başlayalım, diğer zafiyet için SafeSEH ile uğraşmamız gerekecek fakat biz klasik SafeSEH Bypass yöntemleri yerine kendi bulduğumuz bir yöntemi kullanacağız. Çünkü klasik yöntemler ile burada bir bypass başarılı olmuyor. Devam edelim. Öncelikle programı çalıştırıp TcpView ile dinlenen port numaralarına baktığımızda programımızın 80 numaralı portu dinlediğini, yani buradan gelecek olan istekleri işleyeceğini görüyoruz.

siemens1

Aşağıdaki python scripti kullanarak http portuna içerisinde hafızada arayıp bulabileceğimiz karakterler içeren basit bir paket gönderiyoruz.

#SignalSEC Corp. - 2014
import struct
from socket import *
host = "192.168.20.141"
port = 80
adres = (host,port)
Baglanti = socket(AF_INET,SOCK_STREAM)
Baglanti.connect(adres)
icerik = "A" * 30
mesaj = "GET /"+ icerik +" HTTP/1.0\r\n\r\n"
Baglanti.send(mesaj)
print Baglanti.recv(4096)

Program içerisinde 30 A karakteri bulunan bir GET isteği yapıyor. İsteği yaptıktan sonra WinDbg ile kodu takip edip, gönderdiğimiz içeriğin nasıl işlendiği inceliyoruz. Sonuç olarak aşağıda görüleceği üzere program gönderdiğimiz içeriği C:\Program Files\Siemens\WinCC\WinCCScope\ScopePages klasörü altında bir dosya olarak algılayıp, onun içeriğini bize vermeye çalışıyor.

siemens2
Bu durum dizinler arasında “../” aracılığı ile gezinerek istediğimiz dosyayı okuyabileceğimiz “Directory Traversal” zafiyetine sebep oluyor. Bu zafiyeti sömürebilmek için son olarak Python kodumuzdaki “içerik” kısmını ../../../../../Windows/system32/drivers/etc/hosts olarak düzenleyip tekrar çalıştırdığımızda Windows’un hosts dosyasının içeriğini aşağıda görüldüğü üzere elde edebiliyoruz.

directory-traversal-winncc

Zafiyet 2 : Buffer Overflow & SafeSEH Bypass

İkinci olarak ilk zafiyetin keşfi sırasında kullandığımız dosyada 30 karakter yerine 5000 karakter ile bir HEAD isteği gönderiyoruz. Programa baktığımızda çökme gerçekleşiyor, WinDbg ile kontrol ediyoruz.

siemens4

Görüldüğü üzere 0040c1ef adresindeki mov işlemi sırasında çökme meydana geliyor.  Çökmenin ,  esas sebebi ise uygulamaya gelen HTTP isteklerinin kontrolsüz bir şekilde wsprintfA fonksiyonuna argüman olarak verilmesi;

wsprintf-wincc

Yazmaçlara baktığımızda EAX yazmacı üzere yazabildiğimizi görüyoruz. !exchain komutu ile SEH’in durumuna bakarsak, SEH üzerine de yazabildiğimiz görüyoruz. Bu aşamadan sonra klasik SEH tabanlı zafiyet exploiti yazarak çalışabilen bir exploit geliştirebilirsiniz. Tabi eğer SafeSEH  koruması aktif  olmasaydı. Ekip olarak SafeSEH’i geçmek için denediğimiz yöntemler başarısız oldu. İlk olarak gerekli olan pop pop ret üçlüsünü SafeSEH off olan bir dosyada aramayı denedik, fakat aşağıda görebileceğiniz üzere bütün dosyalarda SafeSEH koruması aktif durumdaydı.

siemens5

Ardından gereken pop pop ret üçlüsünü bir sistem dosyasında aramayı denedik. Fakat ne yazık ki HTTP isteği gönderdiğimiz için adreslerin içerisinde bulunan “00” karakteri sonlandırıcı kötü karakter (bad char) olduğu için hafızaya yazmayı yarıda kesiyordu, bu sebeple bu yöntem de başarılı olamadı. Ardından bilinen diğer bir SafeSEH bypass yöntemini denedik. Fakat burada da karşımıza yine kötü karakter (bad char) sorunu çıktı. İhtiyacımız olan call dword ptr[esp+nn] ve türevleri instructionların bulunduğu hafıza adreslerin hepsi HTTP protokolünde kötü karakter olan 00, 20, 3d, 3f, 0a, 0d   bytelarından birini içermekteydi. Zafiyetin HTTP  üzerinden tetiklenmesi gerçekten de bizi oldukça kısıtlıyordu.  Bypass için hafızaya yazılması gereken adresleri hafızaya yazamıyorduk. Bir süre hafızada gözden kaçırmış olabileceğimiz bir adres olduğunu düşünerek aramaya devam ettik fakat bir sonuç çıkmadı.

Üç günlük bir AR-GE ve TeamViewer ile saatlerce yapılan ekip çalışmasının ardından SafeSEH’i  keşfettiğimiz başka bir yöntemle bypass edip, exploitimizi başarıyla yazabildik.  Bu yöntemi ve exploiti şu an için paylaşmayı düşünmüyoruz. Ancak zaman zaman exploit geliştiriciler tarafından sıkça kullanılan ve “application specific” bir exploiting yöntemi diyebiliriz. Aşağıda exploitimizin videosunu görebilirsiniz;

Yazar: Bekir Karul, Celil Ünüver