Poziom bezpieczeństwa aplikacji jest równy poziomowi bezpieczeństwa systemu operacyjnego, na którym działa. Aby zmniejszyć ryzyko, aplikacja powinna ograniczać operacje wrażliwe pod względem bezpieczeństwa za pomocą oceny w czasie rzeczywistym stanu bezpieczeństwa urządzenia. Ocena ta powinna określać, czy urządzenie, a zwłaszcza jego podstawowe komponenty systemowe, jest w pełni zaktualizowane i chronione przed lukami w zabezpieczeniach opublikowanymi w biuletynie bezpieczeństwa Androida. Wgląd w stan zabezpieczeń urządzenia pomaga wprowadzać zabezpieczenia, zanim aplikacja wykona operacje wysokiego ryzyka.
AndroidX Security State to biblioteka Jetpack, która zapewnia ujednolicony dostęp do stanu zabezpieczeń urządzenia z Androidem. Łączy interfejsy API AOSP i publiczne kanały informacji o lukach w zabezpieczeniach Androida, aby zapewnić kompleksowy, precyzyjny i przydatny stan zabezpieczeń urządzenia, który wykracza poza poziom aktualizacji zabezpieczeń.
Omówienie architektury
Diagram poniżej pokazuje, jak biblioteka AndroidX Security State ujednolica właściwości platformy na urządzeniu, dostawców aktualizacji komunikacji międzyprocesowej (IPC) i publiczne kanały informacji o lukach w zabezpieczeniach w jeden spójny zestaw interfejsów API.

Stany i komponenty poprawek zabezpieczeń
Główną zaletą korzystania z biblioteki Security State jest możliwość podawania poziomu aktualizacji zabezpieczeń na poziomie poszczególnych komponentów. Z biegiem lat Android wprowadził więcej modułów do aktualizacji systemowych Google Play (Project Mainline), które są aktualizowane za pomocą Google Play niezależnie od standardowych aktualizacji systemowych OTA, co zapewnia krytyczne poprawki zabezpieczeń w różnych odstępach czasu.
Podobnie jak poziom aktualizacji zabezpieczeń zwykle określa minimalną wymaganą wersję ogólnego obrazu jądra (GKI), aktualizacje jądra mogą wyprzedzać harmonogram systemu. Te poprawki dotyczące jądra mogą nie być w pełni uwzględnione w głównym ciągu znaków SPL systemu.
Aby zwiększyć przejrzystość, biblioteka stanu zabezpieczeń udostępnia efektywny poziom poprawek dla każdego z 3 komponentów z osobna:
- System (
COMPONENT_SYSTEM): reprezentuje standardowy system operacyjny i stan zabezpieczeń systemu pochodzący ze standardowego pola poziomu aktualizacji zabezpieczeń. - Moduły systemowe Mainline (
COMPONENT_SYSTEM_MODULES): określają stan zabezpieczeń modułowych komponentów systemu (aktualizacji systemu Google Play) na podstawie konkretnych wersji modułów. - Jądro (
COMPONENT_KERNEL): reprezentuje stan bezpieczeństwa jądra urządzenia, który jest określany bezpośrednio na podstawie ciągu wersji jądra.
W zależności od komponentu biblioteka udostępnia do 3 wymiarów informacji o poziomie poprawki:
- Poziom poprawek urządzenia (DSPL): bieżący poziom poprawek poszczególnych komponentów działających na urządzeniu, odpytywany synchronicznie bez wysyłania żądań sieciowych. Daty w kalendarzu raportów dotyczących systemu i głównej linii rozwoju (
DateBasedSecurityPatchLevel), a raporty dotyczące jądra zawierają wersję do publikacji (VersionedSecurityPatchLevel, np.5.15.148). - Opublikowana lista SPL (PSPL): oficjalna lista bazowa opublikowana w biuletynie bezpieczeństwa Androida i raportach bazy danych Open Source Vulnerabilities (OSV). Aplikacja może ocenić zgodność, porównując daty lub ciągi znaków wersji podane przez Device SPL.
- Dostępny SPL (ASPL): wskazuje, czy urządzenie ma oczekujące aktualizacje
dostępne od dostawców aktualizacji, o które zapytano asynchronicznie za pomocą IPC. Funkcja aktualizacji systemowej Google Play na Androidzie zapewnia dostępność modułów Mainline, a klienci OTA OEM zapewniają dostępność aktualizacji systemu. Ponieważ aktualizacje jądra są dołączane do obrazu systemu operacyjnego, ich dostępność jest oceniana za pomocą
COMPONENT_SYSTEM.
Ograniczanie dostępu do funkcji wymagających szczególnej ochrony
Możesz łączyć informacje z listy SPL urządzenia (DSPL), listy SPL dostępnej (ASPL) i listy SPL opublikowanej (PSPL), aby podejmować kontekstowe decyzje dotyczące blokowania funkcji wrażliwych na bezpieczeństwo. Możesz na przykład porównać DSPL z ASPL, aby sprawdzić, czy jest dostępna nowsza poprawka zabezpieczeń, której użytkownik jeszcze nie zainstalował. W takim przypadku możesz poprosić go o aktualizację przed rozpoczęciem operacji wymagających zachowania szczególnej ostrożności, takich jak płatności czy rejestracja danych logowania. Możesz też używać areCvesPatched(), aby sprawdzić, czy na urządzeniu usunięto konkretne luki w zabezpieczeniach o wysokim ryzyku, zanim wywołasz podatne na ataki podsystemy, np. sprawdzić, czy nie ma krytycznych luk w zabezpieczeniach NFC lub Bluetooth, zanim autoryzujesz płatności zbliżeniowe lub udostępnianie danych.
Uwagi dotyczące wersji platformy
Niektóre funkcje związane ze stanem zabezpieczeń zależą od architektury platformy i są niedostępne w starszych wersjach Androida:
- Android 11 (poziom interfejsu API 30) i nowszy: pełna obsługa wszystkich komponentów, w tym opublikowanych w biuletynie wersji LTS jądra i zapytań o dostępność aktualizacji (ASPL).
- Android 10 (poziom interfejsu API 29): obsługuje poziomy poprawek systemu i modułu systemowego, ale wersje jądra opublikowane w biuletynie są niedostępne, ponieważ śledzenie podstawowego obrazu jądra (GKI) i docelowych wersji jądra LTS w biuletynie zabezpieczeń Androida rozpoczęło się w Androidzie 11. Wersję jądra na urządzeniu można nadal odczytywać lokalnie.
- Android 9 (poziom API 28) i starsze wersje: oprócz ograniczeń Androida 10, modułowe komponenty systemu (Project Mainline) nie istniały przed Androidem 10.
Wywołanie
getDeviceSecurityPatchLevel(COMPONENT_SYSTEM_MODULES)bezpiecznie wraca do podstawowej daty epoki systemu Unix (1970-01-01), gdy SPL modułu systemowego są niedostępne.
Informacje o dostępności aktualizacji i dostępnym poziomie poprawek zabezpieczeń (ASPL)
Określenie stanu zabezpieczeń urządzenia wymaga sprawdzenia, czy dla poszczególnych komponentów są dostępne oczekujące aktualizacje zabezpieczeń. Urządzenia z Androidem otrzymują aktualizacje zabezpieczeń za pomocą różnych mechanizmów dostarczania, takich jak aktualizacje systemu przesyłane drogą radiową (OTA) i aktualizacje systemowe Google Play w przypadku komponentów modułowych.
Zanim aplikacja będzie mogła pobrać ASPL dla danego komponentu, odpowiedni dostawca aktualizacji musi opublikować te informacje. Aby koordynować te różne źródła aktualizacji, aplikacje klienckie używają biblioteki AndroidX Security State do sprawdzania stanu zabezpieczeń, a klienci aktualizacji na urządzeniu używają powiązanej biblioteki AndroidX Security State Provider do publikowania dostępnego poziomu aktualizacji zabezpieczeń (ASPL).
Google udostępnia informacje o aktualizacjach modułów Mainline na wszystkich urządzeniach z Androidem GMS, a także informacje o aktualizacjach systemu OTA na urządzeniach korzystających z klienta Google OTA (GOTA).
Poniższy diagram pokazuje, jak aplikacje klienckie używają biblioteki AndroidX Security State do sprawdzania stanu zabezpieczeń w przypadku aktualizacji systemowych Google Play i aktualizacji systemowych OTA:

Dodawanie zależności
Aby dodać zależność od AndroidX Security State, musisz uwzględnić w projekcie repozytorium Maven Google. Dodaj zależność do pliku build.gradle.kts lub build.gradle aplikacji:
Kotlin
// Kotlin DSL (build.gradle.kts)
dependencies {
implementation("androidx.security:security-state:1.1.0")
}
Dynamiczny
// Groovy DSL (build.gradle)
dependencies {
implementation "androidx.security:security-state:1.1.0"
}
Macierz zadeklarowanych uprawnień
| Docelowe interfejsy API | Wymagane uprawnienia w AndroidManifest.xml |
Uwagi operacyjne |
|---|---|---|
getDeviceSecurityPatchLevel() |
Brak | Synchroniczne odczytywanie lokalnych właściwości systemu natywnego i metadanych pakietu. |
fetchAvailableSecurityPatchLevel()queryAllAvailableUpdates() |
Brak | Komunikuje się za pomocą IPC na urządzeniu. Biblioteka wysyła zapytania tylko do zaufanych komponentów na urządzeniu (wymaga to, aby dostawcy aktualizacji mieli uprawnienie READ_PRIVILEGED_PHONE_STATE), więc aplikacja może mieć pewność, że otrzymywane informacje są autentyczne. |
createVulnerabilityReportUrl()loadVulnerabilityReport()getPublishedSecurityPatchLevel()areCvesPatched()isDeviceFullyUpdated() |
android.permission.INTERNET |
Wymagane do pobierania publicznych raportów OSV. Po załadowaniu do pamięci za pomocą loadVulnerabilityReport() metody wysyłania zapytań są wykonywane lokalnie bez dostępu do sieci. |
Inicjowanie biblioteki
Zainicjuj SecurityPatchState na urządzeniu z Androidem Context:
Kotlin
import androidx.security.state.SecurityPatchState
val securityPatchState = SecurityPatchState(context)
Java
import androidx.security.state.SecurityPatchState;
SecurityPatchState securityPatchState = new SecurityPatchState(context);
Inicjowanie tylko za pomocą context zapewnia natychmiastowy dostęp do poziomów poprawek urządzenia offline bez zależności od sieci. (Zapytania o dostępność aktualizacji
komunikują się asynchronicznie z dostawcami na urządzeniu).
Jeśli aplikacja ocenia zgodność z CVE i ma już wczytany do pamięci raport o lukach w zabezpieczeniach OSV, wywołujący w Kotlinie mogą przekazać ciąg znaków JSON bezpośrednio do konstruktora w Kotlinie:
val securityPatchState = SecurityPatchState(context, vulnerabilityReportJsonString = jsonString)
W przypadku Javy lub podczas asynchronicznego wczytywania raportów po uruchomieniu zainicjuj kontekst i wywołaj securityPatchState.loadVulnerabilityReport(jsonString).
Sprawdzanie poziomów aktualizacji urządzenia
Synchroniczne wysyłanie zapytań o poziomy aktualizacji na urządzeniu:
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
}
Sprawdzanie dostępności aktualizacji systemu
Aplikacje mogą oceniać dostępność oczekujących aktualizacji, komunikując się asynchronicznie z zaufanymi dostawcami aktualizacji na urządzeniu, najczęściej z aktualizacjami systemowymi Google Play i klientami OTA producentów OEM:
fetchAvailableSecurityPatchLevel(): zwraca obowiązujący poziom SPL dla określonego komponentu (w przypadku braku nowszej aktualizacji przywraca bieżący poziom SPL urządzenia), który można wykorzystać do porównania z poziomem SPL urządzenia i opublikowanym poziomem SPL.queryAllAvailableUpdates(): wykrywa wszystkich zaufanych dostawców aktualizacji na urządzeniu i zwraca szczegółoweUpdateCheckResultwraz z metadanymi dotyczącymi źródła i aktualności danych.
Przykład 1. Zachęcanie użytkowników do zastosowania oczekujących aktualizacji
Użyj fetchAvailableSecurityPatchLevel(), aby zachęcać użytkowników do aktualizacji zabezpieczeń (np. uruchamiając Settings.ACTION_SYSTEM_UPDATE_SETTINGS):
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
W Javie metody asynchroniczne zwracają obiekt ListenableFuture i wywołania zwrotne trasy za pomocą ContextCompat.getMainExecutor():
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));
Przykład 2. Sprawdzanie szczegółowego stanu dostawcy
Użyj queryAllAvailableUpdates(), aby sprawdzić poszczególnych dostawców, sygnatury czasowe i rekordy UpdateInfo:
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));
Sprawdź rozwiązanie problemu z luką w zabezpieczeniach i luki CVE
Aby ocenić środki zaradcze dotyczące CVE, sprawdzić ogólną zgodność aktualizacji lub przejrzeć opublikowane poziomy aktualizacji zabezpieczeń, aplikacja musi najpierw uzyskać i wczytać raport o lukach w zabezpieczeniach OSV, zgodnie z opisem w dokumentacji interfejsu API SecurityPatchState.
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);
Wczytywanie raportów o lukach w zabezpieczeniach
- Lokalne buforowanie i odświeżanie za pomocą WorkManagera: ponieważ biuletyny zabezpieczeń Androida są publikowane co miesiąc, pobrany plik JSON należy buforować w pamięci wewnętrznej (
context.filesDir) i zaplanować okresowe zadanie w tle za pomocąWorkManager(najlepiej co 24–48 godzin), aby odświeżać raport, odczytując synchronicznie dane z lokalnej pamięci podręcznej przy uruchamianiu aplikacji. - Wątki w tle: wywołuj
loadVulnerabilityReport()w wątku w tle (Dispatchers.IOw Kotlinie lubExecutorw Javie), aby uniknąć blokowania głównego wątku UI podczas analizowania rekordów CVE. - Ocena jądra LTS: wywołanie funkcji
getPatchedCves(COMPONENT_KERNEL, ...)powoduje zgłoszenie wyjątkuIllegalArgumentException, a funkcjaareCvesPatched()nie ocenia luk w zabezpieczeniach jądra. Zamiast tego oceń bezpieczeństwo jądra, porównując wersję jądra urządzenia z docelowymi wersjami LTS wspólnego jądra Androida zwracanymi przezgetPublishedSecurityPatchLevel(COMPONENT_KERNEL), które pasują do jego głównej i pomniejszej gałęzi (np. porównując jądro5.15.140z wersją docelową5.15.159).
Dodatkowe materiały
Więcej informacji o stanie bezpieczeństwa urządzenia znajdziesz w tych materiałach:
Dokumentacja
- Biuletyny bezpieczeństwa w Androidzie
- Komponenty systemu modułowego
- Ogólny obraz jądra (GKI)
- Dodatkowe poprawki zabezpieczeń
- Play Integrity API
- Baza danych Open Source Vulnerabilities (OSV)
- Informacje o wersji 1.1.0 usługi Security State