Root-Erkennung: Welche Erkennungsmethoden die App Doctolib anwendet
Im Jahr 2021 hat das Unternehmen Doctolib einen BigBrotherAward »gewonnen«:
Der BigBrotherAward in der Kategorie „Gesundheit“ geht andie Firma Doctolib in Berlin für ihr Terminvermittlungsportal für Ärzte.
Gerade bei solchen Unternehmen ist es interessant, mal den App-Datenverkehr zu analysieren. Bei der Android-Version 3.4.23 wollte ich das tun. Unmittelbar nach dem Start erscheint allerdings der Hinweis:
Die Verwendung eines modifizierten Geräts (Jailbreak/Root) ist derzeit nicht gestattet, um die Sicherheit Ihrer persönlichen Daten auf Doctolib zu gewährleisten.
Die App hat also Mechanismen zur Root-Erkennung implementiert. Ich habe das mal genauer analysiert. Insgesamt muss man einige Erkennungsmethoden aushebeln, damit man den Datenverkehr auf einem gerooteten Gerät analysieren kann. Anbei mal ein paar Aufrufe, die die App durchführt, um zu erkennen, ob das Gerät gerootet ist:
message: {'type': 'send', 'payload': 'Bypass return value for binary: Superuser.apk'} data: None message: {'type': 'send', 'payload': 'Bypass return value for binary: su'} data: None message: {'type': 'send', 'payload': 'Bypass /system/xbin/which,su command'} data: None message: {'type': 'send', 'payload': 'Bypass root check for package: com.noshufou.android.su'} data: None message: {'type': 'send', 'payload': 'Bypass root check for package: com.noshufou.android.su.elite'} data: None message: {'type': 'send', 'payload': 'Bypass root check for package: eu.chainfire.supersu'} data: None message: {'type': 'send', 'payload': 'Bypass root check for package: com.koushikdutta.superuser'} data: None message: {'type': 'send', 'payload': 'Bypass root check for package: com.thirdparty.superuser'} data: None message: {'type': 'send', 'payload': 'Bypass root check for package: com.yellowes.su'} data: None message: {'type': 'send', 'payload': 'Bypass root check for package: com.topjohnwu.magisk'} data: None message: {'type': 'send', 'payload': 'Bypass root check for package: com.koushikdutta.rommanager'} data: None message: {'type': 'send', 'payload': 'Bypass root check for package: com.koushikdutta.rommanager.license'} data: None message: {'type': 'send', 'payload': 'Bypass root check for package: com.dimonvideo.luckypatcher'} data: None message: {'type': 'send', 'payload': 'Bypass root check for package: com.chelpus.lackypatch'} data: None message: {'type': 'send', 'payload': 'Bypass root check for package: com.ramdroid.appquarantine'} data: None message: {'type': 'send', 'payload': 'Bypass root check for package: com.ramdroid.appquarantinepro'} data: None message: {'type': 'send', 'payload': 'Bypass root check for package: com.android.vending.billing.InAppBillingService.COIN'} data: None message: {'type': 'send', 'payload': 'Bypass test-keys check'} data: None message: {'type': 'send', 'payload': 'Bypass which,su command'} data: None message: {'type': 'send', 'payload': 'Bypass native fopen >> /data/local/su'} data: None message: {'type': 'send', 'payload': 'Bypass native fopen >> /data/local/bin/su'} data: None message: {'type': 'send', 'payload': 'Bypass native fopen >> /data/local/xbin/su'} data: None message: {'type': 'send', 'payload': 'Bypass native fopen >> /sbin/su'} data: None message: {'type': 'send', 'payload': 'Bypass native fopen >> /su/bin/su'} data: None message: {'type': 'send', 'payload': 'Bypass native fopen >> /system/bin/su'} data: None message: {'type': 'send', 'payload': 'Bypass native fopen >> /system/bin/.ext/su'} data: None message: {'type': 'send', 'payload': 'Bypass native fopen >> /system/bin/failsafe/su'} data: None message: {'type': 'send', 'payload': 'Bypass native fopen >> /system/sd/xbin/su'} data: None message: {'type': 'send', 'payload': 'Bypass native fopen >> /system/usr/we-need-root/su'} data: None message: {'type': 'send', 'payload': 'Bypass native fopen >> /system/xbin/su'} data: None message: {'type': 'send', 'payload': 'Bypass native fopen >> /cache/su'} data: None message: {'type': 'send', 'payload': 'Bypass native fopen >> /data/su'} data: None message: {'type': 'send', 'payload': 'Bypass native fopen >> /dev/su'} data: None message: {'type': 'send', 'payload': 'Bypass native fopen >> /system/sbin/su'} data: None message: {'type': 'send', 'payload': 'Bypass native fopen >> /product/bin/su'} data: None message: {'type': 'send', 'payload': 'Bypass native fopen >> /apex/com.android.runtime/bin/su'} data: None message: {'type': 'send', 'payload': 'Bypass native fopen >> /odm/bin/su'} data: None message: {'type': 'send', 'payload': 'Bypass native fopen >> /vendor/bin/su'} data: None message: {'type': 'send', 'payload': 'Bypass native fopen >> /vendor/xbin/su'} data: None message: {'type': 'send', 'payload': 'Bypass return value for binary: magisk'} data: None
Die App versucht unter anderem:
- App-Packages zu erkennen, die Root ermöglichen bzw. verschleiern (eu.chainfire.supersu, com.devadvance.rootcloak etc.)
- Befehle (Root-Binaries) auszuführen, die eine Ausführung im Root- bzw. Admin-Kontext ermöglichen (/sbin/su)
- Magisk zu erkennen
Mit einem angepassten Frida-Hook lassen sich allerdings alle Anfragen mit False
bzw. nicht vorhanden beantworten. Somit kann die Root-Erkennung ausgehebelt werden und der App-Datenverkehr analysiert werden. Game over.
Tippt man beim Consent-Banner bspw. auf Ablehnen
wird Folgendes übermittelt [api.privacy-center.org]:
POST /v1/events HTTP/1.1 Host: api.privacy-center.org Content-Length: 1116 User-Agent: react-native/android/3.4.23/10/MSM8953/Mi A1 X-Requested-With: XMLHttpRequest Content-Type: application/json Accept: */* Origin: https://www.doctolib.de Sec-Fetch-Site: cross-site Sec-Fetch-Mode: cors Sec-Fetch-Dest: empty Referer: https://www.doctolib.de/ Accept-Encoding: gzip, deflate Accept-Language: de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7 Connection: close { "source":{ "type":"sdk-web", "domain":"www.doctolib.de", "key":"df2b9f8c-760a-445f-810e-4b47a4fe41a7", "deployment_id":"4GbFn3Lx", "beacon":false }, "user":{ "agent":"react-native/android/3.4.23/10/MSM8953/Mi A1", "id_type":"uuid", "country":"DE", "regs":[ "gdpr" ], "id":"18484cfe-cacb-6fba-a0e0-39fbb5b1625c", "token":{ "user_id":"18484cfe-cacb-6fba-a0e0-39fbb5b1625c", "created":"2022-11-17T17:58:50.566Z", "updated":"2022-11-17T18:00:27.474Z", "vendors":{ "enabled":[ ], "disabled":[ "c:cloudflare-mYYFMYNT", "c:didomi-fYPBYxWa","c:doctolibn-Wp87CpXA", "c:doctoliba-tgtb3W8P" ] }, "purposes":{ "enabled":[ ], "disabled":[ "analytik-N2ZH9BqQ" ] [...]
Weiter habe ich noch nicht geprüft – werde ich vielleicht irgendwann nachholen. Mir ging es erstmal darum, exemplarisch aufzuzeigen, welche Anstrengungen Entwickler gehen, um gerootete Geräte zu erkennen. Hint: Bisher gab es keine App, bei der sich die Root-Erkennung nicht aushebeln ließ. ;-)