OWASP kategorisi: MASVS-STORAGE: Depolama
Genel Bakış
Günlük Bilgilerinin Açıklanması, uygulamaların hassas verileri cihaz günlüğüne yazdığı bir güvenlik açığı türüdür. Kötü niyetli kişilerin eline geçen bu hassas bilgiler, doğrudan değerli olabilir (ör. kullanıcının kimlik bilgileri veya kimliği tanımlayabilecek bilgiler (PII)) ya da başka saldırılara olanak tanıyabilir.
Bu sorun aşağıdaki senaryolardan herhangi birinde ortaya çıkabilir:
- Uygulama tarafından oluşturulan günlükler:
- Günlükler, yetkisiz kişilerin erişimine kasıtlı olarak izin veriyor ancak hassas veriler içeriyor.
- Günlükler kasıtlı olarak hassas veriler içerir ancak yetkisiz kişiler tarafından yanlışlıkla erişilebilir.
- Bazen tetiklenen hata mesajına bağlı olarak hassas verileri yazdırabilen genel hata günlükleri.
- Harici olarak oluşturulan günlükler:
- Harici bileşenler, hassas veriler içeren günlükleri yazdırmaktan sorumludur.
Android Log.* ifadeleri, ortak bellek arabelleğine yazılır logcat. Android 4.1'den (API düzeyi 16) itibaren, yalnızca ayrıcalıklı sistem uygulamalarına READ_LOGS izni bildirilerek logcat okuma erişimi verilebilir. Ancak Android, önceden yüklenmiş uygulamaları bazen READ_LOGS ayrıcalığını bildiren çok çeşitli cihazları destekler. Bu nedenle, veri sızıntısına daha yatkın olduğundan doğrudan logcat'ya günlük kaydı oluşturmanız önerilmez.
Uygulamanızın hata ayıklama yapılmayan sürümlerinde logcat ile ilgili tüm günlük kayıtlarının temizlendiğinden emin olun. Hassas olabilecek tüm verileri kaldırın. Ek bir önlem olarak, uyarı ve hata dışındaki tüm günlük düzeylerini kaldırmak için R8 gibi araçları kullanın. Daha ayrıntılı günlüklere ihtiyacınız varsa sistem günlüğünü kullanmak yerine dahili depolamayı kullanın ve kendi günlüklerinizi doğrudan yönetin.
Etki
Günlük Bilgisi Açıklama güvenlik açığı sınıfının önem düzeyi, bağlama ve hassas veri türüne bağlı olarak değişebilir. Genel olarak, bu güvenlik açığı sınıfının etkisi, kimliği tanımlayabilecek bilgiler ve kimlik bilgileri gibi kritik olabilecek bilgilerin gizliliğinin kaybolmasıdır.
Çözümler
Genel
Tasarım ve uygulama sırasında genel bir önleyici tedbir olarak, en az ayrıcalık ilkesine göre güven sınırları çizin. İdeal olarak, hassas veriler güven alanlarının dışına çıkmamalı veya bu alanlara ulaşmamalıdır. Bu, ayrıcalıkların ayrılmasını güçlendirir.
Hassas verileri günlüğe kaydetmeyin. Mümkün olduğunda yalnızca derleme zamanı sabitlerini günlüğe kaydedin. Derleme zamanı sabit notu için ErrorProne aracını kullanabilirsiniz.
Hata tetiklenmesine bağlı olarak hassas veriler de dahil olmak üzere beklenmedik bilgiler içerebilecek ifadeleri yazdıran günlüklerden kaçının. Günlüklerde ve hata günlüklerinde yazdırılan veriler mümkün olduğunca yalnızca tahmin edilebilir bilgileri içermelidir.
logcat'a günlük kaydı oluşturmaktan kaçının. Bunun nedeni, READ_LOGS iznine sahip uygulamalar nedeniyle logcat'ya giriş yapmanın gizlilik sorunu haline gelebilmesidir. Ayrıca uyarı tetikleyemediği veya sorgulanamadığı için etkili değildir. Uygulamaların logcat arka ucunu yalnızca geliştirici derlemeleri için yapılandırması önerilir.
Çoğu günlük yönetimi kitaplığı, günlük düzeylerinin tanımlanmasına olanak tanır. Bu sayede hata ayıklama ve üretim günlükleri arasında farklı miktarlarda bilgi günlüğe kaydedilebilir. Ürün testi sona erer ermez günlük düzeyini "debug" dışında bir değere değiştirin.
Üretimden mümkün olduğunca çok günlük düzeyini kaldırın. Günlükleri üretimde tutmaktan kaçınamıyorsanız sabit olmayan değişkenleri günlük ifadelerinden kaldırın. Aşağıdaki senaryolar yaşanabilir:
- Üretim kanalındaki tüm günlükleri kaldırabilirsiniz.
- Üretimde uyarı ve hata günlüklerini tutmanız gerekir.
Bu iki durumda da R8 gibi kitaplıkları kullanarak günlükleri otomatik olarak kaldırın. Günlükleri manuel olarak kaldırma girişimleri hataya açıktır. R8, kod optimizasyonunun bir parçası olarak hata ayıklama için saklamak istediğiniz ancak üretimde kaldırılacak günlük düzeylerini güvenli bir şekilde kaldıracak şekilde ayarlanabilir.
Üretimde oturum açacaksanız bir olay olması durumunda günlüğü koşullu olarak kapatmak için kullanabileceğiniz flag'leri hazırlayın. Olay yanıtı işaretleri; dağıtım güvenliği, dağıtım hızı ve kolaylığı, günlüklerin düzeltilmesinin kapsamlılığı, bellek kullanımı ve her günlük mesajının taranmasının performans maliyetleri gibi konulara öncelik vermelidir.
R8'i kullanarak üretim derlemelerinden logcat'e günlükleri ayıklayın.
Android Studio 3.4 veya Android Gradle eklentisinin 3.4.0 ve sonraki sürümlerinde R8, kod optimizasyonu ve küçültme için varsayılan derleyicidir. Ancak R8'i etkinleştirmeniz gerekir.
R8, ProGuard'ın yerini aldı ancak projenin kök klasöründeki kurallar dosyası hâlâ proguard-rules.pro olarak adlandırılıyor.Aşağıdaki snippet, uyarılar ve hatalar hariç tüm günlükleri üretimden kaldıran örnek bir proguard-rules.pro dosyasını gösteriyor:
-assumenosideeffects class android.util.Log {
private static final String TAG = "MyTAG";
public static boolean isLoggable(java.lang.String, int);
public static int v(TAG, "My log as verbose");
public static int d(TAG, "My log as debug");
public static int i(TAG, "My log as information");
}
Aşağıdaki örnek proguard-rules.pro dosyası, üretimdeki tüm günlükleri kaldırır:
-assumenosideeffects class android.util.Log {
private static final String TAG = "MyTAG";
public static boolean isLoggable(java.lang.String, int);
public static int v(TAG, "My log as verbose");
public static int d(TAG, "My log as debug");
public static int i(TAG, "My log as information");
public static int w(TAG, "My log as warning");
public static int e(TAG, "My log as error");
}
R8'in uygulama küçültme ve günlük temizleme işlevleri sunduğunu unutmayın. R8'i yalnızca günlükleri temizleme işlevi için kullanmak istiyorsanız proguard-rules.pro dosyanıza aşağıdakileri ekleyin:
-dontwarn **
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontpreverify
-verbose
-optimizations !code/simplification/arithmetic,!code/allocation/variable
-keep class **
-keepclassmembers class *{*;}
-keepattributes *
Üretimdeki hassas veriler içeren tüm günlükleri temizleyin.
Hassas verilerin sızmasını önlemek için uygulamanızın hata ayıklama içermeyen sürümlerinde logcat ile ilgili tüm günlüklerin temizlendiğinden emin olun. Hassas olabilecek tüm verileri kaldırın.
Örnek:
Kotlin
data class Credential<T>(val data: String) {
/** Returns a redacted value to avoid accidental inclusion in logs. */
override fun toString() = "Credential XX"
}
fun checkNoMatches(list: List<Any>) {
if (!list.isEmpty()) {
Log.e(TAG, "Expected empty list, but was %s", list)
}
}
Java
public class Credential<T> {
private T t;
/** Returns a redacted value to avoid accidental inclusion in logs. */
public String toString(){
return "Credential XX";
}
}
private void checkNoMatches(List<E> list) {
if (!list.isEmpty()) {
Log.e(TAG, "Expected empty list, but was %s", list);
}
}
Günlüklerdeki hassas verileri çıkarma
Günlüklerinize hassas veriler eklemeniz gerekiyorsa hassas verileri kaldırmak veya karartmak için yazdırmadan önce günlükleri temizlemenizi öneririz. Bunu yapmak için aşağıdaki tekniklerden birini kullanın:
- Jetonlaştırma. Hassas veriler, jetonlar aracılığıyla gizli anahtarlara referans verilebilen bir şifreleme yönetim sistemi gibi bir kasada depolanıyorsa hassas veriler yerine jetonu günlüğe kaydedin.
- Veri maskeleme. Veri maskeleme, tek yönlü ve geri döndürülemez bir süreçtir. Hassas verilerin, orijinaline yapısal olarak benzeyen ancak bir alanda bulunan en hassas bilgileri gizleyen bir sürümünü oluşturur. Örnek: Kredi kartı numarasının
1234-5678-9012-3456ile değiştirilmesi.XXXX-XXXX-XXXX-1313Uygulamanızı üretime yayınlamadan önce, veri maskeleme kullanımını incelemek için bir güvenlik inceleme süreci tamamlamanızı öneririz. Uyarı: Hassas verilerin yalnızca bir kısmının yayınlanmasının bile güvenliği önemli ölçüde etkileyebileceği durumlarda (ör. şifreleri işlerken) veri maskeleme kullanmayın. - Redaksiyon. Redaksiyon, maskelemeye benzer ancak bir alanda bulunan tüm bilgileri gizler. Örnek: Kredi kartı numarasının
1234-5678-9012-3456ile değiştirilmesi.XXXX-XXXX-XXXX-XXXX - Filtreleme Günlük ifadelerindeki sabit olmayan değerlerin değiştirilmesini kolaylaştırmak için, henüz yoksa tercih ettiğiniz günlük kaydı kitaplığınıza biçim dizeleri uygulayın.
Günlük yazdırma işlemi yalnızca aşağıdaki kod snippet'inde gösterildiği gibi, tüm günlüklerin yazdırılmadan önce temizlenmesini sağlayan bir "günlük temizleyici" bileşeni aracılığıyla yapılmalıdır.
Kotlin
data class ToMask<T>(private val data: T) {
// Prevents accidental logging when an error is encountered.
override fun toString() = "XX"
// Makes it more difficult for developers to invoke sensitive data
// and facilitates sensitive data usage tracking.
fun getDataToMask(): T = data
}
data class Person(
val email: ToMask<String>,
val username: String
)
fun main() {
val person = Person(
ToMask("name@gmail.com"),
"myname"
)
println(person)
println(person.email.getDataToMask())
}
Java
public class ToMask<T> {
// Prevents accidental logging when an error is encountered.
public String toString(){
return "XX";
}
// Makes it more difficult for developers to invoke sensitive data
// and facilitates sensitive data usage tracking.
public T getDataToMask() {
return this;
}
}
public class Person {
private ToMask<String> email;
private String username;
public Person(ToMask<String> email, String username) {
this.email = email;
this.username = username;
}
}
public static void main(String[] args) {
Person person = new Person(
ToMask("name@gmail.com"),
"myname"
);
System.out.println(person);
System.out.println(person.email.getDataToMask());
}