buffer overflow arşivleri • CanYouPwnMe! - For Cyber Security Researchers https://canyoupwn.me cypm! Sun, 23 Jul 2017 18:41:49 +0000 tr hourly 1 https://wordpress.org/?v=6.0 https://canyoupwn.me/wp-content/uploads/2016/02/cropped-Başlıksız-1-32x32.png buffer overflow arşivleri • CanYouPwnMe! - For Cyber Security Researchers https://canyoupwn.me 32 32 TR | Code Reuse Saldırıları (ret2libc & rop) https://canyoupwn.me/tr-code-reuse-saldirilari-ret2libc-rop/ https://canyoupwn.me/tr-code-reuse-saldirilari-ret2libc-rop/#respond Thu, 16 Jun 2016 21:31:35 +0000 https://canyoupwn.me/?p=2733 CanYouPwnMe! - For Cyber Security Researchers CanYouPwnMe! - For Cyber Security Researchers - cypm!

Merhabalar, bu yazımda sizlere binary exploitationda sıkça kullanılan bir teknikten bahsedeceğim. Diğer bir teknik olan Egg Hunting hakkındaki yazımı okumadıysanız buradan okuyabilirsiniz. Tekniğe giriş yapmadan önce binary exploitation saldırılarının yapısı ve bu tekniğe neden ihtiyaç duyulduğundan biraz bahsetmek istiyorum. Bildiğiniz üzere “program” dediğimiz şey belli bir işi yapmak üzere, belli bir algoritmaya göre bir araya […]

TR | Code Reuse Saldırıları (ret2libc & rop) CanYouPwnMe

]]>
CanYouPwnMe! - For Cyber Security Researchers CanYouPwnMe! - For Cyber Security Researchers - cypm!

rop

Merhabalar, bu yazımda sizlere binary exploitationda sıkça kullanılan bir teknikten bahsedeceğim. Diğer bir teknik olan Egg Hunting hakkındaki yazımı okumadıysanız buradan okuyabilirsiniz.

Tekniğe giriş yapmadan önce binary exploitation saldırılarının yapısı ve bu tekniğe neden ihtiyaç duyulduğundan biraz bahsetmek istiyorum. Bildiğiniz üzere “program” dediğimiz şey belli bir işi yapmak üzere, belli bir algoritmaya göre bir araya getirilmiş talimatlardan başka birşey değildir. Bu programlar genellikle kullanıcıdan bir girdi verisi alır, bu veriyi işler ve bir çıktı verisi üretir. Örnek vermek gerekirse bir e-ticaret sitesi düşünelim. Bu sitede yer alan ürünlerin her birine atanmış özel bir ID değeri vardır. Kullanıcı bir ürünün özelliklerine bakmak istediğinde, (arkaplanda) ilgili ürünün ID bilgisini sunucu tarafındaki yazılıma girdi olarak verir. Yazılım bu ID bilgisini alır ve sahip olduğu veritabanında bu bilgiyi sorgulatarak o ID’ye sahip olan ürünün bilgilerini elde eder, ardından bu bilgileri kullanıcıya çıktı olarak gösterir.

Yine aynı örnek üzerinden devam edelim. Bu bilgileri elde etme sırasında yazılım arkaplanda bir SQL sorgusu çalıştırıyor olsun. SQL sorgumuz da şu şekilde;

SELECT fiyat,ozellikler FROM urunler WHERE urun_id=$id;

$id ile belirtilen yer bizim girdi verimizin yer alacağı değişken. Bu da demek oluyor ki siteye “?id=1″ şeklinde bir parametre gönderirsek arka tarafta “urun_id=1″ için sorgu dönecektir. Burada dikkatinizi çekmesi gereken şey, veritabanına talimat olarak gönderilen SQL komutlarının da aynı gönderdiğimiz ID değişkeni gibi bir veri olması. Yani programın kendisi de, verdiğimiz girdiler de, üretilen çıktılar da esasında birer veridir. Bilgisayar için bu iki veri türünün tek farkı bunların ne şekilde yorumlanacağıdır. Bu programa girdi olarak gelen ID verisi arkada dönecek SQL sorgusuna parametre olacak şekilde yorumlanırken, SQL sorgu verisinin kendisi veritabanında çalıştırılacak talimatlar olarak yorumlanmaktadır. Bundan dolayıdır ki “?id=1 OR 1=1″ şeklinde bir parametre gönderildiğinde sorgu;

SELECT fiyat,ozellikler FROM urunler WHERE urun_id=1 OR 1=1;

halini alacak, gönderdiğimiz girdi verisinin kendisi de bir SQL talimatı olarak algılanacak ve ona göre işlem görecektir. Burada varmak istediğim nokta şudur; bilgisayarlar hangi verinin “data” hangi verinin “talimat” olacağı ayırımını yapamamaktadır! (Burada data’dan kastım talimat olmayan, program tarafından işlenecek olan verilerdir). Çoğu saldırı türünde olayın özü girdi olarak verdiğimiz veriyi karşıdaki yazılımın bir talimat olarak yorumlamasını sağlayarak kendi komutlarımızı çalıştırmaktır.

Binary exploitation’da da durum aynen böyledir. Konumuza hafiften giriş yaparken çalıştırılabilir dosyaların bölümlerini biraz inceleyelim.

Program_memory_layout.pdf

Bir programı çalıştırdığınız zaman ilgili çalıştırılabilir dosya harddiskten okunur ve çalıştırılmaya başlamadan önce hafızaya sağdaki gibi bölümlere ayrılmış şekilde yerleştirilir. Bu bölümlerden text segmenti çalıştırılacak kodların yer aldığı bölümdür. Geri kalan data, bss, heap ve stack adlı bölümler bizim programımızın işleyeceği verilerin, yani az önce “data” olarak bahsettiğim verilerin yer alacağı bölümlerdir.

Zafiyetli bir uygulama istismar edilirken çoğu zaman amaç kod akışını bir şekilde değiştirerek programı kendi çalıştırmak istediğimiz kodlara yönlendirmektir. kod akışını değiştirmenin yollarından birkaçı EIP registerine dolaylı yoldan yazmak, GOT kaydını değiştirmek, program içerisinde yer alan fonksiyon işaretçisinin üzerine yazmak şeklinde sıralanabilir. Peki kod akışını değiştirdik ama nereye yönlendireceğiz? Programın işleyeceği normal verilerin data, bss, heap ve stack kısımlarından birinde tutulacağını söylemiştim. Bunlardan heap ve stack kullanıcıdan alınan girdi verilerini tutar. Dolayısıyla biz çalıştırmak istediğimiz talimatları shellcode adı verilen makine kodu formatında programa girdi olarak verdikten sonra bunun hafızada yer aldığı adresi tespit ederek kod akışımızı o adrese yönlendirebiliriz. Program bu iki türdeki verinin ayırımını yapamadığı için aslında girdi olarak verdiğimiz datayı talimat olarak yorumlayıp çalıştırmaya başlayacaktır. Stack overflow zafiyetli çok basit bir uygulamanın istismarına yönelik bir video çektim. Örnek olması açısından göz atabilirsiniz.

Saldırganların program akışını değiştirme amacını bilen geliştiriciler, bunu önlemek adına kimisinin Data Execution Prevention, kimisinin NX bit dediği ancak kimsenin adı hususunda ortak karara varamadığı bir güvenlik mekanizması geliştirdiler. Bu mekanizmayla beraber hafızada herhangi bir alan (varsayılan olarak) aynı anda hem yazılabilir hemde çalıştırılabilir olamıyordu. Bunun anlamı saldırgan kod akışını ele geçirse dahi shellcode’u yükleyebileceği stack, heap benzeri alanlar Not Executable olduğundan dolayı programı oraya yönlendiremeyecektir. Bu sayede buffer overflow ve benzeri saldırılar engellenmiş(?) oldu.

sigsegv

Bunu gören saldırganlar da boş durmadılar ve “hafızaya kod enjekte etmeden programa kendi istediğimizi nasıl yaptırırız?” sorusu üzerinde kafa yormaya başladılar. Ardından hali hazırda çalıştırılabilir olan hafıza alanı .text akıllarına geldi. Yukarıda da bahsetmiştim text segmenti program kodlarının bulunduğu hafıza alanıdır. Dolayısıyla programın çalışabilmesi için bu alanın Executable olması gerekmektedir. Peki bu alanla ne yapılabilir? Düşünün, kendi kodunuzu yazamıyorsunuz ancak hali hazırda bir takım kod hafızada yüklü halde bulunuyor. Aynı bir kolaj çalışması yapar gibi hafızada yüklü olan bu kodları parça parça birleştirip kendi istediğimiz işi yapacak bir kod bütünü ortaya çıkarabiliriz! Tam olarakta bu işlem Code reuse saldırısı olarak adlandırılır. Bu saldırıda kullanılabilecek iki adet teknik bulunmakta bunlar: ret2libc ve return-oriented-programming.

ret2libc Yöntemi

Bu teknikte kod akışı direkt olarak programda yer alan fonksiyonlara yönlendirilerek amaca ulaşılmaya çalışılır. Örneğin hedef uygulamanın kaynak kodu şu şekilde olsun;

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void foo(char * arg) {
	char buf[40];
	strcpy(buf, arg);
	printf("Girdi: %s\n", buf);
}

void findme(char * arg) {
	system(arg);
}

int main(int argc, char **argv) {
	foo(argv[1]);

	return 0;
}

Burada findme() fonksiyonuna dikkat edin. Argüman olarak bir string alıyor ve içeride system (shell komutları çalıştırmaya yarayan bir fonksiyon) fonksiyonuyla argümanda verilen shell komutunu çalıştırıyor.. Normal program akışına dahil olmasa bile biz zafiyetten faydalanarak kod akışını bu fonksiyona yönlendirir ve parametre olarakta “/bin/sh” stringini verir isek zafiyeti başarılı bir şekilde istismar etmiş oluruz. Çağıracağımız fonksiyon illa programın içinde yer almak zorunda değil, programın çağırdığı kütüphanelerdeki fonksiyonları da pek ala kullanabiliriz. Peki bu yolla bir fonksiyona nasıl argüman verebiliriz? Gelin bir fonksiyona ait stack hafızasını inceleyelim.

Stack hafızası, bir fonksiyonun geri dönüş adresini, o fonksiyona giren argümanları ve fonksiyon içerisindeki lokal değişkenleri depolar.

assembly_stack

Bir fonksiyon çağırıldığında stack hafızası yukarıdaki gibi bir hal alır. EBP ve ESP arasındaki alan fonksiyonun kendi lokal değişkenlerinin tutulduğu alandır. EBP’nin hemen üstünde o fonksiyonun geri dönüş adresi, onun da üstünde fonksiyona giren argümanlar yer alır. Yani biz bir fonksiyon çağıracağımız vakit payload’umuz şöyle bir hal alacaktır;

bellek_tasirma +  geri_donus_adresi + "JUNK" + arguman1 + . . . + argumanN

11

 

Aşağıda bu tekniğin kullanımına dair bir uygulama videosu hazırladım. Detayları orada görebilirsiniz.

ROP Yöntemi

Hedef uygulamada kullanabileceğimiz system() benzeri fonksiyonlar her zaman bulunmaz, hatta bazı geliştiriciler bu istismar yolunu bildiklerinden bilinçli bir şekilde bu fonksiyonları devre dışı bırakabilirler. Bu durumda return-oriented-programming adı verilen bu ikinci yönteme başvurulur. Bu yöntemin tek farkı daha ufak kod parçalarının kullanılmasıdır. Yine kolajdan örnek verecek olursak bütün bir kelimeyi kesip kullanmak ret2libc ise 2-3 harflik kesitler alıp kullanmak rop tekniğidir. Bu teknikte çalıştırmak istediğimiz assembly kodu satır satır incelenmeli, her satırdaki talimatın ya tam aynısı yada ona denk gelecek bir talimat hafızada bulunup adresleri tespit edilmelidir. Tabi her bulduğumuz adresi kullanmamız mümkün değil zira program sadece bizim istediğimiz talimatı çalıştırmalı, ondan sonra gelen talimatları çalıştırmadan durmalıdır. Bunun için sadece kendisinin ardından ret komutu gelen, gadget adını verdiğimiz kod parçalarını kullanabiliyoruz. Bir örnek verelim, istismarın ardından çalıştırmak istediğimiz komutlar aşağıdaki gibi olsun;

;; exit sistem çağrısı. bu shellcode çalıştırıldığında program çıkış yapar.

xor eax, eax
mov al, 0x1

int 0x80

ROP yöntemiyle böyle bir shellcode çalıştırmak için bize 3 adet gadget lazım olacak. Onlarda şu şekilde;

;; ilk gadget
xor eax, eax
ret

;; 2. gadget
mov al, 0x1
ret

;; 3. gadget
int 0x80
ret

Bu gadgetlar hafızada aranıp adresleri bulunduktan sonra ard arda payload’a eklenir. Her bir gadget istediğimiz talimatı çalıştırdıktan sonra program akışını bir sonraki gadget’a yönlendireceğinden ötürü bütün gadgetlar arka arkaya çalışacak ve istismarımız başarılı olacaktır. Dikkat ettiğiniz üzere iki teknikte de hafızaya hiçbir kod enjekte etmedik, sadece hali hazırda yer alan kodları kendi amacımız doğrultusunda kullandık. ROP tekniğine dair uygulama videosunu da aşağıda bulabilirsiniz.

Bir sonraki yazıda görüşmek üzere..

TR | Code Reuse Saldırıları (ret2libc & rop) CanYouPwnMe

]]>
https://canyoupwn.me/tr-code-reuse-saldirilari-ret2libc-rop/feed/ 0
TR | Stack Overflow’da Egg Hunting Tekniği https://canyoupwn.me/tr-stack-overflow-egg-hunting-teknigi/ https://canyoupwn.me/tr-stack-overflow-egg-hunting-teknigi/#respond Sat, 11 Jun 2016 14:59:58 +0000 https://canyoupwn.me/?p=2669 CanYouPwnMe! - For Cyber Security Researchers CanYouPwnMe! - For Cyber Security Researchers - cypm!

Bu yazımda yığın taşması zafiyetinin istismarında kullanılan Egg Hunting adı verilen bir teknikten bahsedeceğim. Adını bir paskalya bayramı geleneğinden alan bu teknik shellcode’umuzu yerleştireceğimiz buffer’da yeterli alan yoksa kullanılır. “Execve /bin/sh” gibi ufak boyutlu shellcode’larda bu tür sorunlar genelde ortaya çıkmasa da reverse-tcp gibi görece daha büyük shellcode’lar kullanıldığında, bunun üstünede IPS benzeri güvenlik önlemlerini […]

TR | Stack Overflow’da Egg Hunting Tekniği CanYouPwnMe

]]>
CanYouPwnMe! - For Cyber Security Researchers CanYouPwnMe! - For Cyber Security Researchers - cypm!

1

Bu yazımda yığın taşması zafiyetinin istismarında kullanılan Egg Hunting adı verilen bir teknikten bahsedeceğim.

Adını bir paskalya bayramı geleneğinden alan bu teknik shellcode’umuzu yerleştireceğimiz buffer’da yeterli alan yoksa kullanılır. “Execve /bin/sh” gibi ufak boyutlu shellcode’larda bu tür sorunlar genelde ortaya çıkmasa da reverse-tcp gibi görece daha büyük shellcode’lar kullanıldığında, bunun üstünede IPS benzeri güvenlik önlemlerini atlatmak için encoding işlemi yapıldığında shellcode’umuz gittikçe daha büyük boyutlara ulaşmaktadır ve şayet yeterli alan bulunmuyorsa Egg hunting gibi tekniklere başvurulmalıdır.

3

Bu tekniğin temel mantığı asıl çalıştırmak istediğimiz shellcode’un önüne etiket görevini üstlenecek bir string (yabancı kaynaklarda TAG olarak geçer) koymak ve oluşturulan bu EGG shellcode‘unu istismar edilecek programın erişebileceği bir hafıza alanına yerleştirmek (örneğin programın aldığı başka bir parametreye girdi olarak verilebilir). Ardından zafiyeti istismar edip program akışını Hunter shellcode adı verilen ikinci bir shellcode’a yönlendirmek. Bu ikinci shellcode’un görevi ise uygulamaya ait bütün belleği tarayıp bizim az önce yerleştirdiğimiz etiketi aramak, bulduğunda ise “etiketin_adresi+len(etiket)” adresine yani asıl shellcode’umuzun bulunduğu adrese atlayıp programı oradan çalıştırmaya devam etmek.

Şimdi örnek olarak burada yer alan shellcode’u inceleyelim…

char hunter[] =
"\xeb\x16"
"\x58"
"\x40"
"\x81\x78\xf8\x65\x67\x67\x20"
"\x75\xf6"
"\x81\x78\xfc\x6d\x61\x72\x6b"
"\x75\xed"
"\xff\xe0"
"\xe8\xe5\xff\xff\xff";
 
char egg[] =
"egg mark"
"\x83\xe8\x08"
"\x89\xc1"
"\xba\x08\x00\x00\x00"
"\xb8\x04\x00\x00\x00"
"\xbb\x01\x00\x00\x00"
"\xcd\x80"
"\xb8\x01\x00\x00\x00"
"\xbb\x00\x00\x00\x00"
"\xcd\x80";
 
int main(){
     (*(void  (*)()) hunter)();
     return 0;
}

Yukarıdaki kod içerisinde demin bahsettiğim gibi hunter ve egg isimli iki adet shellcode bulunuyor. Bunlardan egg bizim asıl çalıştırmak istediğimiz shellcode önüne etiket olarak “egg mark” stringi yerleştirilmiş. Örnek teşkil etmesi açısından basit bir kod parçası seçilmiş isterseniz disassemble edip inceleyebilirsiniz. Biz hunter shellcode’unu disassemble edip inceleyelim.

NOT: Şayet assembly’e aşinalığınız yok ise devam etmeden önce blogumda yazdığım şu yazımı ve burada yazdığım şu yazımı okumanızı tavsiye ediyorum.

4

Gördüğünüz üzere shellcode gayet basit bir yapıda. Burada yapılan ilk işlem hafızanın taranmaya başlanacağı ilk adresi elde etmektir. Developer bunu call-pop ikilisini kullanarak elde etmiş. Şöyle ki;

call
pop eax
/* ...meali... */
push eip
...
pop eax

Ilk adresi elde ettikten sonra bu adresten itibaren hafızamızı taramaya çalışıyoruz. loc 003 te göreceğiniz üzere bu adres bir döngü içerisinde her seferinde değeri 1 arttırılarak iki aşamalı bir şekilde önce bu adresin 8 byte gerisindeki, ardından 4 byte gerisindeki adresin içerisindeki değerler kontrol ediliyor. Kontrol edilen değerlerin ne olduğuna bir bakalım. (kod içerisinde bu değerler Little Endian DWORD halinde yer alıyor)

0x20676765 -> "\x65\x67\x67\x20" -> "egg "
0x6b72616d -> "\x6d\x61\x72\x6b" -> "mark"

Bu stringler birleştirildiğinde ortaya Egg shellcode‘unun önüne yerleştirilen etiket ortaya çıkıyor yani: “egg mark”. Şayet bu iki kontrolün ikisi de geçilir ise bu adrese atlanılıyor ve program çalışmaya oradan devam ediyor. Aksi takdirde döngünün başına dönülüyor. Gördüğünüz gibi mantığı gayet basit, lakin bu teknikte asıl shellcode’umuzun bulunması biraz vakit alabiliyor onu da söylemeden geçmeyelim. Hunter‘ın kaba kodu ise şu şekilde:

Pseudo-code:

int *p = $eip

while True
	p++
	if (*p == 0x20676765) /* "egg " */
		if (*(p+4) == 0x6b72616d) /* "mark" */
			p()

Şimdi kaynak kodunu derleyip çalıştıralım ve ne olacağına bakalım.

NOT: Asıl shellcode’u execve /bin/sh shellcode ile değiştirdim. Yani işlem başarılı olursa uygulama bize shell verecek.

5

İşlem başarılı. Belirtmekte fayda var şuanda herhangi bir istismar işlemi yok, yalnızca exploit-db de yer alan shellcode’un çalışıp çalışmadığını denedik. Gcc ile birlikte kullandığım opsiyonlardan -m32 uygulamanın 32bit olarak derleneceğini, -fno-stack-protector bir stack overflow koruması olan CANARY‘nin devre dışı olacağını, -z execstack ise diğer bir buffer overflow koruması olan NX‘in devre dışı olacağını belirtmekte. Şayet uygulamamızı bu korumaları devredışı bırakmadan derlersek çalıştırdığımızda aşağıdaki gibi bir görüntüyle karşılaşırız.

6

Bunun sebebine başka bir yazımda değineceğim. Bir sonraki yazıda görüşmek üzere.

İleri okuma:

TR | Stack Overflow’da Egg Hunting Tekniği CanYouPwnMe

]]>
https://canyoupwn.me/tr-stack-overflow-egg-hunting-teknigi/feed/ 0