Root Detection — az Android-alkalmazások védelmének mechanizmusa a rootolt eszközökön való futtatás ellen. A banki, fizetési és vállalati alkalmazások blokkolják vagy korlátozzák a funkcionalitást a rootolt eszközökön, mivel a root hozzáférés megszünteti az Android homokozó korlátait, és lehetővé teszi a forgalom elfogását, a folyamatmemória olvasását és az adatok helyettesítését. A OWASP Mobile Top 10 (2024) szerint a Root Detection hiánya az M8 (Security Decisions via Untrusted Inputs) kategóriába tartozik. Root Detection a fájlrendszer statikus ellenőrzéseinek és a runtime-viselkedés dinamikus elemzésének kombinációjára épül.
Főbb pontok
Root Detection — szoftveres mechanizmus, amely meghatározza a root hozzáférés jelenlétét egy Android-eszközön. A root hozzáférés teljes irányítást biztosít az operációs rendszer felett, lehetővé téve az alkalmazásoknak és szkripteknek, hogy UID 0-val hajtsanak végre parancsokat. Egy rootolt eszközön az alkalmazások elkülönítése (Android Sandbox) megszűnik, lehetővé téve a billentyűzetbevitel elfogását, más alkalmazások SQLite adatbázisainak olvasását, kód befecskendezését folyamatokba és SSL-tanúsítványok helyettesítését a megbízható tárolóban.
A pénzügyi és vállalati alkalmazások számára a rootolt eszközön való működés elfogadhatatlan kockázatot jelent: a támadó hozzáfér a tokenekhez, munkamenet-kulcsokhoz és személyes adatokhoz. A szabályozó hatóságok, köztük a PCI Security Standards Council, megkövetelik a fizetési alkalmazásoktól a root hozzáférés észlelését és az arra való reagálást. Válaszul az Android-fejlesztők beépítik a Root Detection-t a proaktív védelem stratégiájának részeként.
Két megközelítés létezik az észlelésre: statikus, amely a fájlrendszert és a telepített csomagokat elemzi, és dinamikus, amely az ellenőrzéseket runtime-ban végzi. A kombinált megközelítés tekinthető a legmegbízhatóbbnak, mivel különböző megkerülési vektorokat fed le. A NowSecure (2025) kutatása szerint a Google Play top 100-as listáján szereplő banki alkalmazások 76%-a tartalmaz valamilyen formájú Root Detection-t.
A statikus módszerek az alkalmazás indításakor futnak le, és ellenőrzik a root eszközök által a fájlrendszerben hagyott root hozzáférés jeleit. Ezek a módszerek nem igényelnek privilegizált parancsok végrehajtását, és egy normál alkalmazás kontextusában működnek.
A root hozzáférés fő jele — a su végrehajtható fájl jelenléte a standard elérési utakon: /system/bin/su, /system/xbin/su, /sbin/su, /su/bin/su. Az alkalmazás a fájl létezését File.exists() vagy a libc-ből származó access() natív implementációján keresztül ellenőrzi. Emellett megkísérelhető a su --version vagy su -c id futtatása és a kilépési kód ellenőrzése.
A root hozzáférés kezelésére szolgáló tipikus alkalmazások: Superuser, SuperSU, Magisk Manager, KingRoot. Jelenlétük a PackageManager.getPackageInfo() vagy a /data/app/ könyvtár olvasásán keresztül ellenőrizhető. Ellenőrizendő csomagok: com.topjohnwu.magisk, eu.chainfire.supersu, com.noshufou.android.su, com.thirdparty.superuser, com.koushikdutta.superuser, com.zacharee1.systemuituner.
Az Android a rendszer állapotával kapcsolatos információkat a System.getProperty és Build.TAGS segítségével elérhető rendszertulajdonságokban tárolja. Ha a Build.TAGS értéke release-keys helyett test-keys-t tartalmaz — ez egyéni firmware-re utal, gyakran root hozzáféréssel. Emellett a ro.build.tags, ro.debuggable és ro.secure ellenőrzése a /system/build.prop olvasásával történik.
public class RootDetectionChecker {
private static final String[] SU_PATHS = {
"/system/bin/su",
"/system/xbin/su",
"/sbin/su",
"/su/bin/su",
"/system/sd/xbin/su"
};
public boolean checkRootByFiles() {
for (String path : SU_PATHS) {
if (new File(path).exists()) {
return true;
}
}
return false;
}
public boolean checkRootByPackages(Context ctx) {
String[] packages = {
"com.topjohnwu.magisk",
"eu.chainfire.supersu",
"com.noshufou.android.su",
"com.koushikdutta.superuser"
};
for (String pkg : packages) {
try {
ctx.getPackageManager().getPackageInfo(pkg, 0);
return true;
} catch (PackageManager.NameNotFoundException e) {
// csomag nem található
}
}
return false;
}
}
A dinamikus módszerek az alkalmazás működése során futnak le, és elemzik a végrehajtási környezetet. A statikus módszerekkel ellentétben képesek észlelni a Magisk Hide vagy Zygisk által elrejtett root-ot, mivel a rendszer viselkedését ellenőrzik, nem csak a fájlszerkezetet.
Root hozzáférés esetén egyes rendszerpartíciók rw (read-write) jelzővel vannak csatolva a ro (read-only) helyett. Az alkalmazás olvassa a /proc/mounts-ot, és ellenőrzi, hogy a /system ro-ként van-e csatolva. Ha a /system rw-ként van csatolva — ez módosított rendszerre utal. Emellett ellenőrzésre kerül a /su csatolásának jelenléte Magisk-en keresztül.
Az Android Safe Mode kikapcsolja a harmadik féltől származó alkalmazásokat, beleértve a root kezelőket is. A Root Detection helyes implementációja ellenőrizheti, hogy az eszköz biztonságos módban működik-e. Ha az alkalmazás észleli, hogy a root kezelők nem láthatók, de a su bináris létezik — ez a Magisk Hide jele.
A su -c id végrehajtásának kísérlete ProcessBuilder vagy Runtime.exec segítségével — a root hozzáférés közvetlen tesztje. A Magisk azonban elfoghatja ezt a hívást. Megbízhatóbb lehetőség — ellenőrzés natív kódon keresztül: /proc/1/limits vagy /proc/self/maps megnyitása és a futó folyamatok UID-jának elemzése. Ha az alkalmazás képes UID 0-t szerezni vagy olyan fájlokat olvasni, amelyek csak root számára elérhetők — az eszköz kompromittált.
public boolean checkRootDynamically() {
// Fordítási flag-ek ellenőrzése
String buildTags = Build.TAGS;
if (buildTags != null && buildTags.contains("test-keys")) {
return true;
}
// /system csatolásának ellenőrzése
try {
BufferedReader reader = new BufferedReader(
new InputStreamReader(new FileInputStream("/proc/mounts"))
);
String line;
while ((line = reader.readLine()) != null) {
if (line.contains("/system")
&& line.contains("rw")) {
reader.close();
return true;
}
}
reader.close();
} catch (IOException e) {
// hiba a mount olvasásakor
}
return false;
}
A Java-ban implementált Root Detection könnyen megkerülhető Xposed-modulokkal vagy Frida-val, amelyek elkapják a Java-metódusokat és meghamisítják a visszatérési értékeket. A C++-ban JNI-n keresztüli natív implementáció lényegesen ellenállóbb: a Java szinten működő dinamikus elemző eszközök nem látják a libc natív hívásait, mint a stat, access, popen és dlopen.
#include <unistd.h>
#include <sys/stat.h>
#include <cstring>
#include <vector>
extern "C"
JNIEXPORT jboolean JNICALL
Java_com_example_checker_RootCheck_nativeCheck(
JNIEnv* env, jobject instance) {
std::vector<const char*> paths = {
"/system/bin/su",
"/system/xbin/su",
"/sbin/su",
"/data/local/su"
};
struct stat st;
for (const char* path : paths) {
if (stat(path, &st) == 0) {
return JNI_TRUE;
}
}
return JNI_FALSE;
}
A natív ellenőrzés nem használ Java API-t, így láthatatlan a Dalvik/ART szinten működő megkerülő eszközök számára. További védelem érdekében ajánlott a konstansokat (útvonalak listája) nem a read-only szekcióban tárolni, hanem egyszerű visszafordítható függvényekkel kiszámítani. A stat hívás a libc-ből közvetlenül a Linux kernelhez fordul, megkerülve a Java burkolókat, és nem fogható el Xposed-en keresztül.
A védelem fejlesztőinek meg kell érteniük a létező megkerülési módszereket, hogy ellenálló észlelési rendszert építhessenek. Minden megkerülési módszer megfelelő szintű ellenintézkedést igényel.
Magisk — a legnépszerűbb root eszköz Android 9–14 rendszeren. A Magisk Hide elrejti a su jelenlétét a /proc-ból, és meghamisítja az útvonal-ellenőrzések eredményeit. A Magisk kernel szinten működik, és elfogja a stat() és access() hívásokat, mielőtt az alkalmazás látná őket. Ellenintézkedés: a Magisk jelenlétének ellenőrzése a /sbin/.magisk meglétén keresztül, vagy ellenőrzés a saját maps olvasásával — a Magisk beágyazza a könyvtárát minden folyamatba.
Frida — dinamikus instrumentációs eszköz, amely Ptrace vagy Dobby segítségével képes natív függvényeket elkapni. A Frida minden ellenőrzés visszatérési értékét lecseréli, a stat eredményét ENOENT-re hamisítva. Ellenintézkedés: a natív függvények integritásának ellenőrzése az utasítások ellenőrzőösszegének kiszámításával a memóriában, és a Frida észlelése a /proc/self/maps elemzésével a frida-agent.so vagy frida-helper jelenlétére.
A Java-ban implementált Root Detection 2–3 perc alatt eltávolítható: az APK-t apktool segítségével kicsomagolják, a smali kódban a metódus visszatérési értékét false-ra javítják, az APK-t újraösszeállítják és aláírják. Ellenintézkedés: a kritikus logika áthelyezése natív kódba, és az alkalmazás digitális aláírásának ellenőrzése runtime-ban Signature API-n vagy az APK hash szerveren lévő etalonnal való összehasonlításán keresztül.
A hatékony Root Detection többrétegű architektúrára épül. Egyetlen módszer önmagában nem nyújt elegendő védelmet. A statikus és dinamikus ellenőrzések, a natív kód és a szerveroldali ellenőrzés kombinációja maximális ellenállást biztosít.
Ne hagyatkozzon csak a kliensoldali ellenőrzésre. Küldje el a Root Detection eredményeit egy egyszer használatos munkamenet-token kíséretében a szerverre. A szerver dönt a blokkolásról vagy a funkcionalitás korlátozásáról. Ez megakadályozza az API-szintű támadásokat, ahol a kliensalkalmazás módosítható, de a szerver megbízható fél marad.
A Root Detection kódot obfuszkálni kell. Ha a támadó a jadx-ban egyértelmű su útvonal-ellenőrzési sorozatot lát — a megkerülés percekig tart. Használjon ProGuard-ot vagy DexGuard-ot a vezérlési folyamat összekuszálásához és a karakterláncok titkosításához. Az obfuszkáció a védelmi kód elemzési idejét néhány percről több órára növeli.
Az ellenőrzött útvonalak, csomagok és indikátorok listáját minden alkalmazás-kiadással frissíteni kell. Új root és megkerülési eszközök havonta jelennek meg. Egy éve nem változott statikus lista nem észleli a modern módszereket. Ajánlott a friss aláírások betöltése a szerverről az alkalmazás indításakor, az ellenőrzések végrehajtása előtt.
Gyakran Ismételt Kérdések
A Root Detection véd az alkalmazás olyan eszközön való futtatásától, ahol az Android homokozó ki van kapcsolva. Egy rootolt eszközön bármely alkalmazás olvashatja más alkalmazások adatait. A banki és fizetési alkalmazások kötelesek blokkolni a működést rootolt eszközökön a PCI DSS követelményei és az OWASP Mobile Security ajánlásai szerint.
A Magisk Hide a névtér-csatolás (mount namespace) mechanizmusát használja. Minden, a kivételek listáján szereplő folyamathoz a Magisk egy elkülönített névteret hoz létre, ahol a su bináris láthatatlan. A rendszerhívások stat, access és open ebben a névtérben nem látják a Magisk fájljait. A Magisk észlelhető a /proc/self/maps jelenlétének ellenőrzésével és a magisk-dump keresésével.
Igen, ha az alkalmazás nem ellenőrzi a saját kódja integritását. A Frida segítségével elkapható a Java ellenőrző metódus, és hamis false visszatérési érték kényszeríthető ki. Ellenintézkedés — a kritikus logika natív implementációja C++-ban és az integritás ellenőrzése a DEX-fájl hash-jén keresztül. Obfuszkáció nélkül bármely Java-beli Root Detection 5–10 perc alatt megkerülhető.
A SafetyNet (elavult) és a Play Integrity API — ezek a Google szerveroldali ellenőrzései, amelyek megerősítik az eszköz integritását. Tartalmazzák a bootloader, a rendszer-aláírás és a root státusz ellenőrzését. Play Integrity API — a SafetyNet ajánlott helyettesítője, három szintet biztosít: BASIC, DEVICE és STRONG. A kliensoldali Root Detection kiegészíti a szerveroldali tanúsítást.
Telepítse az alkalmazást egy valódi rootolt eszközre (pl. Pixel Magisk-kal). Ellenőrizze, hogy a blokkolás aktiválódik-e. Ezután próbálja elrejteni a root-ot a Magisk Hide segítségével az alkalmazás számára, és ismételje meg a tesztet. Mélyreható ellenőrzéshez használja a Frida-t a célmetódusok elkapására, és győződjön meg arról, hogy a natív védelem nem kerülhető meg.
Összegzés
Kulcsrakész mobilalkalmazást fejlesztünk
Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.
Olvassa el is