Py4H Code Hunter

🕊 Bu döküman @KekikAkademi için oluşturulmuştur. ✌🏼

Bu yazımızda PHP scriptlerde bug (hata, zafiyet) avcılarının işini kolaylaştıracak bir araç kodlayacağız.

Saldırı Senaryosu:

Hedef bir PHP projesini bütünüyle ele alıp GET ve POST işlemleri yapılan .php dosyalarını bulmak ve bu dosyalarda zafiyet taraması yapmak için kodları göze hoş bir şekilde renklendirmek.

Algoritma:

  • Başla
  • Belirtilen dizine git
  • Tüm alt dizinleri gez ve php dosyalarını bul
  • Ekrana yaz
  • Bitti
Program 2 işlevli olduğu için 2. algoritmamız:
  • Başla
  • Php dosyasını oku
  • Süzgeçten geçir
  • Süzgeçe yakalanan satırları renklendir ve ekrana yaz
  • Bitti

Kod Paylaşımı:

Aşşağıdaki kodlar renk kodları, içeriye aktarılan kütüphaneler ve tanımlanan değişkenlerden oluşmaktadır.

import sys,re,os,colorama # kullanacağımız modüller(kütüphaneler)

#Renk Kodları
bold = "\033[1m" #Koyulaştıran renk kodu 
underline = "\033[4m" # Kullanmadık ama yazının altını çizen renk kodu
green = "\033[92m" # Yeşil renk kodu
blue = "\033[94m" # Mavi renk kodu
yellow = "\033[93m" # Sarı renk kodu
red = "\033[91m" # Kırmızı renk kodu
endcolor = "\033[0m" # Kodların sonuna gelen renk kodu

taranan_dosyalar = [] # Taranan dosyalar için boş liste
girilen_dizinler = [] # girilen dizinler için boş liste
bulunan_dosyalar = [] # bulunan dosyalar için boş liste

Aşağıdaki kodlarımız, scriptteki kodları renklendirmeyle görevlidir. Gelen dosyayı (dizin ismi ile beraber gelmeli yoksa aynı dizinde olmalı dosyamız) açıp okur satır satır süzer ve renklendiririz. Ekrana yazarken satır sayısı ile beraber yazarız. Süzme işemini açık oluşturabilcek php fonksiyonlarına göre yaptık bu daha fazla eklenebilir yada sizin tarayacağınız php projelerine göre düzenlenebilir.

#Scriptteki kodları renklendir
def oku(dosya_ismi): # oku metodumuz ve alınan dosya ismi
	dosya = open(dosya_ismi,"r") # dosyamızı okumak için açıyoruz
	icerik = dosya.readlines() # satır satır olmak üzere okuduk
	satir_sayisi = len(icerik) # kaç satır sayısı olduğunu bulduk
	for i in range(0,satir_sayisi): # for döngümüz satır sayısı kadar döncek
		if re.findall('.*_GET',icerik[i]): # _GET varsa
			print("%s%s%s-)  %s %s" %(bold,green,(i+1),icerik[i],endcolor)) # renklendir(Koyu yeşil)
		elif re.findall('.*_POST',icerik[i]): # _POST varsa
			print("%s%s%s-)  %s %s" %(bold,green,(i+1),icerik[i],endcolor)) # renklendir(Koyu yeşil)
		elif re.findall('.*include',icerik[i]): # include varsa
			print("%s%s%s-)  %s %s" %(bold,green,(i+1),icerik[i],endcolor)) # renklendir(Koyu yeşil)
		elif re.findall('.*require_once',icerik[i]): # require_once varsa
			print("%s%s%s-)  %s %s" %(bold,green,(i+1),icerik[i],endcolor)) # renklendir(Koyu yeşil)
		elif re.findall('.*readfile',icerik[i]): # readfile varsa 
			print("%s%s%s-)  %s %s" %(bold,green,(i+1),icerik[i],endcolor)) # renklendir(Koyu yeşil)
		elif re.findall('.*mysql_query',icerik[i]): # mysql_query varsa
			print("%s%s%s-)  %s %s" %(bold,green,(i+1),icerik[i],endcolor)) # renklendir(Koyu yeşil)
		elif re.findall('.*setcookie',icerik[i]): # setcookie varsa
			print("%s%s%s-)  %s %s" %(bold,green,(i+1),icerik[i],endcolor)) # renklendir(Koyu yeşil)
		elif re.findall('.*system',icerik[i]): # system varsa
			print("%s%s%s-)  %s %s" %(bold,green,(i+1),icerik[i],endcolor)) # renklendir(Koyu yeşil)
		elif re.findall('.*fputs',icerik[i]): # fputs varsa
			print("%s%s%s-)  %s %s" %(bold,green,(i+1),icerik[i],endcolor)) # renklendir(Koyu yeşil)
		elif re.findall('.*eval',icerik[i]): # eval varsa 
			print("%s%s%s-)  %s %s" %(bold,green,(i+1),icerik[i],endcolor)) # renklendir(Koyu yeşil)
		elif re.findall('.*_REQUEST',icerik[i]): # _REQUEST varsa 
			print("%s%s%s-)  %s %s" %(bold,green,(i+1),icerik[i],endcolor)) # renklendir(Koyu yeşil)
		elif re.findall('.*shell_exec',icerik[i]): # shell_exec varsa
			print("%s%s%s-)  %s %s" %(bold,green,(i+1),icerik[i],endcolor)) # renklendir(Koyu yeşil)
		elif re.findall('.*system',icerik[i]): # system varsa
			print("%s%s%s-)  %s %s" %(bold,green,(i+1),icerik[i],endcolor)) # renklendir(Koyu yeşil)
		elif re.findall('.*exec',icerik[i]): # exec varsa
			print("%s%s%s-)  %s %s" %(bold,green,(i+1),icerik[i],endcolor)) # renklendir(Koyu yeşil)
		elif re.findall('.*passthru',icerik[i]): # passthru varsa 
			print("%s%s%s-)  %s %s" %(bold,green,(i+1),icerik[i],endcolor)) # renklendir(Koyu yeşil)
		elif re.findall('.*proc_open',icerik[i]): # proc_open varsa
			print("%s%s%s-)  %s %s" %(bold,green,(i+1),icerik[i],endcolor)) # renklendir(Koyu yeşil)
		elif re.findall('.*pcntl_exec',icerik[i]): # pcntl_exec
			print("%s%s%s-)  %s %s" %(bold,green,(i+1),icerik[i],endcolor)) # renklendir(Koyu yeşil)
		elif re.findall('.*assert',icerik[i]): # assert varsa
			print("%s%s%s-)  %s %s" %(bold,green,(i+1),icerik[i],endcolor)) # renklendir(Koyu yeşil)
		elif re.findall('.*preg_replace',icerik[i]): # preg_replace varsa
			print("%s%s%s-)  %s %s" %(bold,green,(i+1),icerik[i],endcolor)) # renklendir(Koyu yeşil)
		elif re.findall('.*create_function',icerik[i]): # create_function varsa 
			print("%s%s%s-)  %s %s" %(bold,green,(i+1),icerik[i],endcolor)) # renklendir(Koyu yeşil)
		elif re.findall('.*phpinfo',icerik[i]): # phpinfo varsa
			print("%s%s%s-)  %s %s" %(bold,green,(i+1),icerik[i],endcolor)) # renklendir(Koyu yeşil)
		elif re.findall('.*file_include',icerik[i]): # file_include varsa
			print("%s%s%s-)  %s %s" %(bold,green,(i+1),icerik[i],endcolor)) # renklendir(Koyu yeşil)
		elif re.findall('.*require',icerik[i]): # require varsa 
			print("%s%s%s-)  %s %s" %(bold,green,(i+1),icerik[i],endcolor)) # renklendir(Koyu yeşil)
		else: # hiç biri yoksa
			print("%s%s-)  %s %s" %(blue,(i+1),icerik[i],endcolor)) # açık mavi ile renklendir

Aşağıdaki kodlarımızda olan dizin gezme algoritmasını daha önceden paylaşmıştık. gezgin() metodumuzun görevi verilen dizine girmek ve ne var ne yok diye bakması için Arastirmaci() metodunu çağırmak bu metod işini bitirince tekrar bir üst dizine çıkmak. Arastirmaci() metodumuz ne var ne yok bütün dosyaları alır bu bir dizin mi ve bu dizine girilmemiş mi diye sorar bu cevap olumluysa gezgin() metodu tekrar devreye girer biraz hiyerarşik bir yapısı vardır. Eğer bu bir dizin değil dosya ise ve bu bir php dosyası ise gerekli süzgeçleri uygular ve istediğimiz php dosyalarını bize bulur ve getirir. Nedir bu istediğimiz php dosyaları? İstediğimiz php dosyaları içerisinde _GET ve _POST işlemi yapılmış dosyalardır.

#Dizin gezme algoritması
def gezgin(gelen_dizin): # gezgin metodumuz gelen dizini alır
	os.chdir(gelen_dizin) # gelen dizine girilir
	girilen_dizinler.append(gelen_dizin) # girilen dizi girilen_dizinler adlı listeye eklenir
	Arastirmaci() # Arastirmaci metodu çağrılır
	os.chdir(os.pardir) # bir üst dizine çıkılır


def Arastirmaci(): # Arastirmaci metodumuz
	dosyalar =  os.listdir(os.getcwd()) # içinde bulunduğu dizindeki dosyaları kayıt eder
	for i in dosyalar: # kayıt edilen dosyalar for döngüsünde dökülür
		if os.path.isdir(i): # bu dosya bir dizin mi ?
			if girilen_dizinler.count(i) == 0: # peki daha önce bu dizine girdik mi
				gezgin(i) # girmediysek gezgin metodunu çağır
			else: # girilmişse 
				pass # pas geç girme bir daha 
		else: # bu bir dizin değilse
			if taranan_dosyalar.count(i) == 0: #dosyamızı daha önce taradık mı?
				if re.findall('.*php',i): # taramadıysak bu bir php dosyası mı ?
					dosya = open(i,"r") # öyleyse aç bu dosyayı okumak için
					icerik2 = dosya.read() # dosyanın kodlarını oku
					taranan_dosyalar.append(i) # ve taranan dosyalara kaydet 
					if re.findall('.*_GET',icerik2): # okunan kodlarda _GET var mı ?
						bulunan_dosya_ismi = os.getcwd()+"/"+i # varsa dizini ile beaber al
						bulunan_dosyalar.append(bulunan_dosya_ismi) # bulunan_dosyalar listesine ekle
					elif re.findall('.*_POST',icerik2): # okunan kodlarda _POST var mı ?
						bulunan_dosya_ismi = os.getcwd()+"/"+i # varsa dizini ile beraber al
						bulunan_dosyalar.append(bulunan_dosya_ismi) # bulunan_dosyalar listesine kaydet
					else: # okunan kodlarda _GET ve _POST yok mu ?
						pass # boşver
				else: # bu bir php dosyası değilmiş
					pass # boşver
			else: # bu dosyayı daha önce taramışız
				pass # o zaman boşver

def bitti(): # her şeyin bitip ekrana bulduğumuz dosyaları yazan metod
	for i in bulunan_dosyalar: # bulunan_dosyalar for döngüsünde dökülür
		print(bold+blue+i+endcolor) # koyu mavi olarak ekrana yazılır

Aşağıdaki kodlarımız ilk çalışacak olan kodlardır diyebiliriz. Olası hatalar için try-except yapısını kullandık ve bu sefer yakaladığımız hatanın türüne göre de kullanıcımızı yönlendirdik.

#Olası hatalar için try-except
try: # try olası hatalar için
	if sys.argv[1] == "-f": # argv 1. eleman -f parametresi almış mı
		oku(sys.argv[2]) # aldıysa 2. elemanı oku
	elif sys.argv[1] == "-p": # eğer 1. eleman -p parametresi aldıysa
		gezgin(sys.argv[2]) # sen gene 2. elemanı oku ve gezgin metodunu çağır bu sefer
		bitti() # bitti metodunu çağır
except IOError: # verdiğin php dosyası yok
	print(bold+red+"Dosya Bulunamadı !"+endcolor) # Hata
except IndexError: # programı yanlış mu kullandın sen ?
	print("""
  ____          _        _   _             _            
 / ___|___   __| | ___  | | | |_   _ _ __ | |_ ___ _ __ 
| |   / _ \ / _` |/ _ \ | |_| | | | | '_ \| __/ _ \ '__|
| |__| (_) | (_| |  __/ |  _  | |_| | | | | ||  __/ |   
 \____\___/ \__,_|\___| |_| |_|\__,_|_| |_|\__\___|_|   V1.0
													
""")
	print(bold+red+"\n Örnek kullanım:\n\n $ python tespit.py -f dosya_ismi >>> php dosyasını renklendirir !"+endcolor)
	print(bold+red+"\n $ python tespit.py -p taranacak_dizin >> Dizini tarar ve size işe yarar php dosyalarını bulur !"+endcolor)

Kodların Tamamına Burdan Ulaşabilirsiniz!

Notlar:

  • Yaptığımız bu proje Python 3x sürümü ile yazılmıştır ve standart kütüphaneler kullanılmıştır. Herhangi bir kütüphane yüklemenize gerek kalmamaktadır.
  • Program Linux’ta test edildiği için renk kodlarının çalışabilirliği Windows’ta denenmemişir .
Bir sonraki yazımızda görüşmek üzere.

Kaynak

__________________________

📃 Yandex.Disk Bünyemizdeki veriler 900GB'ı geçmiştir..

Paylaşılan Kursların Tümünü @KekikKahve Grubu notlarından Çağırabilirsiniz..

🕊️ Bize oy verip paylaşarak destek olmaya ne dersin? ✌🏼