Meltdown ve Spectre: Sahte güvenlik duygusu

Deniz İrgin
Codefiction
Published in
14 min readJan 23, 2018

2 Ocak 2018’de modern işlemcilerde güvenlik açıkları olduğu haberi sızdı ve yazılım endüstrisinin gündemine bomba gibi düştü. Sonrasında bu güvenlik açığının 2017 yılının ortalarında Google Project Zero ekibi tarafından tespit edilip, bu açıkların Intel, AMD ve ARM üreticilerine bildirildiğini öğrendik. Daha da kötüsü bu güvenlik açıklarından Meltdown’un 1995 yılından bu yana üretilen çoğu Intel işlemcisinde ve bazı ARM (Mobil cihazlar) işlemcilerde de olduğu ortaya çıktı.

Yazılım endüstrisinin tarihine baktığımızda büyük güvenlik açıkları yeni bir şey değil. Daha önce dünya çapında yaygın kullanılan işletim sistemlerinde ve çeşitli yazılımlarda da ciddi güvenlik açıkları ortaya çıkmıştı. Ama gerek işletim sistemlerine gerekse yazılımlara çıkartılan yamalarla bu açıklar kapatılabiliyordu.

Fakat Meltdown ve Spectre oldukça farklı. Bu sefer güvenlik açığı yazılımsal değil donanımsal. Her ne kadar işletim sistemlerine geçtiğimiz haftalarda bu açıkları kapatmak amacıyla çeşitli güvenlik yamaları çıkmış olsa da, bu yamaların bazıları sorunlu bazıları eski işlemcilerde sorunlara sebep olabiliyor ve en önemlisi bu yamalar işe yarasalar bile, işlemcilerde %5–%30 arası performans kaybına sebep olabiliyor.

Meltdown ve Spectre nedir sorusuna cevap vermeden önce bir kaç teknik detayı anlatmakta fayda var ama özetlemek gerekirse;
Siber suçluların ve ya kötü niyetli kişilerin bilgisayarınızdan, mobil cihazlarınızdan hatta cloud’daki sanal makinalarınızdan istedikleri bilgileri almalarına imkan sağlayan, donanımsal seviyede bir güvenlik açığı. Bu iki güvenlik açığı da modern işlemcilerde kullanılan Speculative Execution adı verilen bir optimizasyon tekniğinin sebep olduğu, bu güne kadar ön görülmemiş bir zaafiyetten yararlanıyor.

Bunlardan Spectre : Intel, AMD ve ARM işlemcileri, Meltdown ise Intel ve bazı ARM işlemcilerini etkiliyor.

Konunun teknik detaylarına girmeden önce birkaç konu hakkında bilgi vermek istiyorum. Böylece Meltdown ve Spectre açıklarının nasıl çalıştığı daha kolay anlaşılacaktır. Bunlar Side-Channel Attack, Kernel, Virtual Memory ve Memory Isolation, CPU Cache ve Speculative Execution.

Bu kavramlara hakimseniz direkt Meltdown ve Spectre’ın açıklandığı kısımlara atlayabilirsiniz.

Side-Channel Attack

Bilgisiyarlardan farkında olmadan sızan bilgilere dayanan, cryptanalytic teknikler (kriptoanaliz) yardımıyla gizli bilgiyi ortaya çıkarmayı amaçlayan bir saldırı türüdür. Bu tarz saldırılarda ağırlıklı olarak analiz edilen fiziksel nitelikler; power consumption (enerji tüketimi), Timing information (zamanlama), electromagnetic leaks (elektromanyetik dalganma).

Bir çok side-channel saldırı tipi var ama konumuzla alakalı olan timing attack.

Bir örnek üzerinden anlatmakta yarar var. Diyelim ki bir bilgisayar sistemine authenticate olmak isteniliyor. Sistem doğru şifreyi biliyor ve bu örnekte şifrenin codefiction olduğunu farz edelim. Saldırgan şifreyi tahmin etmeye başlıyor ve ;
a harfini deniyor ve red yanıtını alıyor.
b harfini deniyor ve red yanıtını alıyor.
c harfini deniyor ve red yanıtını alıyor.

Ama c harfini denediği zaman red yanıtını alması daha uzun sürüyor. Çünkü bilgisayar karşılaştırmayı yaparken şifrenin ilk harfi olan c nin eşleştiğini tespit ediyor ama şifrenin geri kalanı kontrol etmeye çalıştığında red dönüyor çünkü c ile codefiction yazılarını karşılaştırıyor. Ama c karşılaştırmasını için harcanan fazladan zaman saldırgana ilk harfi tahmin ettiğini gösteriyor. Bu noktadan sonra saldırganın tek yapması gereken ca, cb, cc gibi kombinasyonları da deneyerek ikinci harfi ve sonraki harfleri yine zaman bilgisine dayanarak tahmin etmek.

Hemen hemen bütün programlama dillerinde string karşılaştırma işlemi optimize edilmiştir ve iki string’i karakter karakter karşılaştırır.

def string_compare(a, b) :
if (a == b)
return True
else
return False
1: string_compare('abcdefg', 'abctyf2')
2: string_compare('abcdefg', 'abcdefb')

Yukarıdaki kod örneğinde 1 ve 2 nin işletilme zamanları birbirinden farklıdır. 1, 2 ye göre çok daha hızlı şekilde false döner. Çünkü sadece 3. karakterden sonrası farklıdır. Ama 2 çok daha uzun sürer çünkü 6.karaktere kadar iki string’de aynıdır.

Bu tür saldırları string karşılaştırma özelinde önlemek için Hash ve Encryption algoritmalarından yararlanılıyor.

Kernel

Kernel işletim sisteminin kalbinde yer alır ve sistemdeki herşey üzerinde kontrol sahibidir. Sistemin kaynaklarını yönetir ve uygulamaların process’leriyle donanım seviyesinde arasında köprü görevini görür. Kernel’ın kendisi de bir process’dir ve ama özel bir izin seviyesi olan Kernel Mode ile çalışır, donanım ve sistemin tamamına müdehale edebilir. Diğer uygulamalar User Mode denilen daha kısıtlı bir izin seviyesinde çalışır, kernel memory ve ya başka uygulamalarının memory’lerine erişemezler.

Virtual Memory ve Memory Isolation

Virtual (Sanal) Memory hem hardware (Memory Management Unit) hem de software (OS — İşletim Sistemi) bazında implemente edilmiş bir Memory yönetim tekniği. 1970'lerden bu yana bütün işletim sistemlerinde kullanılıyor.

Temel olarak işletim sistemi tarafından physical memory’in (fiziksel hafıza, RAM, Harddisk vb.) uygulamalardan (process) soyutlanması işlemidir. Böylece uygulamaların bilgisayarın sahip olduğudan daha fazla memory kullanabilmelerine olanak sağlanır. Yani bilgisayarın 8 GB RAM’i varsa ve uygulamanın ihtiyacı daha fazlaysa kalan kısmının harddisk’ten kullanılması işletim sistemi kernel’ı tarafından sağlanır. Uygulama açısından birşey fark etmez ona virtual (sanal) bir adres alanı sağlanır ve neyin nereye yazılacağı işletim sistemi tarafından yönetilir.

Hemen hemen her virtual memory implementasyonunda, bu sanal adres alanını, page denilen 4 KB’lık bölümlere ayrılmıştır. Virtual memory adreslerinin gerçek physical memory adreslerine çevirilmesi işlemini CPU’nun bir parçası olan MMU (Memory Management Unit) yapar. MMU bu işlemi yaparken işletim sistemi tarafından yönetilen ve page table adı verilen virtual ve physical memory adres eşleşmesini tutan yapıdan da yararlanır. Fakat sürekli page table’a gitmek yavaş ve masraflıdır. Bütün modern CPU’lar Translation Lookaside Buffer (TLB) denilen bir donanıma sahiptir. Bu donanım sayesinde sık kullanılan adres eşleşmeleri cache’lenir.

Bir virtual memory adresinin physical memory adresine çevirilmesine ihtiyaç duyulduğuda CPU adres eşleşmesini önce TLB içerisinde arar (yukarıdaki şemadaki 1.adım). Eğer adres bulunursa adres direkt dönülür (2.a). Bulunamazsa MMU ilgili adres eşleşmesini bütün page table içerisinde arar (2.b) bu işleme page walk denir. Eğer adres page table içerisinde bulunursa bulunan adres TLB cache’ine yazılır (3.a).

Bazı durumlarda bu lookup döngüsü beklenildiği gibi çalışmaz. İki durum var. Birincisi geçersiz bir adres eşleşmesinin yapılması. Yani uygulamanın kendisine ait olmayan bir memory alanına erişmeye çalışması. İkinci durum ise istenilen adresin daha memory’de yüklenmemiş olması. Her iki durumda da page fault oluşur, page fault özel bir interrupt türüdür ve kontrolün MMU’dan İşletim sistemi kernel’ına geçmesini sağlar.

İlk durumda MMU işletim sistemini geçersiz bir işlem yapıldığına dair bilgilendirir ve kernel Segmentation Fault hatasını fırlatır (3.b) ve uygulama OS tarafından sonlandırılır. Burası önemli çünkü konumuzla alakalı. Yani normal şartlarda işletim sistemleri bir process’in (uygulama) başka bir process’in memory alanına girmesini engeller. Başlıkta bahsettiğim Memory Isolation aslında bu.

İkinci durumda ise aranılan adresin ana memory’de değil de ikincil memory’de (Harddisk) olduğu ortaya çıkar (4.). Bu noktadan sonra kernel page table’ı ve TLB’yi ilgili adres eşleşmesiyle günceller. Swap’a düşmek tabiri de buradan gelir. Bu eskiden çok yaygın bir sorundu. RAM’in düşük olduğu bilgisayarlar harddisk’i kullanmaya başlardı ve bu durum yavaşlamalara sebep olurdu. Hem RAM’in bilgisayarda artık artması hem de SSD gibi çok daha hızlı teknolojilerin çıkmasıyla artık bu yavaşlama o kadar hissedilmiyor.

Şimdi biraz kernel memory ve process ilişkisine değinelim. Virtual ve physical memory adres eşleşmelerinin page table’da saklandığından bahsetmiştik. OS kernel’ının kendisi de bir process olduğundan dolayı kendisine ait bir virtual adres alanı vardır. Bu alan herhangi bir user uygulamasına ait process’den ayrıdır. Örnek şema bir 32-bit işletim sisteminde bu alan ayrımının nasıl olduğunu göstermektedir. Yani aslında her user process’in içerisine kernel’ın bütün virtual memory adres alanı eşlenmiş durumdadır.

Kernel memory özel bir memory alanıdır ve her user process içerisinde adress eşleşmesi tutulsa da process user mode’da çalışırken kernel memory’sine erişemez. Bunu yapmaya kalkışırsa page fault tetiklenir ve Segmentation Fault hatasını oluşur bu da uygulamanın process’inin sonlamasına sebep olur. Fakat process kernel mode’da ( örneğin os seviyesinde call’lar yapılırken) çalışırken kernel memory’e erişmesinde sıkıntı yoktur.

Her user process’in içerisine kernel’ın bütün virtual memory adres alanı eşlenmesinin tutulması performans amacıyla, neredeyse 30 yıldır bütün işletim sistemlerinde kullanılan standart bir tekniktir.

CPU Cache ve Memory

Bildiğiniz üzere modern bilgisayarların ve mobil cihazların hepsinde üç temel bileşen var. CPU (işlemci), RAM, Storage (Harddisk, SSD, SD Card vb.). Basit olarak bir uygulamaya çalıştırdığınız zaman CPU uygulama ile ilgili verileri storage’dan okur, ve yukarıda da bahsettiğimiz gibi process’e bir virtual memory alanı ayırır. Bu alan genelde storage’a göre çok daha hızlı olan RAM’‘dedir ve CPU uygulamayla ilgili hesaplama (computation) yaparken RAM’e okuma ve yazma işlemleri yapar. CPU’nun bu okuma-yazma işlemlerini storage’da yapmayı tercih etmemesinin sebebi RAM’in çok daha hızlı olmasıdır. Elbetteki yukarıda da bahsettiğimiz gibi swap’a düşme gibi durumlarda gerçekleşebilir.

Modern CPU’ların hepsinde kendi dahili RAM’leri vardır. Bunlar normal RAM’le karşılaştırıldığında kapasite olarak çok daha küçüktür ama normal RAM’in aksine CPU ile entegre chip içerisinde gelir ve CPU’un bu bölgeye erişmesi normal RAM’e göre çok çok daha hızlıdır. Bu bölgeye CPU Cache (işlemci ön belleği) denir, adından da anlaşılacağı üzere CPU, RAM’de çok sık ulaştığı verileri CPU cache’e alır ve buradan çok daha hızlı erişir. CPU Cache’deki veriler uzun ömürlü değildir ve yenileri geldikçe kullanılmayan eskileri silinir.

Speculative Execution

Modern CPU’ların çok karmaşık yapıları vardır ve machine instruction‘larını (talimat) basitçe sırayla yerine getirmezler. Her CPU thread’inin (iş parçacığının) kendi karmaşık pipeline’ı vardır ve bu machine instruction‘ları sırasız bir şekilde (out-of-order instructions) execute edebilirler. Bunun sebebi cache’lemedir. CPU Cache başlığında bahsettiğim gibi, CPU sık kullanılan verileri kendi cache’in de tutar fakat cache’de bulamadığında RAM’e gitmek durumundadır, bu da geçikmelere sebep olur. Bu yüzden modern CPU’ların hepsi bu instruction’ları, memory’den cevap gelmesini beklerken işletmeye başlar ve bunu da sırasıyla yapmayabilir (out-of-order). Bu optimizasyon tekniğine Speculative Execution deniliyor.

if (x < array1_size) {
y = array2[array1[x] * 256];
}

Yukarıdaki örnekte kodu inceleyelim. array1_size değişkeninin değerinin CPU cache’inde olmadığını ama array1'in adresinin olduğunu farz edelim. CPU bu durumda bir tahminde yani bir spekülasyonda bulunuyor ve x’in array1_size’dan küçük olduğu senaryoyu işletiyor. Yani if içerisindeki kod bloğunu array1_size’in değerinin RAM’den gelmesini beklemeden çalıştırmaya başlıyor. array1_size’ın değeri RAM’den geldikten sonra iki ihtimal var. CPU doğru spekülasyonda bulunmuşsa bu esnada RAM’den gelen değeri beklemediği için oldukça fazla zaman kazanmış oluyor. Yanlış spekülasyonda bulunmuşsa o zamana kadar yaptığı herşeyi discard (geri alıyor) ediyor. Bu branch prediction denilen özel bir speculative execution tekniği.

Burada konumuzla alakalı olarak şöyle bir durum var. Bu discard işlemi esnasında o zamana kadar execude edilmiş (işletilmiş) instruction’ların sonuçları RAM’den geri alınıyor. Çünkü işletilmemesi gereken bir kod bloğunun sonucunun, uygulamanın state’ini değiştirmesi istenilmez. Ama RAM’in aksine bu sonuçlar CPU cache’inden discard edilmiyor yani orada kalmaya devam ediyorlar.

Bu optimizasyon tekniği 20 yılı aşkın süredir işlemcilerde kullanılan bir teknik ve speculative execution algoritmalarının da gelişmesiyle beraber daha isabetli spekülasyonlar yapılmaya başladı. Speculative Execution modern CPU’ların işlem hızını arttıran en faktörlerden biri.

Meltdown ve Spectre’in detaylarına girmeden önce birşeyi belirtmek istiyorum. Yukarıda verdiğim bilgilendirmelerin hepsi aslında bir makale konusu ve her biri oldukça detaylı bir şekilde ele alınabilir. Yukarıdaki bilgiler konuyla ilgili kendi araştırmalarımın bir özeti ve genel hatlarıyla doğru olduğunu düşünüyorum. Yine de bir takım yanlışlar varsa düzeltilmekten mutluluk duyarım.

Meltdown

İlk güvenlik açığımız Meltdown olarak biliniyor. Ve aslında bakıldığı zaman bu açıktan faydalanmak oldukça kolay.

1. uint8_t* probe_array = new uint8_t[256 * 4096];
2. // ... Make sure probe_array is not cached
3. uint8_t kernel_memory = *(uint8_t*)(kernel_address);
4. uint64_t final_kernel_memory = kernel_memory * 4096;
5. uint8_t dummy = probe_array[final_kernel_memory];
6. // ... catch page fault
7. // ... determine which of 256 slots in probe_array is cached

(Kod örneğinin aslı burada)

Açık sayesinde bilgisayarın tüm memory’sini okumak mümkün. Yukarıdaki kod örneğini adım adım inceleyelim.

  1. Birinci satırda probe_array tanımlıyoruz. Bu array user alanında tanımlı standart bir array. Adı üzerinde bu array bizim için bir sonda görevi görecek ve daha önceden bahsettiğim timing attack tekniği kullanılarak kernel datasını okumamız sağlanacak.
  2. Sonrasında probe_array’in datasının cache’lenmemesini açık olarak belirmek gerekiyor. CPU instruction’ları kullanılarak bu işlem gerçekleştirilebiliyor. Böylece bizim sonda array’imizin CPU cache’de yer tutmamasını garantilemiş olacağız.
  3. Sonrasında seçtiğimiz bir kernel adres alanından bir byte değerini okumaya çalışıyoruz. Yazının önceki bölümlerinde bütün kernel virtual adres alanının performans arttırma sebebiyle user process içerisinde eşleştirildiğinden bahsetmiştik. Ama biliyoruz ki user mode’da çalışan hiç bir process kernel memory’e erişemez. Yani bu kod page fault’a sonrasında Segmentation Fault hatasına sebep olacaktır. Bu aşamada kernel memory’den bir byte data okuduk ama ne olduğunu bilmiyoruz, bilmemizin de imkanı yok.
  4. Fakat modern işlemcilerde speculative execution yapıldığından da bahsetmiştik yani 3–5 arası instruction’lar daha page fault almadan önce out-of-order olarak execute edilebilir. Page boyutunun 4 KB yani 4096 byte olduğundan bahsetmiştik. Bu değer kernel memory’nin byte değeri ile çarpılır, byte değeri bildiğiniz üzere 0–255 arasında olabilir. Artık elimizde probe_array’de kullanabileceğimiz bir indeks var. Bu bir bayt’ın, 4096 ile çarpımı “ prefetcher” olarak adlandırılan bir CPU özelliğinden kaçınmak için yapılır. Yani CPU cache’e istediğimizden fazla data yüklemeyi önlemek için. Yine 4096 ile çarptığımızdan dolayı, probe_array’e her erişim arasında bir page (4kB) aralık vardır. Bu nedenle her 0–255 arsındaki farklı byte değeri farklı bir page’e eşlenir.
  5. İşlemler başlamadan önce probe_array’in cache’lenmeyeceğini 2.adımda garantilemiştik. Speculative execution sebebiyle bu satırdaki kod çalıştırılır. Bu aşamada probe_array’in indeksinden gelen değer dummy bir değişkene atanır ve cache’lenir. Önemli bir nokta olarak belirtmek istiyorum burada elde ettiğimiz değerin kernel memory ile hiç bir alakası yok, user mode’da erişebileceğimiz geçerli bir memory alanına erişiyoruz. Ama bu değer artık CPU cache’inde, bizim oluşturuğumuz indeks ile eşleşmiş bir şekilde duruyor.
  6. Bu aşamada artık CPU hata yaptığının yani yanlış spekülasyonda bulunduğunun farkına varır, 4. ve 5. adımlarda yaptıklarını geri alarak 3.adıma kadar işlemleri roll back eder, yani 5.adımda speculative execution sonucu oluşan dummy değer RAM’den geri alınır. Fakat bu değer hala CPU cache’in de durmaktadır. Alınan Segmentation Fault hatası handle edilip bastırıl ve programın çalıştırılmasına devam edilir.
  7. Artık probe_array üzerinde iterasyon yapmaya başlayabiliriz. Biliyoruz ki kernel memory’deki byte data’dan elde ettiğimiz indeks (kernel memory byte *4096) ile eşleşmiş değer yani dummy değer CPU Cache’de duruyor. Artık daha önceden bahsettiğimiz timing attack tekniğini kullanabiliriz. Diyelim ki kernel memory byte değeri 67. Eğer olası bütün 256 byte için probe_array üzerinde iterasyon yaparsak bu iterasyonlardan biri diğerlerinden önemli ölçüde hızlı gerçekleşektir. Yani ;
uint8_t dummy = probe_array[1 * 4096] YAVAŞ
uint8_t dummy = probe_array[2 * 4096] YAVAŞ
uint8_t dummy = probe_array[3 * 4096] YAVAŞ
uint8_t dummy = probe_array[4 * 4096] YAVAŞ
.
.
.
uint8_t dummy = probe_array[67 * 4096] HIZLI

Bunun sebebi 67 harici diğer indekslere ait değerler istenildiğinde RAM’e gidilecektir çünkü daha önce o indekse takabül eden data çekilmemiştir. Ama 67 istenildiğinde hızlı gelecektir çünkü daha önceden speculative execution sonucu elde edilen değer CPU Cache’de durmaktadır. Artık en başta ulaştığımız kernel memory adresindeki değerin 67 olduğunu biliyoruz. 67 nin ASCII değeri C.

Eğer olası bütün kernel memory adreslerine erişmeye çalışırsanız (ki bunların hepsi Segmentation Fault hatası fırlatacaktır) ve her adres için 256 sonda operasyonu gerçekleştirirseniz, eninde sonunda bütün kernel memory’sini user process’e almış olacaksınız. Bu oldukça ciddi bir güvenlik açığı. Gördüğünüz üzere kernel mode’da birşeyler yapmanıza gerek yok, bütün olay user mode’da gerçekleşiyor.

Bütün bunların olabilmesinin sebebi 1995 yılından beri üretilen çoğu Intel işlemcide olan bir bug. Yani process’in ulaşmak istediği memory alanına ulaşma izni olup olmadığını kontrol etmeden speculative execution işleminin gerçekleşmesine izin vermek. Ayrıca bazı ARM işlemcilerinde de bu güvenlik açığının olduğu bildirildi.

AMD işlemcileri Meldown’dan etkilenmiyor. AMD işlemcileri process’in ulaşmaması gereken bir yere ulaştığını tespit ederse speculative execution’ı bloklayıp, direkt Segmentation Fault hatasının fırlatılmasına sebep oluyor.

Spectre

Spectre bazı açılardan Meltdown’a benziyor ve iki farklı variant’ı var. Meldown ile karşılaştırıldığında kullanılması daha zor bir açık ama son 20 yıl içerisinde üretilmiş bütün CPU’lar bu açığa maruz kalabiliyor. Spectre aslında CPU’yu speculative execution uygulaması için kandırmak üzerine bir teknik ve belli şartların oluşması gerekiyor.

if (x < array1_size) {
y = array2[array1[x]];
}
  1. x değeri bizim kontrolümüzde olmalı
  2. array1_size cache’lenmemiş olmalı
  3. array1 cache’de olmalı

x, array1_size’dan küçük olduğu sürece, herhangi kötü birşey olmaz ve if ifadesi x’in array1'in dışına taşması önlenir. Fakat daha önce de bahsettiğimiz gibi if içerisindeki kod bloğu CPU tarafından speculative execution kullanılarak çalıştırılabilir. Burada uygulanan özel speculative execution tekniğine branch prediction deniyor.

Diyelim ki CPU x’in değerinin array1_size’dan küçük olduğunu tahmin etti yani bir spekülasyonda bulundu ama x değeri array’in size’ın çok ötesinde bir değer. array1_size değeri RAM’den gelene kadar, CPU if içerindeki kod bloğunu çalıştırıldı. Bu noktada CPU, branch prediction tekniğini kullanması için çeşitli geçerli argümanlar kullanılarak eğitilebilir. Spectre açığını kullanmak için biraz ön hazırlık gerekiyor.

array1_size RAM’den geldiği zaman CPU hata yaptığını anlar ve o zamana kadar yaptığı işlemleri discard eder. Ancak bu noktada x değeri ile beraber dizinin dışına taşmış array1[x]’in değeri, şimdi CPU cache’de olan array2'in değerini aramak için kullanılmaktadır. array1[x] değerinin CPU cache’de olmadığına dikkat edin, ancak bunun bir önemi yok çünkü sadece array2'nin hangi elemanın CPU cache’inde bulunduğunu array1[x]’i kullanarak bulabiliyoruz. Tek yapmamız gereken array2'nin her elamanına ulaşmak ve hangi elemanın daha hızlı geldiğini tespit etmek. Yani yine daha önceden bahsettiğimiz timing attack tekniğini kullanılıyor. Fakat burada Meltdown’dan farklı olarak kernel memory’e erişmeye çalışmak gibi bir durum yok sadece speculative execution kullanılıyor.

Spectre açığını kullanmak Meltdown’a göre daha zor çünkü belli şartları olgunlaştırmak gerekiyor. Saldırgan CPU’yu yanlış spekülasyon yapmaya ikna etmeli yani speculation engine’i yanıltmalı.

Meltdown’la karışlaştırıldığında bir CPU tasarım hatası demek daha zor çünkü bu durum biraz modern CPU’ların doğal işleyişiyle alakalı. CPU’lardan, belli erişim şablonları kullanılarak indirekt bir şekilde yani side-channel attack kullanılarak (bu durumda timing attack) bir takım bilgiler elde edilebiliyor.

Dikkat edilmesi gereken nokta Spectre güvenlik açığının Browser’larda da javascript kullanılarak oluşturalabilmesi. Bu yazı yazılırken Google Chrome bu açağı kapatacak bir paket çıkartma hazırlığındaydı.

Peki şimdi ne olacak?

Meltdown ve Spectre açıkları ayyuka çıktığından beri bu açıkları kapatmak için çalışmalar yapılıyor. Özellikle cloud provider’lar (Amazon AWS, Microsoft Azure, Google Cloud) bu konuyu çok ciddiye alıyorlar ve bildiğim kadarıyla hem Azure hem AWS çeşitli güncellemeler yaptılar hatta bazı durumlarda çeşitli server’ları müşterilerine haber vererek restart etmişler.

Her ne kadar AMD ve Intel bu açıklara ideal bir çözüm üretmeye çalışsa da yazılım şirketleri onları beklemden güvenlik yamaları çıkartmaya başladır. Sadece işletim sistemlerinden bahsetmiyorum, Database’lere ve Browser’lara da güvenlik yamaları ardı ardına çıkmaya başladı.

Fakat çıkartılan bütün bu güvenlik yamaları yazılımsal olarak normalde yapılmayan kontroller yapılmasına sebep olduğu için %5 — %30 arası performans kayıplarına sebep oluyor.

Bu durum özellikle Cloud alt yapılarını kullanan büyük küçük bütün firmaları etkiliyor, şu an herkes alt yapı mimarilerini yeniden incelemek durumunda kaldı. Örneğin Epic Game bu yamalardan sonra yaşadıkları performans düşüklükleri ile ilgili detaylı bir makale yayınladı.

Bu çıkan güvenlik yamalarıyla beraber ilk şok atlatıldı diyebiliriz. Ama bu güvenlik açıklarının uzun vadeli sonuçlarının nasıl olacağını ön görmek zor. Intel ve AMD’den önümüzdeki haftalarda chipset seviyesinde güvenlik yamaları bekleniyor. Ve daha optimize yamaların zamanla çıkarak performans etkilerinin en aza indirilebileceği düşünülüyor.

Bunların yanısıra okuduğum tüm makalelerde normal ev kullanıcılarının güncel güvenlik yamalarını kurdukları sürece risk altında olmadıkları belirtiliyor. Benim de size tavsiyem gerek kullandığınız işletim sisteminin gerekse kullandığınız browser’ların son yamalarını indirip kurmanız yönünde. Sonrasında da bir süre daha konuyu takipte kalmakta yarar var.

Sahte Güvenlik Hissi

Peki neden yazının başlığında “Sahte güvenlik hissi (eng. false sense of security)” terimini kullandım. Uzun süredir kullanıcılar olarak hemen hemen her uygulamaya girerken kendi belirlediğimiz şifreleri kullanıyoruz, günümüzde artık parmak izi, retina ve yüz tanıma gibi sistemler de kullanılmaya başlandı. Bir çok kişi bilgisayarlarını korumak için çeşitli antivirus, anti-malware ve firewall yazılımları kullanıyor. Aynı şekilde Cloud alt yapılarımızda da çeşitli güvenlik önlemleri alıyoruz. Bugüne kadar hepimiz bu tür güvenlik önlemlerinin bizi koruduğunu düşünüyorduk. Ama yazıyı buraya kadar okuduysanız Meltdown ve Spectre’ın ne kadar ciddi etkilerinin olabileceğini anladığınızı düşünüyorum. Ama benim bahsettiğim bugün yaşadığımız etkiler değil.

Şimdi komplo teorilerine çok prim veren bir insan değilim (bazen verdiğim oluyor :) ) ama insan düşünmeden edemiyor. Google Project Zero ekibi Meltdown ve Spectre açıklarını 2017 ortalarında keşfediyorlar ve bu açıklardan Meltdown’un 1995 yılından bu yana üretilen çoğu Intel işlemcisinde olduğunu biliyoruz, aynı şekilde Spectre’ın da uzun yıllardır olduğu biliniyor.

Sormak istediğim soru “Ya biri bu güvenlik açıklarını daha önceden keşfetmişse?”. 1995 yılına kadar uzanıyorsa böyle bir olasılık mümkün. Demek istediğim “CIA bizi gözlüyor!” değil ama bunca yıldır kendimizi güvende hissetmemizin Sahte Güvenlik Hissi olduğunu düşünüyorum.

Son Olarak

Meltdown ve Spectre’ın uzun vadeli etkilerinin kısa vadeli etkilerinden çok daha büyük olacağını düşünüyorum. Belkide önümüzdeki 5–10 senin bütün yazılımsal ve donanımsal tasarımları gözden geçirilip, yenilenecek. Özellikle işlemci üreticilerinin mimarilerinde köklü değişiklikler yapacağını düşünüyorum.

Güvenlik açıklarını kapatmak amaçıyla çıkartılan yamaların sebep olduğu performans sorunlarının ise uzun vadeli etkileri çok daha fazla olacaktır. Şu an bile alt yapıları Cloud’da olan şirketlerler bu problemle boğuşuyorlar.

Uzun vadede bir çok sorun olacağını ön görsek de şu an ki durum bir kaç hafta öncesine göre daha iyi, ilk şok atlatıldı ve en azından Cloud Provider’lar alabilecekleri bütün önemleri aldılar.

Bir sonraki yazımda görüşünceye dek hepinize iyilikler dilerim.

Kaynaklar

--

--