diff --git a/agent/src/android/scanner.ts b/agent/src/android/scanner.ts new file mode 100644 index 00000000..d0a87b8d --- /dev/null +++ b/agent/src/android/scanner.ts @@ -0,0 +1,15 @@ +import { wrapJavaPerform, getApplicationContext } from "./lib/libjava"; + +export namespace scanner { + export const getfbdatabase = (): Promise => { + return wrapJavaPerform(() => { + // -- Sample Java + // + // String dburl = (String)getString(R.string.firebase_database_url); + const context = getApplicationContext(); + const myid = context.getResources().getIdentifier("firebase_database_url", "string", context.getPackageName()); + const dburl = context.getString(myid); + return dburl; + }); + } +} \ No newline at end of file diff --git a/agent/src/rpc/android.ts b/agent/src/rpc/android.ts index 7560e75f..fc19bc63 100644 --- a/agent/src/rpc/android.ts +++ b/agent/src/rpc/android.ts @@ -10,6 +10,7 @@ import { sslpinning } from "../android/pinning"; import { root } from "../android/root"; import { androidshell } from "../android/shell"; import { userinterface } from "../android/userinterface"; +import { scanner } from "../android/scanner"; export const android = { // android clipboard @@ -67,6 +68,9 @@ export const android = { androidRootDetectionDisable: () => root.disable(), androidRootDetectionEnable: () => root.enable(), + // android scanner declarations + androidGetFbDatabase: () => scanner.getfbdatabase(), + // android user interface androidUiScreenshot: () => userinterface.screenshot(), androidUiSetFlagSecure: (v: boolean): Promise => userinterface.setFlagSecure(v), diff --git a/objection/commands/android/scanner.py b/objection/commands/android/scanner.py new file mode 100644 index 00000000..9114ee08 --- /dev/null +++ b/objection/commands/android/scanner.py @@ -0,0 +1,35 @@ +import click +import requests + +from objection.state.connection import state_connection + +def firebase(args: list) -> None: + """ + Search for a Firebase Database and check if it's leaking data. + + :param args: + :return: + """ + api = state_connection.get_api() + try: + fbdb = api.android_get_fb_database() + click.secho('Scanning FireBase DB: {0}'.format(fbdb), fg='green') + click.secho('Note: If the DB is exposed, it may take a while to download', fg='red') + response = requests.get(fbdb + '/.json') + if response.status_code == 401: + click.secho('Firebase DB is not leaking data', fg='green') + elif response.status_code == 200: + click.secho('Firebase DB is leaking data!', fg='red') + if len(response.text) < 1000: + click.secho('Size: {:,.0f}'.format(len(response.text)) + "B", fg='red') + elif len(response.text) >= 1000 and len(response.text) < 1000000: + click.secho('Size: {:,.0f}'.format(len(response.text)/float(1<<10)) + "KB", fg='red') + elif len(response.text) >= 1000000: + click.secho('Size: {:,.0f}'.format(len(response.text)/float(1<<20)) + "MB", fg='red') + else: + click.secho('Something weird happened. Please report the issue.', fg='red') + except: + click.secho('Application doesn''t make use of FireBase', fg='red') + + #Now we've got the FireBase URL, lets request some data + diff --git a/objection/console/commands.py b/objection/console/commands.py index 35e2ebb6..6b80abfc 100644 --- a/objection/console/commands.py +++ b/objection/console/commands.py @@ -18,6 +18,7 @@ from ..commands.android import keystore from ..commands.android import pinning as android_pinning from ..commands.android import root +from ..commands.android import scanner as android_scanner from ..commands.ios import binary from ..commands.ios import bundles from ..commands.ios import cookies @@ -277,6 +278,15 @@ 'meta': 'Execute a shell command', 'exec': command.execute }, + 'scanner': { + 'meta': 'Command used to invoke the scanner', + 'commands': { + 'firebase': { + 'meta': 'Scan for leaking firebase DBs', + 'exec': android_scanner.firebase + }, + }, + }, 'hooking': { 'meta': 'Commands used for hooking methods in Android', 'commands': {