Last active
April 9, 2018 10:06
-
-
Save SleepyLctl/27f917285de7c7552969fa4978991ec5 to your computer and use it in GitHub Desktop.
Android Testing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
APK to java | |
-- dex2jar + jd-gui | |
-- jadx | |
-- apktool? | |
https://stackoverflow.com/questions/1249973/decompiling-dex-into-java-sourcecode |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
http://mobiletools.mwrinfosecurity.com/drozer/blog | |
Install Drozer | |
- dpkg -i drozer.dpgk | |
Allow Developer Mode + USB in phone | |
Allow port forwarding | |
# adb forward tcp:31415 tcp:31415 | |
# adb devices | |
If unauthorized, confirm phone prompt | |
# drozer console connect | |
dz> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Based on: https://sushi2k.gitbooks.io/the-owasp-mobile-security-testing-guide/content/0x05d-Testing-Data-Storage.html | |
******************************************************************* | |
******************************************************************* | |
Testing Local Storage for Sensitive Data | |
******************************************************************* | |
******************************************************************* | |
############################################## | |
Overview | |
############################################## | |
Public data should be available to everyone, but sensitive and private data must be protected, or, better yet, kept out of device storage. | |
-------------- | |
Shared Preferences | |
- /data/data/[package]/shared_preferences | |
-------------- | |
SQLite Databases | |
==Unecrypted DB | |
SQLiteDatabase notSoSecure = openOrCreateDatabase("privateNotSoSecure",MODE_PRIVATE,null); | |
notSoSecure.execSQL("CREATE TABLE IF NOT EXISTS Accounts(Username VARCHAR, Password VARCHAR);"); | |
notSoSecure.execSQL("INSERT INTO Accounts VALUES('admin','AdminPass');"); | |
notSoSecure.close(); | |
# /data/data/<package-name>/databases/privateNotSoSecure | |
==Encrypted DB | |
SQLiteDatabase secureDB = SQLiteDatabase.openOrCreateDatabase(database, "password123", null); | |
secureDB.execSQL("CREATE TABLE IF NOT EXISTS Accounts(Username VARCHAR,Password VARCHAR);"); | |
secureDB.execSQL("INSERT INTO Accounts VALUES('admin','AdminPassEnc');"); | |
secureDB.close(); | |
# Weak Passwd/Bruteforce/Authentication Token/Hardcoded Passwd | |
-------------- | |
Realm Databases(https://realm.io/docs/java/latest/) | |
//the getKey() method either gets the key from the server or from a Keystore, or is deferred from a password. | |
RealmConfiguration config = new RealmConfiguration.Builder() | |
.encryptionKey(getKey()) | |
.build(); | |
Realm realm = Realm.getInstance(config); | |
-------------- | |
Internal Storage | |
Search for the class FileInputStream to find out which files are opened and read within the app. | |
- MODE_PRIVATE (only secure) | |
-------------- | |
External Storage | |
- Files saved to external storage are world-readable | |
- !! It's also worth knowing that files stored outside the application folder (data/data/<package-name>/) will not be deleted when the user uninstalls the application. | |
Find a file, discard Errors; | |
find / -name "*file*" 2>/dev/null | |
############################################## | |
Best Practices | |
############################################## | |
- KeyStore | |
- Users are authorized to use keys for a limited period of time after authentication. In this mode, all keys can be used as soon as the user unlocks the device. You can customize the period of authorization for each key. You can use this option only if the secure lock screen is enabled. If the user disables the secure lock screen, all stored keys will become permanently invalid. | |
- import java.security.KeyStore, import javax.crypto.Cipher, import java.security.SecureRandom | |
- Use the store(OutputStream stream, char[] password) function to store the KeyStore to disk with a password. Make sure that the password is provided by the user, not hard-coded. | |
############################################## | |
Static Analysis | |
############################################## | |
- Check AndroidManifest.xml for read/write external storage permissions, for example, | |
uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE". | |
- Check the source code for keywords and API calls that are used to store data: | |
- MODE_WORLD_READABLE or MODE_WORLD_WRITABLE: You should avoid using MODE_WORLD_WRITEABLE and MODE_WORLD_READABLE for files because any app will be able to read from or write to the files, even if they are stored in the app's private data directory. If data must be shared with other applications, consider a content provider. A content provider offers read and write permissions to other apps and can grant dynamic permission on a case-by-case basis. | |
- Classes and functions, such as: | |
the SharedPreferences class ( stores key-value pairs) | |
the FileOutPutStream class (uses internal or external storage) | |
the getExternal* functions (use external storage) | |
the getWritableDatabase function (returns a SQLiteDatabase for writing) | |
the getReadableDatabase function (returns a SQLiteDatabase for reading) | |
the getCacheDir and getExternalCacheDirs function (use cached files) | |
- !! resources (typically at res/values/strings.xml) | |
############################################## | |
Dynamic Analysis | |
############################################## | |
Install and use the app, executing all functions at least once. Data can be generated when entered by the user, sent by the endpoint, or shipped with the app. Then complete the following: | |
- Identify development files, backup files, and old files that shouldn't be included with a production release. | |
- Determine whether SQLite databases are available and whether they contain sensitive information. SQLite databases are stored in /data/data/<package-name>/databases. | |
- Check Shared Preferences that are stored as XML files (in /data/data/<package-name>/shared_prefs) for sensitive information. Avoid using Shared Preferences and other mechanisms that can't protect data when you are storing sensitive information. Shared Preferences is insecure and unencrypted by default. You can use recure-preferences to encrypt the values stored in Shared Preferences, but the Android KeyStore should be your first choice for storing data securely. | |
- Check the permissions of the files in /data/data/<package-name>. Only the user and group created when you installed the app (e.g., u0_a82) should have user read, write, and execute permissions (rwx). Other users should not have permission to access files, but they may have execute permissions for directories. | |
- Determine whether a Realm database is available in /data/data/<package-name>/files/, whether it is unencrypted, and whether it contains sensitive information. By default, the file extension is realm and the file name is default. Inspect the Realm database with the Realm Browser. | |
- Check external storage for data. Don't use external storage for sensitive data because it is readable and writeable system-wide. | |
Files saved to internal storage are by default private to your application; neither the user nor other applications can access them. When users uninstall your application, these files are removed. | |
******************************************************************* | |
******************************************************************* | |
Testing Logs for Sensitive Data | |
******************************************************************* | |
******************************************************************* | |
############################################## | |
Static Analysis | |
############################################## | |
Check the app's source code for logging mechanisms by searching for the following keywords: | |
Functions and classes, such as: | |
android.util.Log | |
Log.d | Log.e | Log.i | Log.v | Log.w | Log.wtf | |
Logger | |
Keywords and system output: | |
System.out.print | System.err.print | |
logfile | |
logging | |
logs | |
############################################## | |
Best Practices | |
############################################## | |
- While preparing the production release, you can use tools like ProGuard (included in Android Studio) to delete logging-related code. | |
############################################## | |
Dynamic Analysis | |
############################################## | |
- Use all the mobile app functions at least once, then identify the application's data directory and look for log files (/data/data/<package-name>). Check the application logs to determine whether log data has been generated; some mobile applications create and store their own logs in the data directory. | |
- Many application developers still use System.out.println or printStackTrace instead of a proper logging class. Therefore, your testing strategy must include all output generated while the application is starting, running and closing. To determine what data is directly printed by System.out.println or printStackTrace, you can use Logcat. | |
$ adb logcat > logcat.log | |
******************************************************************* | |
******************************************************************* | |
Determining Whether Sensitive Data is Sent to Third Parties | |
******************************************************************* | |
******************************************************************* | |
############################################## | |
Static Analysis | |
############################################## | |
- You can embed third-party services in apps. These services can implement tracker services, monitor user behavior, sell banner advertisements, improve the user experience, and more. | |
- Most third-party services are implemented in one of two ways: | |
- With a standalone library, such as an Android project Jar that is included in the APK | |
- With a full SDK | |
############################################## | |
Dynamic Analysis | |
############################################## | |
- man-in-the-middle (MITM) attack with Burp Suite Professional | |
******************************************************************* | |
******************************************************************* | |
Determining Whether the Keyboard Cache Is Disabled for Text Input Fields | |
******************************************************************* | |
******************************************************************* | |
When users type in input fields, the software automatically suggests data. This feature can be very useful for messaging apps. Hovewer, the keyboard cache may disclose sensitive information when the user selects an input field that takes this type of information. | |
############################################## | |
Static Analysis | |
############################################## | |
<EditText | |
android:id="@+id/KeyBoardCache" | |
android:inputType="textNoSuggestions"/> | |
******************************************************************* | |
******************************************************************* | |
Finding Sensitive Data on the Clipboard | |
******************************************************************* | |
******************************************************************* | |
- Start the app and click in the input fields that take sensitive data. If strings are suggested, the keyboard cache has not been disabled for these fields. | |
############################################## | |
Dynamic Analysis | |
############################################## | |
- You can use the Drozer module post.capture.clipboard to extract data from the clipboard: | |
dz> run post.capture.clipboard | |
[*] Clipboard value: ClipData.Item { T:Secretmessage } | |
******************************************************************* | |
******************************************************************* | |
Determining Whether Sensitive Stored Data Has Been Exposed via IPC Mechanisms | |
******************************************************************* | |
******************************************************************* | |
############################################## | |
Best Practices | |
############################################## | |
If you expose a content provider, determine whether parameterized query methods (query, update, and delete) are being used to prevent SQL injection. If so, make sure all their arguments are properly sanitized. | |
############################################## | |
Static Analysis | |
############################################## | |
- The first step is to look at AndroidManifest.xml to detect content providers exposed by the app. You can identify content providers by the <provider> element. Complete the following steps: | |
- Determine whether the value of the export tag is "true" (android:exported="true"). Even if it is not, the tag will be set to "true" automatically if an <intent-filter> has been defined for the tag. If the content is meant to be accessed only by the app itself, set android:exported to "false." If not, set the flag to "true" and define proper read/write permissions. | |
- Determine whether the data is being protected by a permission tag (android:permission). Permission tags limit exposure to other apps. | |
- Determine whether the android:protectionLevel attribute has the value signature. This setting indicates that the data is intended to be accessed only by apps from the same enterprise (i.e., signed with the same key). To make the data accessible to other apps, apply a security policy with the <permission> element and set a proper android:protectionLevel. If you use android:permission, other applications must declare corresponding <uses-permission> elements in their manifests to interact with your content provider. You can use the android:grantUriPermissions attribute to grant more specific access to other apps; you can limit access with the <grant-uri-permission> element. | |
############################################## | |
Dynamic Analysis | |
############################################## | |
- You can use the Drozer module: | |
dz> run app.provider.info -a com.mwr.example.sieve | |
dz> run scanner.provider.finduris -a com.mwr.example.sieve | |
dz> run app.provider.query content://com.mwr.example.sieve.DBContentProvider/Passwords/ --vertical | |
(Insert/Delete/Update) | |
dz> run app.provider.insert content://com.vulnerable.im/messages | |
******************************************************************* | |
******************************************************************* | |
SQL Injection in Content Providers | |
******************************************************************* | |
******************************************************************* | |
- You can use the Drozer module app.provider.query to test for SQL injection by manipulating the projection and selection fields that are passed to the content provider: | |
dz> run app.provider.query content://com.mwr.example.sieve.DBContentProvider/Passwords/ --projection "'" | |
dz> run app.provider.query content://com.mwr.example.sieve.DBContentProvider/Passwords/ --selection "'" | |
dz> run app.provider.query content://com.mwr.example.sieve.DBContentProvider/Passwords/ --projection "* FROM Key;--" | |
| Password | pin | | |
| thisismypassword | 9876 | | |
You can automate these steps with the scanner.provider.injection module. | |
dz> run scanner.provider.injection -a com.mwr.example.sieve | |
******************************************************************* | |
******************************************************************* | |
File System Based Content Providers | |
******************************************************************* | |
******************************************************************* | |
dz> run scanner.provider.traversal -a com.mwr.example.sieve | |
Scanning com.mwr.example.sieve... | |
Vulnerable Providers: | |
content://com.mwr.example.sieve.FileBackupProvider/ | |
content://com.mwr.example.sieve.FileBackupProvider | |
$ adb shell content query --uri content://com.owaspomtg.vulnapp.provider.CredentialProvider/credentials | |
Row: 0 id=1, username=admin, password=StrongPwd | |
Row: 1 id=2, username=test, password=test |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
adb shell content query --uri content://jakhar.aseem.diva.provider.notesprovider/notes | |
dz> run scanner.provider.finduris -a jakhar.aseem.diva | |
dz> run app.provider.query content://jakhar.aseem.diva.provider.notesprovider/notes |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
adb shell am start -n <package>/.<activity> -a <action> --ez <param> <bool> | |
--ez = param boolean | |
--ei = param integer | |
--eu = param uri |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment