Root Detection, Android uygulamalarının süper kullanıcı ayrıcalıklarına sahip cihazlarda çalışmasını engelleyen bir güvenlik mekanizmasıdır. Bankacılık, ödeme ve kurumsal uygulamalar, rootlu cihazlarda işlevselliği engeller veya kısıtlar, çünkü root erişimi Android sandbox kısıtlamalarını kaldırır ve trafiği engelleme, süreç belleğini okuma ve verilerde değişiklik yapma olasılığını açar. OWASP Mobile Top 10 (2024)'e göre, Root Detection eksikliği M8 kategorisine (Security Decisions via Untrusted Inputs) girer. Root Detection, dosya sisteminin statik kontrolleri ve çalışma zamanı davranışının dinamik analizinin bir kombinasyonu üzerine kuruludur.
Anahtar Noktalar
Root Detection, bir Android cihazında root erişiminin varlığını tespit eden bir yazılım mekanizmasıdır. Root erişimi, işletim sistemi üzerinde tam kontrol sağlayarak uygulamaların ve betiklerin UID 0 ile komut yürütmesine olanak tanır. Rootlu bir cihazda, uygulama yalıtımı (Android Sandbox) kaybolur ve klavye girişini engelleme, diğer uygulamaların SQLite veritabanlarını okuma, süreçlere kod enjekte etme ve güvenilir depodaki SSL sertifikalarını değiştirme mümkün hale gelir.
Finansal ve kurumsal uygulamalar için, rootlu bir cihazda çalışmak kabul edilemez bir risk oluşturur: saldırgan token'lara, oturum anahtarlarına ve kişisel verilere erişim sağlar. PCI Security Standards Council dahil olmak üzere düzenleyici kurumlar, ödeme uygulamalarının root erişimini tespit etmesini ve buna yanıt vermesini zorunlu kılar. Buna yanıt olarak, Android geliştiricileri proaktif bir koruma stratejisinin parçası olarak Root Detection'ı entegre eder.
Tespit için iki yaklaşım vardır: dosya sistemini ve yüklü paketleri analiz eden statik ve çalışma zamanında kontroller yapan dinamik. Birleşik yaklaşım en güvenilir olarak kabul edilir, çünkü farklı atlatma vektörlerini kapsar. NowSecure (2025) tarafından yapılan bir araştırmaya göre, Google Play'deki ilk 100 bankacılık uygulamasının %76'sı bir tür Root Detection içermektedir.
Statik yöntemler, uygulama başlangıcında yürütülür ve rootlama araçlarının dosya sisteminde bıraktığı root erişimi belirtilerini kontrol eder. Bu yöntemler, ayrıcalıklı komutların yürütülmesini gerektirmez ve normal bir uygulama bağlamında çalışır.
Root erişiminin ana göstergesi, standart yollarda su yürütülebilir dosyasının bulunmasıdır: /system/bin/su, /system/xbin/su, /sbin/su, /su/bin/su. Uygulama, dosyanın varlığını File.exists() veya libc'den access()'in yerel uygulaması aracılığıyla kontrol eder. Ek olarak, su --version veya su -c id çalıştırılmayı deneyebilir ve çıkış kodunu kontrol edebilir.
Root erişimini yönetmek için tipik uygulamalar: Superuser, SuperSU, Magisk Manager, KingRoot. Bunların varlığı, PackageManager.getPackageInfo() aracılığıyla veya /data/app/ dizini okunarak kontrol edilir. Kontrol edilecek paketler: com.topjohnwu.magisk, eu.chainfire.supersu, com.noshufou.android.su, com.thirdparty.superuser, com.koushikdutta.superuser, com.zacharee1.systemuituner.
Android, System.getProperty ve Build.TAGS aracılığıyla erişilebilen sistem özelliklerinde sistem durumu bilgilerini saklar. Build.TAGS, release-keys yerine test-keys içeriyorsa, bu genellikle root erişimi olan özel bir üretici yazılımını gösterir. Ek olarak, /system/build.prop okunarak ro.build.tags, ro.debuggable ve ro.secure kontrol edilir.
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) {
// package not found
}
}
return false;
}
}
Dinamik yöntemler, uygulama çalışması sırasında yürütülür ve yürütme ortamını analiz eder. Statik yöntemlerin aksine, Magisk Hide veya Zygisk aracılığıyla gizlenmiş rootlamayı tespit edebilirler, çünkü yalnızca dosya yapısını değil, sistem davranışını da kontrol ederler.
Root erişimiyle, bazı sistem bölümleri ro (salt okunur) yerine rw (okuma-yazma) bayrağıyla bağlanır. Uygulama /proc/mounts'u okur ve /system'in ro olarak bağlandığını kontrol eder. /system rw olarak bağlanmışsa, bu değiştirilmiş bir sistemi gösterir. Ek olarak, Magisk aracılığıyla /su bağlantısının varlığı kontrol edilir.
Android Güvenli Modu, root yöneticileri de dahil olmak üzere üçüncü taraf uygulamaları devre dışı bırakır. Doğru bir Root Detection uygulaması, cihazın güvenli modda çalışıp çalışmadığını kontrol edebilir. Uygulama, root yöneticilerinin görünmediğini ancak su ikili dosyasının var olduğunu tespit ederse, bu Magisk Hide belirtisidir.
ProcessBuilder veya Runtime.exec aracılığıyla su -c id çalıştırmayı denemek, root erişiminin doğrudan bir testidir. Ancak Magisk bu çağrıyı engelleyebilir. Daha güvenilir bir yaklaşım, yerel kod aracılığıyla kontroldür: /proc/1/limits veya /proc/self/maps'i açmak ve çalışan süreçlerin UID'sini analiz etmek. Uygulama UID 0 alabiliyor veya yalnızca root tarafından erişilebilen dosyaları okuyabiliyorsa, cihazın güvenliği ihlal edilmiştir.
public boolean checkRootDynamically() {
// Build flags check
String buildTags = Build.TAGS;
if (buildTags != null && buildTags.contains("test-keys")) {
return true;
}
// Checking /system mount
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) {
// error reading mounts
}
return false;
}
Java ile uygulanan Root Detection, Java yöntemlerini engelleyen ve dönüş değerlerini değiştiren Xposed modülleri veya Frida aracılığıyla kolayca atlatılır. JNI aracılığıyla C++ ile yerel uygulama önemli ölçüde daha dirençlidir: Java seviyesinde çalışan dinamik analiz araçları, stat, access, popen ve dlopen gibi yerel libc çağrılarını göremez.
#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;
}
Yerel kontrol Java API'sini kullanmaz, bu da onu Dalvik/ART seviyesinde çalışan atlatma araçları için görünmez kılar. Ek koruma için, sabitlerin (yol listesi) salt okunur bir bölümde saklanmaması, bunun yerine basit tersinir işlevler aracılığıyla hesaplanması önerilir. libc'den stat çağrısı, Java sarmalayıcılarını atlayarak doğrudan Linux çekirdeğine erişir ve Xposed aracılığıyla engellenemez.
Koruma geliştiricileri, sağlam bir tespit sistemi oluşturmak için mevcut atlatma yöntemlerini anlamalıdır. Her atlatma yöntemi, uygun seviyede bir karşı önlem gerektirir.
Magisk, Android 9–14'te en popüler rootlama aracıdır. Magisk Hide, su'nun varlığını /proc'tan gizler ve yol kontrol sonuçlarını taklit eder. Magisk çekirdek seviyesinde çalışır ve uygulama görmeden önce stat() ve access()'i engeller. Karşı önlem: /sbin/.magisk'in varlığı aracılığıyla Magisk'in kendisini kontrol etmek veya uygulamanın kendi haritalarını okuyarak kontrol etmek — Magisk, kütüphanesini her sürece enjekte eder.
Frida, Ptrace veya Dobby aracılığıyla yerel işlevleri engelleyebilen dinamik bir enstrümantasyon aracıdır. Frida, herhangi bir kontrolün dönüş değerini değiştirir, stat sonucunu ENOENT olarak taklit eder. Karşı önlem: Bellekteki talimatların sağlama toplamını hesaplayarak yerel işlevlerin bütünlüğünü doğrulamak ve frida-agent.so veya frida-helper'ın varlığı için /proc/self/maps'i analiz ederek Frida'yı tespit etmek.
Java ile uygulanan Root Detection, 2–3 dakika içinde kaldırılır: APK, apktool aracılığıyla derlenir, smali kodunda yöntemin dönüş değeri false olarak değiştirilir, APK yeniden oluşturulur ve imzalanır. Karşı önlem: Kritik mantığı yerel koda taşımak ve çalışma zamanında Signature API'si aracılığıyla uygulamanın dijital imzasını doğrulamak veya APK hash'ini sunucudaki bir referansla karşılaştırmak.
Etkili Root Detection, çok katmanlı bir mimari üzerine inşa edilmiştir. Hiçbir tek yöntem tek başına yeterli koruma sağlamaz. Statik ve dinamik kontrollerin, yerel kodun ve sunucu tarafı doğrulamanın kombinasyonu maksimum direnç sağlar.
Yalnızca istemci tarafı kontrollere güvenmeyin. Root Detection sonuçlarını tek kullanımlık bir oturum token'ı ile birlikte sunucuya gönderin. Sunucu, işlevselliği engellemeye veya kısıtlamaya karar verir. Bu, istemci uygulamasının değiştirilebildiği ancak sunucunun güvenilir bir taraf olarak kaldığı API seviyesindeki saldırıları önler.
Root Detection kodu karartılmalıdır. Bir saldırgan jadx'te su yolu kontrollerinin net bir dizisini görürse, atlatma dakikalar alır. Kontrol akışını karartmak ve dizeleri şifrelemek için ProGuard veya DexGuard kullanın. Karartma, koruma kodu analiz süresini dakikalardan saatlere çıkarır.
Kontrol edilen yolların, paketlerin ve göstergelerin listesi, her uygulama sürümüyle güncellenmelidir. Yeni rootlama ve atlatma araçları aylık olarak ortaya çıkar. Bir yıldır değişmeyen statik bir liste, modern yöntemleri tespit edemez. Kontrolleri gerçekleştirmeden önce uygulama başlangıcında sunucudan güncel imzaların yüklenmesi önerilir.
Sıkça Sorulan Sorular
Root Detection, Android sandbox'ının devre dışı olduğu bir cihazda uygulamanın çalışmasını engeller. Rootlu bir cihazda, herhangi bir uygulama diğer uygulamaların verilerini okuyabilir. Bankacılık ve ödeme uygulamaları, PCI DSS gereksinimleri ve OWASP Mobile Security önerileri uyarınca rootlu cihazlarda çalışmayı engellemekle yükümlüdür.
Magisk Hide, bağlantı ad alanı (mount namespace) mekanizmasını kullanır. Hariç tutma listesindeki her süreç için Magisk, su ikili dosyasının görünmediği yalıtılmış bir ad alanı oluşturur. Bu ad alanındaki sistem çağrıları stat, access ve open, Magisk dosyalarını görmez. Magisk, /proc/self/maps'in varlığı kontrol edilerek ve magisk dökümleri aranarak tespit edilebilir.
Evet, uygulama kod bütünlüğünü doğrulamazsa. Frida aracılığıyla, Java doğrulama yöntemi engellenebilir ve false döndürmeye zorlanabilir. Karşı önlem, kritik mantığın C++ ile yerel uygulanması ve DEX dosya hash'i aracılığıyla bütünlük doğrulamasıdır. Karartma olmadan, Java'daki herhangi bir Root Detection 5–10 dakikada atlatılır.
SafetyNet (kullanımdan kaldırıldı) ve Play Integrity API, cihaz bütünlüğünü onaylayan Google'ın sunucu tarafı kontrolleridir. Önyükleyici, sistem imzası ve root durumu kontrolünü içerirler. Play Integrity API, SafetyNet için önerilen yedektir ve üç seviye sağlar: BASIC, DEVICE ve STRONG. İstemci tarafı Root Detection, sunucu tarafı tasdiki tamamlar.
Uygulamayı gerçek bir rootlu cihaza (örneğin, Magisk'li bir Pixel) kurun. Engellemenin tetiklenip tetiklenmediğini kontrol edin. Ardından uygulamanız için Magisk Hide aracılığıyla root'u gizlemeyi deneyin ve testi yeniden başlatın. Derinlemesine test için, hedef yöntemleri engellemek üzere Frida'yı kullanın ve yerel korumanın atlatılamadığından emin olun.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun