Cihaz güvenlik durumunu anlama

Uygulamanızın güvenliği, yalnızca temel işletim sisteminin güvenliği kadardır. Riski azaltmak için uygulamanız, cihazın güvenlik durumunun gerçek zamanlı değerlendirmesiyle güvenlikle ilgili hassas işlemleri kontrol etmelidir. Bu değerlendirme, cihazın (özellikle temel sistem bileşenlerinin) tamamen güncellenip güncellenmediğini ve Android Güvenlik Bülteni'nde yayınlanan güvenlik açıklarına karşı korunup korunmadığını belirler. Cihaz güvenliği durumunun görünürlüğü, uygulamanız yüksek riskli işlemler gerçekleştirmeden önce koruma önlemleri almanıza yardımcı olur.

AndroidX Security State, Android destekli bir cihazın güvenlik durumuna birleşik erişim sağlayan bir Jetpack kitaplığıdır. Yalnızca güvenlik yaması düzeyinin (SPL) ötesinde kapsamlı, hassas ve uygulanabilir bir cihaz güvenlik durumu sağlamak için AOSP API'lerini ve Android'in herkese açık güvenlik açığı feed'lerini birleştirir.

Mimariye genel bakış

Aşağıdaki diyagramda, AndroidX Security State kitaplığının cihaz üzerinde platform özelliklerini, işlemler arası iletişim (IPC) güncelleme sağlayıcılarını ve herkese açık güvenlik açığı feed'lerini tek bir tutarlı API kümesinde nasıl birleştirdiği gösterilmektedir.

AndroidX Security State kitaplığı, cihaz üzerindeki platform özelliklerini, IPC güncelleme sağlayıcılarını ve herkese açık güvenlik açığı feed'lerini bir dizi birleşik API'de birleştirir.

Güvenlik yaması durumları ve bileşenleri

Security State kitaplığını kullanmanın temel avantajı, güvenlik yaması seviyesini (SPL) ayrıntılı ve bileşen düzeyinde sağlayabilmesidir. Android, yıllar içinde Google Play sistem güncellemelerine (Project Mainline) daha fazla modül ekledi. Bu modüller, Google Play kullanılarak standart kablosuz sistem güncellemelerinden (OTA) bağımsız olarak güncellenir ve farklı bir sıklıkta kritik güvenlik düzeltmeleri sağlar.

Benzer şekilde, güvenlik yaması seviyesi genellikle gerekli minimum Generic Kernel Image (GKI) sürümünü zorunlu kılsa da çekirdek güncellemeleri aslında sistem planının önüne geçebilir. Çekirdeğe özgü bu düzeltmeler, sistemin birincil SPL dizesi tarafından tam olarak yakalanamayabilir.

Şeffaflığı artırmak için güvenlik durumu kitaplığı, üç bileşenin her biri için ayrı ayrı etkili bir yama düzeyi sağlar:

  • Sistem (COMPONENT_SYSTEM): Standart güvenlik yaması seviyesi alanından elde edilen standart işletim sistemi ve sistem güvenlik durumunu gösterir.
  • Sistem Mainline Modülleri (COMPONENT_SYSTEM_MODULES): Belirli modül yayın sürümlerinden elde edilen, modüler sistem bileşenlerinin (Google Play sistem güncellemeleri) güvenlik durumunu gösterir.
  • Çekirdek (COMPONENT_KERNEL): Cihaz çekirdeğinin güvenlik durumunu gösterir. Doğrudan çekirdek sürümü dizesinden elde edilir.

Kitaplık, bileşene bağlı olarak yama düzeyinde en fazla 3 boyutlu bilgi sağlar:

  • Cihaz SPL'si (DSPL): Cihazda çalışan tek tek bileşenlerin mevcut yama düzeyi. Ağ istekleri olmadan eşzamanlı olarak sorgulanır. Sistem ve Mainline takvim tarihlerini (DateBasedSecurityPatchLevel) bildirir, Çekirdek ise yayınlanan sürümünü (VersionedSecurityPatchLevel, örneğin 5.15.148) bildirir.
  • Yayınlanmış SPL (PSPL): Android Güvenlik Bülteni ve Açık Kaynak Güvenlik Açıkları (OSV) veritabanı raporlarında resmi olarak yayınlanan temel sürüm. Uygulamanız, Device SPL tarafından sağlanan tarihleri veya sürüm dizelerini karşılaştırarak uygunluğu değerlendirebilir.
  • Kullanılabilir SPL (ASPL): Bir cihazda, IPC kullanılarak eşzamansız olarak sorgulanan güncelleme sağlayıcılarından gelen bekleyen güncellemeler olup olmadığını gösterir. Android Google Play sistem güncellemesi özelliği, Mainline modüllerinin kullanılabilirliğini sağlar. OEM OTA istemcileri ise sistem güncellemelerinin kullanılabilirliğini sağlar. Çekirdek güncellemeleri işletim sistemi görüntüsüne dahil edildiğinden çekirdek güncelleme kullanılabilirliği COMPONENT_SYSTEM kullanılarak değerlendirilir.

Güvenliğe duyarlı özellikleri kontrol etme

Güvenliğe duyarlı özelliklerin kullanımını kısıtlamak için bağlamsal belirlemeler yapmak üzere Cihaz SPL'si (DSPL), Kullanılabilir SPL (ASPL) ve Yayınlanmış SPL'den (PSPL) gelen bilgileri birleştirebilirsiniz. Örneğin, kullanıcının henüz yüklemediği daha yeni bir güvenlik yaması olup olmadığını belirlemek için DSPL ile ASPL'yi karşılaştırabilir ve ödeme veya kimlik bilgisi kaydı gibi hassas işlemleri başlatmadan önce kullanıcıyı güncelleme yapmaya yönlendirebilirsiniz. Ayrıca, savunmasız alt sistemleri çağırmadan önce cihazda belirli yüksek riskli güvenlik açıklarının giderilip giderilmediğini doğrulamak için areCvesPatched() kullanabilirsiniz. Örneğin, temassız ödemeleri veya veri paylaşımını yetkilendirmeden önce kritik NFC veya Bluetooth güvenlik açıklarını kontrol edebilirsiniz.

Platform sürümüyle ilgili dikkat edilmesi gereken noktalar

Belirli güvenlik durumu özellikleri, temel platform mimarisine bağlıdır ve Android'in eski sürümlerinde kullanılamaz:

  • Android 11 (API düzeyi 30) ve sonraki sürümler: Bültende yayınlanan çekirdek LTS sürümleri ve güncelleme kullanılabilirliği (ASPL) sorguları dahil olmak üzere tüm bileşenler için tam destek.
  • Android 10 (API düzeyi 29): Sistem ve sistem modülü yama düzeylerini destekler ancak Android Güvenlik Bülteni'nde Genel Çekirdek Görüntüsü (GKI) takibi ve çekirdek LTS hedefleri Android 11'de başladığından bültenle yayınlanan çekirdek sürümleri kullanılamaz. Cihaz üzerindeki çekirdek sürümü yine de yerel olarak okunabilir.
  • Android 9 (API düzeyi 28) ve önceki sürümler: Android 10'daki sınırlamalara ek olarak, modüler sistem bileşenleri (Project Mainline) Android 10'dan önce mevcut değildi. Sistem modülü SPL'leri kullanılamadığında getDeviceSecurityPatchLevel(COMPONENT_SYSTEM_MODULES) güvenli bir şekilde temel Unix dönemi tarihine (1970-01-01) geri döner.

Güncelleme kullanılabilirliği ve Kullanılabilir SPL (ASPL) hakkında bilgi

Bir cihazın güvenlik durumunu belirlemek için, bekleyen güvenlik güncellemelerinin tek tek bileşenler için kullanılabilir olup olmadığını bilmek gerekir. Android cihazlar, modüler bileşenler için sistem kablosuz (OTA) güncellemeleri ve Google Play sistem güncellemeleri gibi birden fazla farklı dağıtım mekanizması aracılığıyla güvenlik güncellemeleri alır.

Uygulamanızın belirli bir bileşenin ASPL'sini alabilmesi için ilgili güncelleme sağlayıcının bu bilgileri yayınlaması gerekir. İstemci uygulamaları, bu farklı güncelleme kaynakları arasında koordinasyon sağlamak için güvenlik durumunu sorgulamak üzere AndroidX Security State kitaplığını kullanır. Cihazdaki güncelleme istemcileri ise Kullanılabilir Güvenlik Yaması Seviyelerini (ASPL) yayınlamak için yardımcı AndroidX Security State Provider kitaplığını kullanır.

Google, Google OTA istemcisini (GOTA) kullanan cihazlar için sistem OTA bilgileriyle birlikte tüm GMS Android cihazlara Mainline modülleriyle ilgili güncelleme bilgileri sağlar.

Aşağıdaki diyagramda, istemci uygulamalarının hem Google Play sistem güncellemeleri hem de sistem OTA güncellemeleri genelinde güvenlik duruşunu sorgulamak için AndroidX Security State kitaplığını nasıl kullandığı gösterilmektedir:

İstemci uygulamaları, hem Google Play sistem güncellemeleri hem de sistem OTA güncellemeleri genelinde güvenlik durumunu sorgulamak için AndroidX Security State kitaplığını kullanır.

Bağımlılık ekleme

AndroidX Security State'e bağımlılık eklemek için projenize Google Maven deposunu dahil etmeniz gerekir. Bağımlılığı uygulamanızın build.gradle.kts veya build.gradle dosyasına ekleyin:

Kotlin

// Kotlin DSL (build.gradle.kts)
dependencies {
    implementation("androidx.security:security-state:1.1.0")
}

Modern

// Groovy DSL (build.gradle)
dependencies {
    implementation "androidx.security:security-state:1.1.0"
}

Beyan edilen izinler matrisi

Hedef API'ler AndroidManifest.xml'da Gerekli İzinler Operasyonel Notlar
getDeviceSecurityPatchLevel() Yok Yerel yerel sistem özelliklerini ve paket meta verilerini eşzamanlı olarak okur.
fetchAvailableSecurityPatchLevel()
queryAllAvailableUpdates()
Yok Cihaz üzerindeki IPC'yi kullanarak iletişim kurar. Kitaplık yalnızca cihazdaki güvenilir bileşenleri sorgular (güncelleme sağlayıcıların ayrıcalıklı READ_PRIVILEGED_PHONE_STATE iznine sahip olmasını gerektirir). Bu nedenle, uygulamanız aldığı bilgilerin doğruluğundan emin olabilir.
createVulnerabilityReportUrl()
loadVulnerabilityReport()
getPublishedSecurityPatchLevel()
areCvesPatched()
isDeviceFullyUpdated()
android.permission.INTERNET Herkese açık OSV raporlarını getirmek için gereklidir. loadVulnerabilityReport() kullanılarak belleğe yüklendikten sonra sorgulama yöntemleri, ağ erişimi olmadan yerel olarak yürütülür.

Kitaplığı başlatma

SecurityPatchState cihazını Android Context ile başlatın:

Kotlin

import androidx.security.state.SecurityPatchState

val securityPatchState = SecurityPatchState(context)

Java

import androidx.security.state.SecurityPatchState;

SecurityPatchState securityPatchState = new SecurityPatchState(context);

Yalnızca context ile başlatma, ağ bağımlılıkları olmadan çevrimdışı cihaz yama seviyelerine anında erişim sağlar. Güncelleme kullanılabilirlik sorguları cihaz üzerindeki sağlayıcılarla eşzamansız olarak iletişim kurar).

Uygulamanız CVE uyumluluğunu değerlendiriyorsa ve belleğe zaten bir OSV güvenlik açığı raporu yüklediyse Kotlin arayanlar JSON dizesini doğrudan Kotlin'deki oluşturucuya iletebilir:

val securityPatchState = SecurityPatchState(context, vulnerabilityReportJsonString = jsonString)

Java'da veya başlangıçtan sonra raporlar eşzamansız olarak yüklenirken bağlamla başlatın ve securityPatchState.loadVulnerabilityReport(jsonString) işlevini çağırın.

Cihaz yama seviyelerini kontrol etme

Cihaz üzerinde yama düzeylerini eşzamanlı olarak sorgulama:

Kotlin

val deviceSpl = securityPatchState.getDeviceSecurityPatchLevel(SecurityPatchState.COMPONENT_SYSTEM)
val mainlineSpl = securityPatchState.getDeviceSecurityPatchLevel(SecurityPatchState.COMPONENT_SYSTEM_MODULES)
val kernelVersion = securityPatchState.getDeviceSecurityPatchLevel(SecurityPatchState.COMPONENT_KERNEL)

// Gatekeeping check: compare against a required baseline patch date
val requiredSpl = SecurityPatchState.DateBasedSecurityPatchLevel.fromString("2026-01-01")
if (deviceSpl < requiredSpl) {
    // Restrict access to sensitive features or guide user to update
}

Java

SecurityPatchState.SecurityPatchLevel deviceSpl = securityPatchState.getDeviceSecurityPatchLevel(SecurityPatchState.COMPONENT_SYSTEM);
SecurityPatchState.SecurityPatchLevel mainlineSpl = securityPatchState.getDeviceSecurityPatchLevel(SecurityPatchState.COMPONENT_SYSTEM_MODULES);
SecurityPatchState.SecurityPatchLevel kernelVersion = securityPatchState.getDeviceSecurityPatchLevel(SecurityPatchState.COMPONENT_KERNEL);

// Gatekeeping check: compare against a required baseline patch date
SecurityPatchState.SecurityPatchLevel requiredSpl = SecurityPatchState.DateBasedSecurityPatchLevel.fromString("2026-01-01");
if (deviceSpl.compareTo(requiredSpl) < 0) {
    // Restrict access to sensitive features or guide user to update
}

Bekleyen sistem güncellemelerini kontrol etme

Uygulamalar, cihaz üzerindeki güvenilir güncelleme sağlayıcılarla (en yaygın olarak Google Play sistem güncellemeleri ve OEM OTA istemcileri) eşzamansız olarak iletişim kurarak bekleyen güncelleme kullanılabilirliğini değerlendirebilir:

  • fetchAvailableSecurityPatchLevel(): Belirtilen bir bileşen için geçerli olan Kullanılabilir SPL'yi döndürür (daha yeni bir güncelleme yoksa mevcut Cihaz SPL'sine geri döner). Bu SPL, Cihaz SPL'si ve Yayınlanan SPL ile karşılaştırmak için kullanılabilir.
  • queryAllAvailableUpdates(): Cihazdaki tüm güvenilir güncelleme sağlayıcıları keşfeder ve kaynakla ilgili meta veriler ile verilerin güncelliğiyle birlikte ayrıntılı UpdateCheckResult döndürür.

1. örnek: Kullanıcılardan bekleyen güncellemeleri yapmalarını isteme

Güvenlik güncellemeleri kullanıma sunulduğunda kullanıcılardan güncelleme yapmalarını istemek için fetchAvailableSecurityPatchLevel() özelliğini kullanın (örneğin, Settings.ACTION_SYSTEM_UPDATE_SETTINGS'ı başlatarak):

Kotlin

import androidx.lifecycle.lifecycleScope
import androidx.security.state.SecurityPatchState
import kotlinx.coroutines.launch

// Pattern A: Prompt users for pending updates (with automatic offline fallback)
lifecycleScope.launch {
    val currentSpl = securityPatchState.getDeviceSecurityPatchLevel(SecurityPatchState.COMPONENT_SYSTEM)
    val availableSpl = securityPatchState.fetchAvailableSecurityPatchLevel(SecurityPatchState.COMPONENT_SYSTEM)
    if (availableSpl > currentSpl) {
        // Prompt the user to install pending updates in system settings
    }
}

Java

Java'da eşzamansız yöntemler ListenableFuture döndürür ve ContextCompat.getMainExecutor() kullanarak geri çağırmaları yönlendirir:

import androidx.core.content.ContextCompat;
import androidx.security.state.SecurityPatchState;
import androidx.security.state.SecurityPatchState.SecurityPatchLevel;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;

// Pattern A: Prompt users for pending updates (with automatic offline fallback)
SecurityPatchLevel currentSpl = securityPatchState.getDeviceSecurityPatchLevel(SecurityPatchState.COMPONENT_SYSTEM);
ListenableFuture<SecurityPatchLevel> availableSpl = securityPatchState.fetchAvailableSecurityPatchLevelAsync(
    SecurityPatchState.COMPONENT_SYSTEM,
    SecurityPatchState.UPDATE_INFO_SERVICE_BINDING_TIMEOUT_MS
);

Futures.addCallback(availableSpl, new FutureCallback<SecurityPatchLevel>() {
    @Override
    public void onSuccess(SecurityPatchLevel available) {
        if (available.compareTo(currentSpl) > 0) {
            // Prompt the user to install pending updates in system settings
        }
    }

    @Override
    public void onFailure(Throwable t) {
        // Handle timeout or IPC communication error
    }
}, ContextCompat.getMainExecutor(context));

2. örnek: Ayrıntılı sağlayıcı durumunu inceleme

Tek tek sağlayıcıları, zaman damgalarını ve UpdateInfo kayıtlarını incelemek için queryAllAvailableUpdates() simgesini kullanın:

Kotlin

import androidx.lifecycle.lifecycleScope
import androidx.security.state.SecurityPatchState
import kotlinx.coroutines.launch

// Pattern B: Inspect detailed provider status
lifecycleScope.launch {
    val updateResults = securityPatchState.queryAllAvailableUpdates()
    for (result in updateResults) {
        val provider = result.providerPackageName
        val lastCheck = result.lastCheckTimeMillis
        val updates = result.updates // List<UpdateInfo>
    }
}

Java

import androidx.core.content.ContextCompat;
import androidx.security.state.SecurityPatchState;
import androidx.security.state.UpdateCheckResult;
import androidx.security.state.UpdateInfo;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import java.util.List;

// Pattern B: Inspect detailed provider status
ListenableFuture<List<UpdateCheckResult>> updateResults = securityPatchState.queryAllAvailableUpdatesAsync(
    SecurityPatchState.UPDATE_INFO_SERVICE_BINDING_TIMEOUT_MS
);

Futures.addCallback(updateResults, new FutureCallback<List<UpdateCheckResult>>() {
    @Override
    public void onSuccess(List<UpdateCheckResult> results) {
        for (UpdateCheckResult result : results) {
            String provider = result.getProviderPackageName();
            long lastCheck = result.getLastCheckTimeMillis();
            List<UpdateInfo> updates = result.getUpdates();
        }
    }

    @Override
    public void onFailure(Throwable t) {
        // Handle error
    }
}, ContextCompat.getMainExecutor(context));

Güvenlik açığı çözümünü doğrulama ve CVE'leri kontrol etme

CVE azaltma yöntemlerini değerlendirmek, genel güncelleme uygunluğunu kontrol etmek veya Yayınlanan Güvenlik Yaması Seviyelerini (PSPL) incelemek için uygulamanızın önce API reference for SecurityPatchState bölümünde ayrıntılı olarak açıklandığı gibi bir OSV güvenlik açığı raporu alıp yüklemesi gerekir.

Kotlin

// Load vulnerability report
val reportUrl = SecurityPatchState.createVulnerabilityReportUrl()
// ... download JSON string from reportUrl ...
securityPatchState.loadVulnerabilityReport(jsonString)

// Check overall update compliance against published bulletin
val isFullyUpdated = securityPatchState.isDeviceFullyUpdated()

val cves = listOf("CVE-2019-9501", "CVE-2020-3699", "CVE-2024-0016")
val isPatched = securityPatchState.areCvesPatched(cves)

// Get a list of all patched CVEs for a specific component and SPL
val deviceSpl = securityPatchState.getDeviceSecurityPatchLevel(SecurityPatchState.COMPONENT_SYSTEM)
val patchedSystemCVEs = securityPatchState.getPatchedCves(SecurityPatchState.COMPONENT_SYSTEM, deviceSpl)

// Inspect published SPL and kernel LTS target versions from the bulletin
val publishedSystemSpl = securityPatchState.getPublishedSecurityPatchLevel(SecurityPatchState.COMPONENT_SYSTEM)
val kernelLtsTargets = securityPatchState.getPublishedSecurityPatchLevel(SecurityPatchState.COMPONENT_KERNEL)

Java

// Load vulnerability report
Uri reportUrl = SecurityPatchState.createVulnerabilityReportUrl();
// ... download JSON string from reportUrl ...
securityPatchState.loadVulnerabilityReport(jsonString);

// Check overall update compliance against published bulletin
boolean isFullyUpdated = securityPatchState.isDeviceFullyUpdated();

List<String> cves = Arrays.asList("CVE-2019-9501", "CVE-2020-3699", "CVE-2024-0016");
boolean isPatched = securityPatchState.areCvesPatched(cves);

// Get a list of all patched CVEs for a specific component and SPL
SecurityPatchState.SecurityPatchLevel deviceSpl = securityPatchState.getDeviceSecurityPatchLevel(SecurityPatchState.COMPONENT_SYSTEM);
Map<SecurityPatchState.Severity, Set<String>> patchedSystemCVEs =
    securityPatchState.getPatchedCves(SecurityPatchState.COMPONENT_SYSTEM, deviceSpl);

// Inspect published SPL and kernel LTS target versions from the bulletin
List<SecurityPatchState.SecurityPatchLevel> publishedSystemSpl =
    securityPatchState.getPublishedSecurityPatchLevel(SecurityPatchState.COMPONENT_SYSTEM);
List<SecurityPatchState.SecurityPatchLevel> kernelLtsTargets =
    securityPatchState.getPublishedSecurityPatchLevel(SecurityPatchState.COMPONENT_KERNEL);

Güvenlik açığı raporlarını yükleme

  1. Yerel Önbelleğe Alma ve WorkManager Yenileme: Android Güvenlik Bültenleri aylık olarak yayınlandığından, indirilen JSON'u dahili depolama alanında önbelleğe alın (context.filesDir) ve raporu yenilemek için WorkManager ile düzenli bir arka plan görevi planlayın (tercihen 24-48 saatte bir). Bu sayede, uygulama başlatıldığında yerel önbellekten eşzamanlı olarak okuma yapılır.
  2. Arka planda iş parçacığı oluşturma: CVE kayıtları ayrıştırılırken ana kullanıcı arayüzü iş parçacığının engellenmesini önlemek için arka planda iş parçacığında loadVulnerabilityReport() çağrısı yapın (Kotlin'de Dispatchers.IO veya Java'da Executor).
  3. Kernel LTS Değerlendirmesi: getPatchedCves(COMPONENT_KERNEL, ...) çağrıldığında IllegalArgumentException oluşturulur ve areCvesPatched(), çekirdek CVE'lerini değerlendirmez. Bunun yerine, cihazın çekirdek sürümünü, getPublishedSecurityPatchLevel(COMPONENT_KERNEL) tarafından döndürülen Android Common Kernel LTS hedefleri ile karşılaştırarak çekirdek güvenliğini değerlendirin.Bu karşılaştırma, ana ve alt dalların eşleştirilmesiyle yapılır (ör. 5.15.140 çekirdeğini 5.15.159 hedefiyle karşılaştırma).

Ek kaynaklar

Cihaz güvenliği durumu hakkında daha fazla bilgi için aşağıdaki kaynaklara bakın:

Belgeler

API referansı