Güvenli olmayan seri durumdan çıkarma

OWASP kategorisi: MASVS-CODE: Kod Kalitesi

Genel Bakış

Büyük miktarda Java nesne verisi depolarken veya aktarırken genellikle verileri önce serileştirmek daha verimlidir. Daha sonra veriler; alıcı uygulama, etkinlik veya sağlayıcı tarafından seri durumdan çıkarılarak işlenir. Normal şartlar altında veriler, serileştirilir ve ardından herhangi bir kullanıcı müdahalesi olmadan seri dışı bırakılır. Ancak serileştirmeden çıkarma işlemi ile amaçlanan nesnesi arasındaki güven ilişkisi, kötü amaçlı bir kişi tarafından kötüye kullanılabilir. Bu kişi, örneğin serileştirilmiş nesneleri durdurup değiştirebilir. Bu durum, kötü amaçlı kullanıcının hizmet reddi (DoS), ayrıcalık yükseltme ve uzaktan kod yürütme (RCE) gibi saldırılar gerçekleştirmesine olanak tanır.

Serializable sınıfı, serileştirmeyi yönetmek için yaygın olarak kullanılan bir yöntem olsa da Android'in serileştirmeyi işlemek için Parcel adlı kendi sınıfı vardır. Parcel sınıfı kullanılarak nesne verileri bayt akışı verilerine serileştirilebilir ve Parcelable arayüzü kullanılarak bir Parcel içine paketlenebilir. Bu sayede Parcel daha verimli bir şekilde taşınabilir veya depolanabilir.

Bununla birlikte, yüksek verimli bir IPC taşıma mekanizması olması amaçlandığından, ancak veri uyumluluğu sorunlarına veya kaybına yol açabileceğinden, serileştirilmiş nesneleri yerel kalıcı depolama alanında depolamak için kullanılmamalıdır. Parcel sınıfını kullanırken dikkatli olunmalıdır. Verilerin okunması gerektiğinde, Parcel öğesini seri dışına çıkarmak ve nesne verilerine dönüştürmek için Parcelable arayüzü kullanılabilir.

Android'de seri dışılaştırmadan yararlanmak için üç temel vektör vardır:

  • Geliştiricinin, özel sınıf türünden gelen nesnelerin seri dışına çıkarılmasının güvenli olduğu yönündeki yanlış varsayımından yararlanma Gerçekte, herhangi bir sınıf tarafından kaynak olarak kullanılan herhangi bir nesne, kötü amaçlı içerikle değiştirilebilir. Bu içerik, en kötü senaryoda aynı veya diğer uygulamaların sınıf yükleyicilerini etkileyebilir. Bu müdahale, sınıf amacına göre örneğin veri sızıntısına veya hesap ele geçirilmesine yol açabilecek tehlikeli değerlerin eklenmesi şeklinde gerçekleşir.
  • Tasarım gereği güvenli olmayan olarak kabul edilen seri dışılaştırma yöntemlerinin kötüye kullanılması (ör. derin bağlantı seri dışılaştırma vektörü aracılığıyla keyfi JavaScript kodu eklemeye izin veren yerel ayrıcalık yükseltme hatası olan CVE-2023-35669)
  • Uygulama mantığındaki açıklardan yararlanma (örneğin, CVE-2023-20963; bir uygulamanın Android'in WorkSource paket mantığındaki bir kusur aracılığıyla ayrıcalıklı bir ortamda kod indirip yürütmesine olanak tanıyan bir yerel ayrıcalık yükseltme hatası).

Etki

Güvenilmeyen veya kötü amaçlı serileştirilmiş verileri seri dışı bırakan tüm uygulamalar, uzaktan kod yürütme veya hizmet reddi saldırılarına karşı savunmasız olabilir.

Risk: Güvenilmeyen girişin seri dışı bırakılması

Saldırganlar, uygulama mantığındaki paket doğrulamasının eksikliğinden yararlanarak rastgele nesneler enjekte edebilir. Bu nesneler, seri dışı hale getirildikten sonra uygulamayı hizmet reddi (DoS), ayrıcalık yükseltme ve uzaktan kod yürütme (RCE) ile sonuçlanabilecek kötü amaçlı kod yürütmeye zorlayabilir.

Bu tür saldırılar fark edilmeyebilir. Örneğin, bir uygulama, doğrulandıktan sonra seri durumdan çıkarılacak yalnızca bir parametrenin yapılmasını bekleyen bir amaç içerebilir. Bir saldırgan, beklenenle birlikte beklenmedik ikinci bir kötü amaçlı ek parametre gönderirse intent, ekleri Bundle olarak ele aldığından, enjekte edilen tüm veri nesnelerinin seri dışına çıkarılmasına neden olur. Kötü amaçlı kullanıcılar, bu davranışı kullanarak seriden çıkarıldıktan sonra RCE, veri güvenliği ihlali veya kayba neden olabilecek nesne verilerini yerleştirebilir.

Çözümler

En iyi uygulama olarak, tüm serileştirilmiş verilerin güvenilmediğini ve kötü amaçlı olabileceğini varsayın. Serileştirilmiş verilerin bütünlüğünü sağlamak için verilerde doğru sınıf ve biçimin kullanıldığını doğrulamak amacıyla doğrulama kontrolleri yapın.

java.io.ObjectInputStream Kitaplığı için ileriye dönük kalıbı uygulamak uygun bir çözüm olabilir. Nesneden dizeye dönüştürme işleminden sorumlu kodu değiştirerek intent içinde yalnızca açıkça belirtilen bir sınıf grubunun serileştirildiğinden emin olabilirsiniz.

Android 13 (API düzeyi 33) itibarıyla, Intent sınıfında paketleri işlemeyle ilgili eski ve artık desteği sonlandırılmış yöntemlerin daha güvenli alternatifleri olarak kabul edilen çeşitli yöntemler güncellendi. getParcelableExtra(java.lang.String, java.lang.Class) ve getParcelableArrayListExtra(java.lang.String, java.lang.Class) gibi tür daha güvenli bu yeni yöntemler, uygulamaların çökmesine ve CVE-2021-0928 gibi ayrıcalık artırma saldırıları gerçekleştirirken kötüye kullanılma olasılığı bulunan uyumsuzluk zayıflarını yakalamak için veri türü denetimleri gerçekleştirir.

Aşağıdaki örnekte, Parcel sınıfının güvenli bir sürümünün nasıl uygulanabileceği gösterilmektedir:

UserParcelable sınıfının Parcelable uyguladığını ve kullanıcı verilerinin, daha sonra Parcel öğesine yazılan bir örneğini oluşturduğunu varsayalım. Daha sonra, serileştirilmiş paketi okumak için aşağıdaki readParcelable türüne daha güvenli yöntem kullanılabilir:

Kotlin

val parcel = Parcel.obtain()
val userParcelable = parcel.readParcelable(UserParcelable::class.java.classLoader)

Java

Parcel parcel = Parcel.obtain();
UserParcelable userParcelable = parcel.readParcelable(UserParcelable.class, UserParcelable.CREATOR);

Yukarıdaki Java örneğinde yöntem içinde UserParcelable.CREATOR kullanıldığına dikkat edin. Bu zorunlu parametre, readParcelable yöntemine ne tür olması gerektiğini bildirir ve readParcelable yönteminin kullanımdan kaldırılmış olan sürümüne göre daha iyi performans gösterir.

Belirli Riskler

Bu bölümde, standart olmayan azaltma stratejileri gerektiren veya belirli bir SDK düzeyinde azaltılan riskler toplanmıştır. Bu riskler, eksiksiz bir liste sunmak için burada yer almaktadır.

Risk: İstenmeyen Nesne Seri Dışı Dönüştürme

Bir sınıfta Serializable arayüzünün uygulanması, söz konusu sınıfın tüm alt türlerinin arayüzü otomatik olarak uygulamasına neden olur. Bu senaryoda, bazı nesneler yukarıda belirtilen arayüzü devralabilir. Bu, seri dışına çıkarılmaması gereken belirli nesnelerin yine de işleneceği anlamına gelir. Bu durum, saldırı yüzeyini istemeden artırabilir.

Çözümler

Bir sınıf Serializable arayüzünü devralır ve OWASP yönergelerine uygunsa sınıftaki bir nesne grubunun seri dışı hale getirilmesini önlemek için readObject yöntemi aşağıdaki şekilde uygulanmalıdır:

Kotlin

@Throws(IOException::class)
private final fun readObject(in: ObjectInputStream) {
    throw IOException("Cannot be deserialized")
}

Java

private final void readObject(ObjectInputStream in) throws java.io.IOException {
    throw new java.io.IOException("Cannot be deserialized");
}

Kaynaklar