Monday, February 15, 2016

Android Information security Guidelines with code examples


Following are requirements which should be met before submitting any APK file to Information security or before publishing app at play store.  

Always Use Proguard

Proguard will obfuscate your code. If someone decompiles your code, Your code will be useless. Because proguard will change classes, methods, variables names.


1. Add these lines in build.gradle file to enable proguard.

 minifEnabled must be true.

buildTypes {
    release {
        minifyEnabled true

        proguardFiles getDefaultProguardFile('proguard-android.txt'),
                'proguard-rules.pro'    }
    debug {
        minifyEnabled false    
}
}


2. Configure proguard-rules.pro file in your project

If you are using libraries in your project. Proguard will replace classes or remove classes. And you will get ClassDefNotFoundException.

To avoid this. Add proguard rules in Pro-guard rules.pro file. Check all dependencies in project build.gradle file and add rules for each of them.

I am using volley, mix panel, ACRA, sliding menu, jackson libraries in my project for which I am using below rules.

Example:

-keep class android.support.v4.app.** { *; }
 -keep interface android.support.v4.app.** { *; }
-keep class android.support.v7.app.** { *; }
-keep interface android.support.v7.app.** { *; }
 -keep class android.support.v13.app.** { *; }
 -keep interface android.support.v13.app.** { *; }
-dontwarn android.support.design.**
-keep class android.support.design.** { *; }
-keep interface android.support.design.** { *; }
-keep public class android.support.design.R$* { *; }
#-dontwarn android.support.design.internal.NavigationMenu.**
android.support.design.widget.NavigationView -dontwarn org.apache.http.**
 -dontwarn com.mixpanel.**
-dontwarn org.codehaus.jackson.**
-dontwarn org.acra.ErrorReporter.**
-dontwarn com.jeremyfeinstein.slidingmenu.**
-keepnames class com.fasterxml.jackson.** { *; }
 -keepclassmembers public final enum org.codehaus.jackson.annotate.JsonAutoDetect$Visibility {

 public static final org.codehaus.jackson.annotate.JsonAutoDetect$Visibility *; } -keep class  com.tozny.crypto.android.AesCbcWithIntegrity$PrngFixes$* { *; }  


4. I used allatori  for String encryption and for hiding static code blocks in my application. as proguard do not obfuscate Strings so I had to use allotri for that purpose.

5. To avoid Intent Injection
    I will explain how to do this later.

6. Remove logs from application before publishing it to play store.

7. Do not allow application to be installed on rooted devices. so that your application sensitive  information is not exposed to other apps.

To do this below is code to check if device is rooted or not. finish splash activity or application is below code returns true.

public boolean isRooted() {

    // get from build info    String buildTags = android.os.Build.TAGS;
    if (buildTags != null && buildTags.contains("test-keys")) {
        return true;
    }

    // check if /system/app/Superuser.apk is present    try {
        File file = new File("/system/app/Superuser.apk");
        if (file.exists()) {
            return true;
        }
    } catch (Exception e1) {
        // ignore    }

    // try executing commands    return canExecuteCommand("/system/xbin/which su")
            || canExecuteCommand("/system/bin/which su") || canExecuteCommand("which su");
}

// executes a command on the systemprivate boolean canExecuteCommand(String command) {
    boolean executedSuccesfully;
    try {
        Runtime.getRuntime().exec(command);
        executedSuccesfully = true;
    } catch (Exception e) {
        executedSuccesfully = false;
    }

    return executedSuccesfully;
} 


Always Sign APK before giving it to Information Security team. Do not give APK in debug mode. It should be in release mode.

8. Sensitive information stored in Database and SharedPreferences should be encrypted. Because any one can read this on rooted devices or using different tools they can break APK file and can get all files.

9. compile 'com.scottyab:secure-preferences-lib:0.1.4'
I used above mentioned library for encrypting data stored in sharedPreferences. You can read its documentation for further information. There are many other libraries for SqliteDB and sharedPreferences encryption.

This is proguard rule which I am using for above library. To make sure that it do not obfuscate classes in this library. So my app do not crash.

-keep class com.tozny.crypto.android.AesCbcWithIntegrity$PrngFixes$* { *; }

You can check/search proguard rules against other libraries which you are using in your project.

10. Error messages in case of incorrect username/password should be general. We should never tell explicitly if username is not valid or password is not valid.

Further information can be found at below links.

References:
http://developer.android.com/training/articles/security-tips.html 
http://developer.android.com/training/best-security.html

Wednesday, February 10, 2016

How to read precise state of an outgoing call in Android programatically


In this example I will show you how to get precise call state in Android programatically using java reflection API. 


Add this in Android Manifest file. Declare Broadcast receiver.




<receiver
        android:name=".OutCallLogger"
        android:enabled="true"
        android:exported="true" >
            <intent-filter>
                <action android:name="android.intent.action.PRECISE_CALL_STATE" />
                <action android:name="android.intent.action.NEW_OUTGOING_CALL" />
            </intent-filter>
    </receiver>
Add below permissions in android manifest file.
<uses-permission android:name="android.permission.READ_PHONE_STATE" />  
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<uses-permission android:name="android.permission.READ_PRECISE_PHONE_STATE" />
Also add this line in manifest file.
 <uses-feature android:name="android.hardware.telephony"></uses-feature>
And this is your class which will be used for getting precised call state for outgoing calls.
 public class OutCallLogger extends BroadcastReceiver {
public OutCallLogger() {
}
TelephonyManager Tm;
ITelephony telephonyService;
Class c = null;
Method methodGetInstance = null;
Method methodGetActiveFgCallState=null;
String TAG="Tag";
Object objectCallManager=null;
Context context1;
Class<?> classCallManager;

Class telephonyClass;
Class telephonyStubClass;
Class serviceManagerClass;
Class serviceManagerStubClass;
Class serviceManagerNativeClass;
Class serviceManagerNativeStubClass;

Method telephonyCall;
Method telephonyEndCall;
Method telephonyAnswerCall;
Method getDefault;

Method[] temps;
Constructor[] serviceManagerConstructor;

// Method getService;
Object telephonyObject;
Object serviceManagerObject;
private Timer timer= null;

@Override
public void onReceive(Context context, Intent intent) {
    // TODO: This method is called when the BroadcastReceiver is receiving
    // an Intent broadcast.



    this.context1= context;
 Tm=(TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
final ClassLoader classLoader = this.getClass().getClassLoader();
try {
     classCallManager = classLoader.loadClass("com.android.internal.telephony.CallManager");
    Log.e(TAG, "CallManager: Class loaded " + classCallManager.toString());
    methodGetInstance = classCallManager.getDeclaredMethod("getInstance");
    methodGetInstance.setAccessible(true);
    Log.e(TAG, "CallManager: Method loaded " + methodGetInstance.getName());
    objectCallManager = methodGetInstance.invoke(null);
    Log.e(TAG, "CallManager: Object loaded " + objectCallManager.getClass().getName());
    Method[] aClassMethods = classCallManager.getDeclaredMethods();
    for(Method m : aClassMethods)
    {
        Log.e("MEthods", m.getName());
    }
    methodGetActiveFgCallState = classCallManager.getDeclaredMethod("getActiveFgCallState");
    Log.e(TAG, "CallManager: Method loaded " + methodGetActiveFgCallState.getName());

    Log.e(TAG, "CallManager: What is the Call state = " + methodGetActiveFgCallState.invoke(objectCallManager));
}
catch (ClassNotFoundException e) {
    Log.e(TAG, e.getClass().getName() + e.toString());
}
catch (NoSuchMethodException e) {
    Log.e(TAG, e.getClass().getName() + e.toString());
}
catch (InvocationTargetException e) {
    Log.e(TAG, e.getClass().getName() + e.toString());
}
catch (IllegalAccessException e) {
    Log.e(TAG, e.getClass().getName() + e.toString());
}
Tm.listen(new PhoneStateListener(){
    public void  onCallStateChanged(int state,String number) {
        super.onCallStateChanged(state, number);

        try {
            if (methodGetActiveFgCallState.invoke(objectCallManager).toString().toLowerCase() .equals("idle"))
            {
                //Toast.makeText(context1, "I am in idle state", Toast.LENGTH_LONG).show();            }
            if (methodGetActiveFgCallState.invoke(objectCallManager).toString().toLowerCase() .equals("active"))
            {
                //Toast.makeText(context1, "I am in active state", Toast.LENGTH_LONG).show();            }

            Toast.makeText(context1, " "+methodGetActiveFgCallState.invoke(objectCallManager).toString(), Toast.LENGTH_LONG).show();


        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block            e.printStackTrace();
        } catch (InvocationTargetException e) {
            // TODO Auto-generated catch block            e.printStackTrace();
        }

    }

}, PhoneStateListener.LISTEN_CALL_STATE);
}

A Toast will appear which will tell you about call state. Find a line which shows Toast.

Kotlin Android MVP Dagger 2 Retrofit Tutorial

http://developine.com/building-android-mvp-app-in-kotlin-using-dagger-retrofit/