Background Image

BLOG

18 Şubat 2018 CTF

DKHOS - Web 400 - Esaret


Sorunun Açıklaması:

http://34.205.154.108  

Sorunun Çözümü:

http://34.205.154.108/ adresi ilk ziyaret edildiğinde aşağıdaki bilgiler temin edilir.

1 – phpinfo adresi
http://34.205.154.108/phpinfo

2 – İlgili controllerin kaynak kodu

3 – Flag lokasyonu ve ek bilgiler
Bu kaynak kod okunduğunda http://34.205.154.108/flag.txt adresinde flag’in var olduğu ama doğrudan erişim imkanı olmadığı görülür. 

Özellikle PHP info ve flag’in isminin ifşa edilmiş olmasının nedeni ise farklı bir yol izleyerek çözüme giden takımlar için flag.txt’inin local full path’ini ifşa etmektir. Aşağıdaki ekran görüntüsünde phpinfo çıktısından alınan SCRIPT_FILENAME sonucu görülmektedir.

Yine aynı şekilde phpinfo’nun ifşa edilme nedeni, olurda bir takım unserialize fonksiyonu ile ilgili overflow zafiyeti kullanmak isteyen takımın spesifik olarak php versiyonunu bilmesine ihtiyaç duyacak olmasıdır.

Ayrıca; takip edenlerin bildiği üzere PHP 7.0 ve 7.1 arasında yapılan değişiklerden biz hacker’lar için en önemli olan değişiklik; parse_str, extract, assert vb kritik fonksiyonların dinamik bir şekilde parametre almaları iptal edilmiş olmasıdır. [Forbid dynamic calls to scope introspection functions]

Zafiyet Analizi

Tahmin edildiği üzere bir adet object deserialization zafiyeti mevcuttur. Tüm mevzunun döndüğü kısım ise aşağıdaki bölgedir.
 

İlk satırda bir integrity check yapılmaktadır. Pek bir önemi olmayan bir husus. Payload’ın md5 hash değeri checksum değişkeni üzerinden sunucuya iletilmeli. Asıl husus ise unserialize fonksiyonun çağrısının yapıldığı yer. Burada yarışmaya katılanların durup ne yapıyorum ben ? diye kendilerini sorgulamaları için aslında ufak bir trick eklenmiştir. Unserialize edildiğinde şayet ortaya bir array, bu array’inde c isimli indisi varsa bu indise set edilmiş sınıfın open() methodu çağırılmıştır.

Şu soruları kendisine soran kişiler, doğru yolu bulmuş olacaktılar.

1 – Bu hangi framework ? (Laravel)
2 – Herhangi bir parametresi set edilmeyen ve open() methodu çağırıldığında işime yarar hale gelecek bir php sınıfı (built-in veya framework özelinde) var mı ?

Açıncası ikinci sorunun cevabı hayır, yok. Bu nedenle asıl odaklanılması gereken nokta şu olmaktadır.

“Laravel framework’ü initialize edildiğinde kendi yapısında hangi sınıfları namespace’e load etmekte ? Bu sınıfları kullanarak bir custom object chaining yapabilir miyim ? Bu chaining her zaman RCE ile sonuçlanmasına gerek yok zira local file content okuyabilirsemde işime yarar zira flag’in /var/www/html/public/flag.txt olduğunu biliyorum.”

Laravel 5.6 (şu andaki son versiyon) dahil olmak üzere Laravel 5.x ailesi için geçerli olan benim daha önceki yıllarda geliştirdiğim 3 adet object chaining payload’ı bulunmaktadır. Bu chaining’lerden iki tanesi henüz internette yayınlandığını görmedim. Bu nedenle public olarak var olduğunu bildiğim bir chaining payload üzerinden anlatacağım.

Laravel load edilirken yüklenen sınıflardan \Illuminate\Broadcasting\PendingBroadcast Sınıfı yapısında __destruct metotunu içerir. Bu metoda bakıldığında class property’lerinden events’in dispatch metodunun gene aynı sınıfın property’si olan event ile çağırıldığı gözlemlenmektedir.



Bu bilgiyi bir kenara koyarak devam ettiğimizde \Faker\Generator sıfında çok ilginç bir magic function (__call) çağrısı olduğu görülmektedir.

Format methodunun detayına bakıldığındaysa aşağıdaki tanım görülür.

Burada en önemli olan durum, call_user_func_array fonksiyonunun kullanılmış olması. Lakin ufak bir husus var ki oda ilk parametresinin getFormatter() fonksiyonundan geliyor olması. Bu fonksiyona detaylı bakıldığındaysa formatters isimli class property’sinde tanımlı olan bir metodun çağırılıyor olmasının zorunlu olduğu bilgisi görülmektedir.

Bu bilgiler birleştirildiğinde nihai olarak üretmiş olacağınız object chain kodu şu şekilde olmalıdır.

O:40:"Illuminate\Broadcasting\PendingBroadcast":2:{s:9:"*events";O:15:"Faker\Generator":1:{s:13:"*formatters";a:1:{s:8:"dispatch";s:6:"system";}}s:8:"*event";s:8:"sleep 10";}

Böylece RCE elde edilmiş olacaktır. Geriye kalan tek şey ise gidip flag.txt okumak.
 

ctf dkhos web400