Güvenli kodlama: Java'da CWE 416 – Ücretsiz Sonra Kullan – kaynaklı sorunlardan kaçının

Saberie

Active member
Ortak Zayıflık Sayımı CWE-416'da açıklanan Boş Sonra Kullan (UAF) güvenlik açığı, bir program serbest bırakıldıktan sonra bir işaretçiyi kullanmaya devam ettiğinde ortaya çıkar. Bu, güvenlik açıklarını açabilir ve çökmeler ve hatta veri bozulması dahil tanımsız davranışlara yol açabilir. Sorun, işaretçi tarafından başvurulan belleğin başka amaçlar için yeniden tahsis edilebilmesi nedeniyle ortaya çıkar. Bu da saldırganlar tarafından istismar edilebilir.


Duyuru








Sven, 1996'dan bu yana ve 15 yılı aşkın bir süredir dünya çapında otomotiv, havacılık, sigorta, bankacılık, Birleşmiş Milletler ve Dünya Bankası gibi endüstrilerde endüstriyel projelerde Java programlıyor. 10 yıldan fazla bir süredir Amerika'dan Yeni Zelanda'ya kadar konferanslarda ve topluluk etkinliklerinde konuşmacı olarak yer alıyor, JFrog ve Vaadin için geliştirici savunucusu olarak çalışıyor ve düzenli olarak BT dergileri ve teknoloji portalları için makaleler yazıyor. Ana konusu olan Core Java'nın yanı sıra TDD ve güvenli kodlama uygulamalarını da kapsar.







CWE-416'nın Nedenleri – Serbest Sonra Kullan (UAF)


Yanlış bellek yönetimi: Belleği boşalttıktan sonra işaretçileri geçersiz kılmayı unuttum.

Eller asılı: Paylaşılan depolama alanına ilişkin referansları saklayın ve bunlara daha sonra erişin.

Çift çıkış: Bellek birden fazla kez serbest bırakılır, bu da aynı konumda birden fazla işlemin yapılmasına neden olabilir.

CWE-416'nın olası sonuçları

Güvenlik Açıkları: Saldırganlar, rastgele kod yürütmek, ayrıcalıkları yükseltmek veya hizmet reddine (DoS) neden olmak için UAF'tan yararlanabilir.

Veri Bozulması: UAF, program kararsızlığına veya kararsız davranışlara yol açabilecek beklenmeyen veri değişikliklerine neden olabilir.

Program çöküyor: Paylaşılan belleğe erişim, segmentasyona veya diğer çalışma zamanı hatalarına neden olabilir.

Java'da CWE-416'nın anlamı


Otomatik çöp toplama yoluyla Java, serbest kullanım sonrası güvenlik açıkları da dahil olmak üzere pek çok bellek yönetimi sorununa karşı doğal olarak koruma sağlar. Ancak, bellek dışındaki kaynaklar (dosya tanıtıcıları veya ağ bağlantıları gibi) düzgün şekilde işlenmezse Java'da UAF'ye benzer sorunlar ortaya çıkabilir. Aşağıda Java'da UAF'ye benzer bazı senaryolar ve bunları hafifletmeye yönelik stratejiler bulunmaktadır.

Senaryo 1: Dış kaynakların kötü yönetimi

Java'daki bellek çöp toplayıcı (GC) tarafından yönetilse de, dosya tanıtıcıları veya ağ yuvaları gibi diğer kaynaklar yanlış şekilde işlenebilir ve kapatma sonrası kullanım sorunlarına neden olabilir.

Kod örneği:


import java.io.*;

public class UseAfterFreeExample {
public static void main(String[] args) {
FileInputStream fis = null;
try {
fis = new FileInputStream("example.txt");
// Use the file input stream...
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

// Attempt to use the file input stream after it has been closed
try {
int data = fis.read(); // This will throw an IOException
} catch (IOException e) {
System.out.println("Attempted to read from a closed stream.");
}
}
}


Bu örnekte, dosya kapatıldıktan sonra kaynaktan okuma girişimi başarısız oluyor FileInputStream birine IOException.

Try-With-Resources ile otomatik kaynak yönetimi:

Java 7'de tanıtılan Try-With-Resources deyimini kullanır ve bu, her kaynağın deyimin sonunda kapatılmasını sağlar.


import java.io.*;

public class UseAfterFreeFixed {
public static void main(String[] args) {
try (FileInputStream fis = new FileInputStream("example.txt")) {
// Use the file input stream...
} catch (IOException e) {
e.printStackTrace();
}

// fis is automatically closed here
// Attempting to use fis here will cause a compilation error
}
}


Açık hükümsüzlük beyanı:

Yanlışlıkla yeniden kullanımı önlemek için kapattıktan sonra referansları sıfıra ayarlayın.


import java.io.*;

public class UseAfterFreeWithNull {
public static void main(String[] args) {
FileInputStream fis = null;
try {
fis = new FileInputStream("example.txt");
// Use the file input stream...
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
fis = null; // Prevent reuse
}
}
}

// fis is now null, so the following attempt
// to use it will fail at compile-time
if (fis != null) {
try {
int data = fis.read(); // This will not compile since fis is null
} catch (IOException e) {
System.out.println("Attempted to read from a closed stream.");
}
}
}
}


Senaryo 2: Zayıf referansların uygunsuz kullanımı

Bu doğrudan bir UAF sorunu olmasa da, zayıf referansların uygunsuz kullanımı, çöp toplayıcı tarafından alındıktan sonra nesnelere erişirken yine de olumsuz sonuçlara yol açabilir.


import java.lang.ref.WeakReference;

public class WeakReferenceExample {
public static void main(String[] args) {
Object obj = new Object();
WeakReference<Object> weakRef = new WeakReference<>(obj);

obj = null; // Eligible for garbage collection

System.gc(); // Suggest garbage collection

// Attempt to use the object after it may have been collected
if (weakRef.get() != null) {
System.out.println("Object is still alive.");
} else {
System.out.println("Object has been garbage collected.");
}
}
}


Bu örnekte, güçlü referansı geçersiz kıldıktan ve çöp toplamayı önerdikten sonra, zayıf referansa erişim sıfırla sonuçlanabilir, bu da nesnenin GC tarafından zaten toplandığını gösterir. Hâlâ ihtiyaç duyulan kritik nesneler için zayıf referanslar kullanmaktan kaçının.

Zayıf bir referansı kullanmadan önce daima silinip silinmediğini kontrol edin:


if (weakRef.get() != null) {
// Safe to use the object
Object obj = weakRef.get();
// Use obj
} else {
// Handle the case where the object has been collected
System.out.println("Object has been garbage collected.");
}


Java'nın otomatik bellek yönetimi, geleneksel UAF güvenlik açıkları riskini azaltırken, geliştiricilerin benzer sorunları önlemek için kaynak yönetimine ve zayıf referanslara dikkat etmesi gerekiyor. Modern Java özellikleri gibi Try-with-Ressourcen ve nesne referanslarına saygı duymak, kodun sağlam ve hatasız korunmasına yardımcı olabilir.

Hangi CVE'ler Java'daki CWE-416'yı temel alır?


Java'daki CWE-416 güvenlik açıklarıyla ilgili olarak dikkate alınması gereken bazı CVE'ler şunlardır:

CVE-2022-45146

Bu güvenlik açığı, 1.0.2.4 sürümünden önceki Bouncy Castle BC-FJA FIPS Java API'sinde bulunuyor. Java 13 ve sonraki sürümlerde JVM çöp toplayıcısında yapılan değişiklikler bu sorunu tetikleyebilir ve modül tarafından kullanılan geçici anahtarların kullanımdayken sıfıra ayarlanmasına neden olabilir. Bu, hatalara veya potansiyel bilgi kaybına yol açar. Bu durum Java 7, 8 ve 11 için geçerli olduğundan FIPS uyumlu kullanıcılar etkilenmez.

CVE-2023-38703

Bu CVE, Java da dahil olmak üzere birçok dilde yazılan PJSIP multimedya iletişim kitaplığını etkiler. Sorun, daha yüksek seviyeli SRTP ortamı ile UDP gibi daha düşük seviyeli aktarım arasında senkronizasyon sağlanamadığında ortaya çıkar ve UAF güvenlik açığına neden olur. Bu, uygulamanın beklenmedik şekilde kapanmasına veya belleğin bozulmasına neden olabilir.

Açıklanan örnekler, dil, belleği çöp toplama yoluyla yönetse bile, Java uygulamalarında uygun bellek ve kaynak yönetiminin önemini göstermektedir. Bu güvenlik açıkları hakkında daha fazla bilgiyi Ulusal Güvenlik Açığı Veritabanında (NVD) veya GitHub ve mvnrepository gibi platformlardaki belirli uyarılarda bulabilirsiniz.
 
Üst