Memcache Injection (Hacktrick Tshirtü Hediyeli)

Merhabalar. Bildiğiniz veya bilmediğiniz üzere geçenlerde Hacktrick Siber Güvenlik Konseransı düzenlendi (buda haberinin linki). Orada çok hızlı olmuş olsana Memcache Injection adlı bir sunum gerçekleştirdim. Hem etkinliğe gelenler hem etkinlik dışındakiler bu konuyu detaylı olarak yazmam için ricada bulundu ve bende yazıyorum 🙂

Memcache Nedir?

Memcache, adından da anlaşılabileceği üzere bir cache’leme servisidir. Genelde Php web application’ların kullanılsada Python, Asp.net, Java gibi dillerde de bu servisi kullanabileceğiniz library’ler mevcuttur.

Memcache kullanılmasının en büyük sebebi ise hız ve sistemi daha az yormasıdır. Şöyleki; büyükçe bir veritabanınız var ve aşırı request alıyorsunuz. Her sefersinde tekrardan Mysql connect oluyor, select from ile gerekli sorguyu gerçekleştirip kullanıcıya datayı veriyor. Bu sistemi aşırı şekilde yoruyor. Memcache ise, Mysql’deki datanızı alıp, belirttiğiniz süre zarfı içerisinde sunucunun RAM’inde tutuyor. Server’a request geldiğinde eğer istenen data Memcache’te var ise direk RAM üzerindeki datayı kullanıcıya sunuyoruz. Böylelikle data RAM’dan okunduğundan hem daha hızlı get edilmiş oluyor hemde hiç Mysql server’a bağlanıp database’imizi yormuyoruz 🙂

Nasıl Çalışır?

Memcache’in kurulu olduğu server’a connect sağlıyoruz ve sonrasında çok temelce veri kaydet (set) ve veri çek (get) işlemlerini gerçekleştiriyoruz. Kısaca bir php kodu ile gösterecek olursak;

$m = new Memcached();
$m->addServer("localhost", 11211);
$m->set("username", "omer", 3600);
echo $m->get("username"); // çıktı : "omer"

Yukarıda basitçe Php’de Memcached library kullnarak Memcache servisimize veri set edip o veriyi okuduk. Peki bu işlerim arkaplanı nasıl gerçekleşiyor? Bizim yazdığımız bu kodu Memcache servisimiz terminalize edip uyguluyor. Yani yukarıda yazdığımız kodu Memcache server’ımıza telnet ile baplanıp uygalamk istesydik aşağıdaki gibi terminal adımlarını izlememiz gerekecekti.

> set username 0 3600 4
> omer
< STORED
> get username
< VALUE username 0 4
< omer
< END

Yukarıdaki kodu açıklayalım.

  • İlk satırda set komutundan sonra gelen parametreler sırasıyla;
    • 1.si datamızın keyi
    • 2.si datamız sıkıştırılsınmı sıkıştırmasın mı? Boolean değer alıyor. 0 ise hayır 1 ise evet
    • 3.sü datamızın nekadar süre tutulacağı. Saniye cinsinden
  • 2 satır ise bir üst satırda belittiğimiz şartlar kapsamında datamızı girmemizi bekliyor
  • 3. satır verimizin sapasağlam kaydedildiğini bildiriyor
  • 4. satırda ise get komutundan sonra çekmek istediğimiz verinin key’ini yazıyoruz
  • 5. satırda gerekli işlemleri kendi yazıyor
  • 6. satırda bize istediğimiz key’in içindeki value’yu döndürüyor
  • Son satırda ise sapasağlam get edebildiğini bildiriyor.

Injection?

Injection tam olarak şu mantık ile çalışıyor; arkada kodun terminalize edildiğini biliyoruz. Ozaman terminalde yeni bir key ekliyor gibi gibi sorgumuzu manipüle edip gönderebiliriz. Yani yukarıdaki terminal sorgularına göre ben key’ime “username” değilde “username 0 3600 6 <LF><CR> hacked <LF><CR>” yaparsam, artık username keyimin içerisine omer değilde hacked kelimesini enjekte etmiş oluyorum.

Yukarıda anlattığımın terminaldeki karşılaşı aynen şu şekildir;

> set username 0 3600 6
> hacked
< STORED
> 0 3600 4
< ERROR

Hemen senaryomuzu kurgulayalım. Bir php sayfamız olsun, GET request olarak gelen “key” parametresinin içindeki değere ait bir memcache kaydı ekleyip içine 123456 kaydetsin. İçine girdiği değeri kullanıcıdan almasın, direk kod kendi ekledin. Biz ise manipüle edip 123456 yerine “hacked” kelimesini enjekte edelim.

Php kodumuz :

URL : ?key=omer

$m = new Memcached();
$m->addServer("localhost", 11211);
$m->set($_GET["key"], "123456", 3600);
echo $m->get("omer"); // çıktı : "123456"

Herşey normal. Hadi şimdide injection işlemini gerçekleştirelim.

URL : ?key=omer 0 3600 6 %0d%0a hacked %0d%0a

$m = new Memcached();
$m->addServer("localhost", 11211);
$m->set($_GET["key"], "123456", 3600);
echo $m->get("omer"); // çıktı : "hacked"

Gördüğünüz gibi yukarıdaki gibi bir payload girdiğimiz vakit artık “omer” keyimizin içinde “hacked” kelimesi yazacaktır.

Ne Yaptık Şimdi Biz?

Yeni bir satıra geçip komutumuzu istediğimiz gibi şekillendirebilmek için alt satıra geçmemiz gerekiyordu. Alt satıra geçmek için LFCR’nin url encode hali yani %0d%0a’yı kullandık. Bundan başka new line’a geçme methodlarıda mevcut. Şöyleki;

Null-byte

Null-byte yani (%00)’ı kullandığınız vakit o satırdaki sorgu sonlanıp, memcache ERROR döndürüp sonrasında yeni satıra geçecektir. Bu şekil yeni bir satıra geçip istediğiniz sorguyu yazabilirsiniz.

Char-limit

Memcache’de key olarak yazabileceğiniz string’in kapasitesi 250 karakterdir. Yani siz 251.yi girmeye çalıştığınız vakit Memcache ERROR döndürüp yeni bir satıra geçecektir.

Peki Nasıl Önleriz?

Yukarıdaki methodlardan yola çıkarsak bizim için tehlike teşkil eden 4 kriter bulunuyor

  1. LFCR yani %0d%0a
  2. Null-byte
  3. Char-limit

Ozaman bu 3 kriteri yok edecek bir kod yazmamız gerekiyor.

Öncelikle user’dan aldığımız data kaç karakter olursa olsun sub string ile ilk 200’ünü alalım.

$key = substr($_GET["key"], 0, 200);

Sonrasında bizim için zararlı olan 3 karakteri temizlememiz gerekiyor. Ancak bunları klasik string replace ile yapmamız gerekiyor. Byte byte okuyup zararlı karakterlerin bytelerını temizlememiz gerekiyor.

  1. %0d’nin decimal’i : 13
  2. %0a’nın decimal’i : 10
  3. Null-byte’ın decimali : 0

Ozaman php kodumuz şu şekil olacak :

$key = substr($_GET["key"], 0, 200); // bu satırı zaten bir önceki işlemde yazmıştık

$newkey = "";
for($i=0; $i<strlen($key); $i++){
    $ord = ord($key[$i]); // ord fonksiyonu içinde girdiğiniz string'in ascii karşılığını verir
    if($ord!=0 && $ord!=10 && $ord!=13){
        $newkey .= $key[$i];
    }
}

$m->set($newkey, "123456", 3600);

Bu şekil kendi çapımızca korumamızı almış oluruz 🙂

Peki Her Memcache Kullanan Uygulamada Geçerli mi?

Tabiki hayır 🙂 Her dilde güvenlik açığı barındıran ve barındırmayan kütüphaneler var. Güvenlik açığı barındırıpta update gelen kütüphaneler de var 🙂

Liste tam olarak şöyle;

memvullist

Son olarak bu sunumu ve teknik detayı ilk olarak Black Hat 2014‘te Ivan Navikov adlı abimiz gerçekleştirdi.

E Hani Hediye Tshirt?

Yazının başında bahsetmiştim Hacktrick Konferansı’ndan. Etkinlikten dağıtılan tshirtlerden fazladan almıştım dağıtmak için. Elimde 2 adet fazladan tshirt var. Çekiliş sonucu şanslı 2 kişiye o tshirtleri ve çoğ güzel stickerlar’ı hediye edeeceğim 🙂

Bu yazıyı “herkese açık” şekilde herhangi bir sosyal medyada (twitter ve facebook en makbülüdür) paylaşıp, paylaşımızın linkini bu yazıya yorum olarak yazarsanız çekiliş listenize adınızı ekleyebilirim. Çekilişe son katılma tarihi 15 Eylül saat 12:00‘dır. 15 Eylül gecesi çekilişi yapıp sonuçları açıklayacağım 🙂

Merak edenler için; Tshirt ve stickerların resmi ;

tshirt

Comments on this post

  1. Eline sağlık Ömer, gayet temiz ve anlaşılır bir blog tutuyorsun.

    Ben önceden veritabanı işlemlerinde belli bir bölüme sadece okuma yetkisi belli bölüme sadece yazma yetkisi verip. Gelen dataları da 3 tane filtreden geçirirdim.

    Şimdi sırtımı laravel ve popüler kütüphanelere dayadım. Özellikle injection saldırılarına, “zaten bunu çözmüşlerdir” diye düşünüp kodlamaya devam ediyorum.

    Tabi bu sınıfları açıp incelemek en iyisi fakat zaman sorunu yüzünden atlamak zorunda kalıyorum. Laravel’i incelediğini önceki yazında okudum. Yazılımcı hatası dışında bu framework tek başına yeterli mi? Yoksa yine filtreler uygulamakta fayda var mı?

    • Öncelikle yazıyı ve genel olarak blogu beğendiğin için teşekkürler 🙂

      Sadece framework yeterli değil. Framework’te dediğin gibib popüler güvenlik açıkları için zaten önlenler alınmış durumda. Genelde developer hatasından dolayı güvenlik açığı çıkmış oluyor ortaya. Ama şöyle birşeyde var; bilmem duymuşmusundur güvenlik dünyasında “0day” dediğimiz bir olay var. Bİr sistem üzerinde bir açık buluyorsun ve bunu henüz kimse bilmiyor. Şuan laravel’in core’unda belli bi 0day yok diye biliyorum. Ancak nodejs ve mongodb de henüz yeni bir 0day keşfedildi. Laravel üzerinden mongodb veya nodejs kullanıyorsan framework bile seni kurtaramıyor. Bu tarz durumlardada 0day public edilir edilmez vendorlar hemen patch yayınlıyorlar. Sürekli güncel tutmamız gerekiyor yani 🙂

  2. Anladım sık sık güncellemeyle sırtımı gene yaslayabilirim. 🙂
    Cevabın için teşekkür ederim.
    İyi akşamlar.

  3. Erkan

    Eline sağlık ömer. Genel olarak takip ediyorum yazılarını. Kitabını bekliyorum 🙂 İyi çalışmalar

  4. Tese

    Blogunuzu ilk defa gördüm sık kullanılanlara ekledim. Yazılarınızı ve blogunuzu beğendim. Teşekkürler.

  5. gerçekten güzel bir açıklama olmuş ilk defa duydum böyle bir terimi 🙁 buraya bunuda yazamadan duramam şimdi blogun sayfa isimleri çok güzel gerçekten 🙂

  6. orhan

    Ellerinize sağlık.Yazınız çok güzel olmuş.

  7. Hadi hayırlısı 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *

Trackbacks and Pinbacks

No trackbacks.

TrackBack URL