Deserialization of Untrusted Data Açıklığı (CWE-502) | |||||
Bu makalede Deserialization of Untrusted Data (CWE-502), yani denetlenmemiş verinin tersine serileştirilmesi açıklığı anlatılacaktır.
Açıklık Önem Derecesi: Yüksek Açıklığın Etkisi: Uzaktan kod çalıştırma Açıklığın Açıklaması: Uygulamalar ihtiyaca göre serileştirme (serialization) ve deserileştirme (deserialization) işlemini kullanabilmekteler. Uygulama kaynak kodlarındaki bir veri yapısının veya nesnenin sonradan ağ üzerinden başka bir platforma iletilmek veya sonradan kullanılmak amacıyla dönüştürülerek bir dosyaya veya veritabanına depolanması işlemine serileştirme adı verilir. Serileştirme ile uygulama kaynak kodlarındaki bir veri yapısı veya nesne JSON, XML veya binary ( byte[] ) veri formatlarında dosyaya veya BLOB veri formatında veritabanına kaydolur. Uygulama kaynak kodlarındaki bir veri yapısının ve nesnenin serileştirme işlemi ile oluşan formunu tersine alarak tekrar uygulama kaynak kodlarında denk bir veri yapısı veya nesne oluşturmaya ise deserileştirme adı verilir. Örneğin serileştirmeye python’dan örnek verilmiştir: Python: class Person: def __init__(self, name, age): self.name = name self.age = age Person nesnesi uygulamada bir serileştirme fonksiyonu kullanılarak aldığı değerler ile beraber şu şekilde JSON formata dönüştürülüp depolanabilir. JSON Dosyası: {"name": "John", "age": 25} Örneğin deserileştirmeye yine python’dan bir örnek verilmiştir: JSON Dosyası: {"name": "John", "age": 25} Python: json_veri = '{"name": "John", "age": 25}' person_nesne = json.loads(json_data) # Python nesnesi ile sonuçlanır # {'name': 'John', 'age': 25} Bir person’ın JSON temsili verisi alınarak ve json.loads() ile deserileştirme uygulayarak tekrardan kaynak kodda Person nesnesi elde edilir. Deserileştirme sırasında eğer kaynak JSON, XML, Binary temsili verileri denetlenmeden kaynak kodda denk bir veri yapısı ve nesneye dönüştürülürse bu durum keyfi komut çalıştırma veya işletim sistemi komutları çalıştırma ile sonuçlanabilir. Saldırganlar bu sonuca deserileştirme işlemi sırasında nesnede mevcut olan olası sınıfları ve metotları çağırarak ulaşabilirler. Dolayısıyla denetlenmemiş veri deserileştirmeye tabi tutulursa bu bir güvenlik açıklığı olarak ele alınır. Çeşitli teknolojilerde bu açıklığın varlığını ve kapatılma yöntemini gösteren bazı kod bloklarına yer verilmiştir: C# - Güvensiz Kod Bloğu: // TR: Kullanıcı Girdisinden Zafiyetl Json.NET Nesne Deserileştirme // EN: Vulnerable Json.NET Deserialization of Object from User Input string objString = Request.Form["object"]; Newtonsoft.Json.JsonSerializerSettings settings = new Newtonsoft.Json.JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All //Any value except TypeNameHandling.None is vulnerable }; object o = Newtonsoft.Json.JsonConvert.DeserializeObject(objString, settings); C# - Güvenli Kod Bloğu - Söz Dizimi (Syntax) (1): // TR: Tür Zorlaması Uygulayan Kullanıcı Girdisinden // Json.NET Nesne Deserileştirmesi // EN: Json.NET Deserialization of Object from User Input That Enforces Type string objString = Request.Form["object"]; TrustedObject oo = Newtonsoft.Json.JsonConvert.DeserializeObject<TrustedObject>(objString); C# - Güvenli Kod Bloğu - Söz Dizimi (Syntax) (2): // TR: Tür Zorlaması Uygulayan Kullanıcı Girdisinden // Json.NET Nesne Deserileştirmesi // EN: Json.NET Deserialization of Object from User Input That Enforces Type using Newtonsoft.Json; using Newtonsoft.Json.Converters; ... string objString = Request.Form["object"]; TrustedObject oo = JsonConvert.DeserializeObject<TrustedObject>(objString); C# güvensiz kod bloğu örneğinde kullanıcı girdisinden gelen json veri denetlenmeden deserileştirmeye tabi tutuluyor. Kullanıcı, girdisini manipüle ederek deserileştirme sonrası kaynak kodda bu vaziyette keyfi komut çalıştırabilir. C# güvenli kod bloğu örneklerinde ise kullanıcı girdisinden gelen json veri içeriği kendi veri tipinde deserileştirmeye <TrustedObject> ile zorlanıyor. Yani kendi veri tipinde deserileştirmeye zorlanarak kullanıcı taraftan gelen json veri içerisinde var olabilecek komut niteliğindeki kodların kaynak kodda çalıştırılması önleniyor. PHP - Güvensiz Kod Bloğu: <?php // TR: Güvensiz bir şekilde Unserialize() Fonksiyonu // ile Yeni $user Nesnesi oluşturma // EN: Create New User with unserialize() insecurely $attributes = $_GET['user_attributes']; // Gelen Input JSON Verisi. $user = unserialize($attributes); // Deserileştirme ile Nesne Oluşur. ?> PHP - Güvenli Kod Bloğu: <?php // TR: Parametreleri Kullanarak JSON'dan Yeni Bir $user Nesnesi // EN: Create New User from JSON using Parameters // .. JSON Validity Kontrolü - JSON Çıktı Döner .. // $user_params = json_decode($_GET['user_attributes']); // .. Parametre Kontrolü – JSON Çıktı Parçaları String’leşir .. // $name = $user_params['Name']; $email = $user_params['Email']; $phone = $user_params['Phone']; // .. String’lerle Yeni Bir $user Nesnesi Oluşur .. // $user = new User($name, $email, $phone); ?> PHP güvensiz kod bloğu örneğinde kullanıcı girdisinden gelen json veri denetlenmeden deserileştirmeye tabi tutuluyor. Kullanıcı, girdisini manipüle ederek deserileştirme sonrası kaynak kodda bu vaziyette keyfi komut çalıştırabilir. PHP güvenli kod bloğu örneğinde ise kullanıcı girdisinden gelen json veri içeriği doğrudan deserileştirme ile nesneye dönüştürülmüyor. Kullanıcı girdisi önce json formatta ayıklanarak çekiliyor. Ardından ayıklanmış json formattaki veride yer alan json parametreler teker teker değişkenlere “string” olarak atanıyor. En sonunda bu string formattaki değişkenler yeni bir User nesnesi için değer olarak aktarılıyor ve $user nesnesi oluşturuluyor. Yani kullanıcı girdisi ayıklanarak ve string’leştirilerek gelen json veri içerisinde var olabilecek komut niteliğindeki kodların kaynak kodda çalıştırılması önleniyor. JAVA - Güvensiz Kod Bloğu: // TR: ServletRequest Input Stream’den Bir Nesne Okuma // EN: Reading an Object from ServletRequest Input Stream ServletInputStream sis = request.getInputStream(); ObjectInputStream ois = new ObjectInputStream(sis); Object obj = ois.readObject(); JAVA - Güvenli Kod Bloğu: // TR: Güvenli Object Input Stream Kullanarak ServletRequest // Input Stream’den bir Nesne Okuma // EN: Reading an Object from ServletRequest Input Stream // Using a Secure Object Input Stream // TrustedObject’nin güvenilir bir nesne sınıfı olduğunu varsayalım // ObjectInputStream’den Güvenli Kalıtım public class SafeObjectInputStream extends ObjectInputStream { @Override protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { if (!desc.getName().equals(TrustedObject.class.getName())) { throw new ClassNotFoundException("Unsupported Class: ", desc.getName()); } return super.resolveClass(desc); } /* Constructors */ } // SafeObjectInputStream ile güvenli stream okuma kodu ServletInputStream sis = request.getInputStream(); ObjectInputStream ois = new SafeObjectInputStream(sis); TrustedObject obj = (TrustedObject)ois.readObject(); JAVA güvensiz kod bloğu örneğinde kullanıcı girdisinden gelen json veri denetlenmeden ObjectInputStream.readObject() ile deserileştirmeye tabi tutuluyor. Kullanıcı, girdisini manipüle ederek deserileştirme sonrası kaynak kodda bu vaziyette keyfi komut çalıştırabilir. JAVA güvenli kod bloğu örneğinde ise kullanıcı girdisinden gelen json veri içeriği doğrudan deserileştirme ile nesneye dönüştürülmüyor. Önce deserileştirme class’ından kalıtım yoluyla güvenli bir deserileştirme class’ı oluşturuluyor. Ardından güvenli deserileştirme class’ı ile deserileştirme uygulanarak ve ilgili TrustedObject nesnesi ile (güvenli olduğu varsayılıyor) casting işlemi uygulanarak nesne oluşturuluyor. Yani kullanıcı girdisi güvenli bir şekilde deserileştirilerek gelen json veri içerisinde var olabilecek komut niteliğindeki kodların kaynak kodda çalıştırılması önleniyor. Eğer bir uygulamada denetlenmemiş bir veri doğrudan deserileştirmeye tabi tutuluyorsa “Denetlenmemiş Verinin Tersine Serileştirilmesi (CWE-502)” açıklığı vardır denir. Açıklığın Önlemi: Bu açıklığın giderilmesi için tavsiyeler şu şekildedir:
Yararlanılan Kaynaklar:
|
|||||
![]() |
|||||
|
|||||
Yorumlar |
|||||
Henüz yorum girilmemiştir. | |||||
Yorum Ekle | |||||