Android Security Measures
Android Security
If you’re creating an app or have an app in the market, chances are, you’ve often stopped to consider how to secure your app, your data, and your customer’s data.
A mobile app needs a good bit of plumbing to make it work: there’s software code , business logic on the back-end network and client’s side, databases, APIs funneling data between the two, device and its operating system, and user. Each plays an important role in the fabric of an app’s security. For companies with mobile apps in a crowded, competitive market, having robust security could make a huge difference. Here are a few tips for you to take into consideration while working on mobile app security:
- Signature-Based Permission
Why: It checks that app accessing data is signed with an original signing key.
Implementation:
<manifest xmlns:android=”http://schemas.android.com/apk/res/android"
package=”com.example.myapp”>
<permission android:name=”android.permission.INTERNET”
android:protectionLevel=”signature” />
2. Use SSL Traffic
Why: Used to establish an encrypted link between server and client.
Implementation: If your app communicates with a web server that has a certificate issued by a well-known, trusted CA, you can use this HTTPS request-
URL url = new URL(“https://www.google.com");
HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
urlConnection.connect();
InputStream in = urlConnection.getInputStream();
3. Add Network Security Configuration
Why: Used to establish a secure connection between server and client.
Implementation:
For Android N and above
a. Declare the configuration in your app’s manifest.
<manifest>
<application
android:networkSecurityConfig=”@xml/network_security_config”>
</application>
</manifest>
b. Add an XML resource file, located at res/xml/network_security_config.xml.
<network-security-config>
<domain-config cleartextTrafficPermitted=”false”>
<domain includeSubdomains="true">appmattus.com</domain>
<pin-set>
<pin digest="SHA-256">4hw5tz+scE+TW+mlai5YipDfFWn1dqvfLG+nU7tq1V8=</pin>
<pin digest="SHA-256">YLh1dUR9y6Kja30RrAn7JKnbQG/uEtLMkBgFF2Fuihg=</pin>
</pin-set>
</domain-config>
</network-security-config>
For Android N and above,Below Android N
To get public keys with a domain name, the code below prints out the public keys in the chain as an SHA-256 hash using base 64 encoding.
openssl s_client -showcerts -connect domain.com:443 </dev/null 2>/dev/null|openssl x509 -outform PEM >mycertfile.pem
Now run this command to get your key.
openssl x509 -in mycertfile.pem -pubkey -noout | openssl rsa -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64
c. Using OKHTTP:
CertificatePinner certPinner = new CertificatePinner.Builder()
.add("domain.com",
"sha256/4hw5tz+scE+TW+mlai5YipDfFWn1dqvfLG+nU7tq1V8=")
.build();
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.certificatePinner(certPinner)
.build();
Using Retrofit, as Retrofit built on top of OkHttp, configuring it for pinning is as simple as setting up an OkHttpClient as shown above and supplying that to your Retrofit.Builder.
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://domain.com")
.addConverterFactory(GsonConverterFactory.create())
.client(okHttpClient)
.build();
4. Use Encryption Algorithm like AES to Save Credentials
Why: Enhances the security of a message or file. To encrypt a message, you need the right key, and you need the right key to decrypt it as well.
Implementation:
a. Generate a signed key.
public static SecretKey generateKey()
{
return secret = new SecretKeySpec(password.getBytes(), “AES”);
}
b. Encrypt a message, and get an encrypted byte array.
public static byte[] encryptMsg(String message, SecretKey secret)
{
/* Encrypt the message. */
Cipher cipher = null;
cipher = Cipher.getInstance(“AES/ECB/PKCS5Padding”);
cipher.init(Cipher.ENCRYPT_MODE, secret);
byte[] cipherText = cipher.doFinal(message.getBytes(“UTF-8”));
return cipherText;
}
c. Decrypt byte array and get original message back.
public static String decryptMsg(byte[] cipherText, SecretKey secret)
{
/* Decrypt the message, given derived encContentValues and initialization vector. */
Cipher cipher = null;
cipher = Cipher.getInstance(“AES/ECB/PKCS5Padding”);
cipher.init(Cipher.DECRYPT_MODE, secret);
String decryptString = new String(cipher.doFinal(cipherText), “UTF-8”);
return decryptString;
}
5. Use SQL db Encryption
Why: Enhances security of SQLite data.
Implementation:
a. Add dependency in gradle file.
implementation ‘net.zetetic:android-database-sqlcipher:3.5.9@aar’
b. Call InitializeSQLCipher() from onCreate.
private void InitializeSQLCipher() {
SQLiteDatabase.loadLibs(this);
File databaseFile = getDatabasePath(“database.db”);
databaseFile.mkdirs();
databaseFile.delete();
SQLiteDatabase database = SQLiteDatabase.openOrCreateDatabase(file, “test”, null);
database.execSQL(“create table t1(a, b)”);
database.execSQL(“insert into t1(a, b) values(?, ?)”, new Object[]{“parameter 1”,
“parameter 2”});
}
6. Protect Access to App’s Content Provider
Why: Prevent other apps from accessing your app’s data.
Implementation:
<provider
android:name=”android.support.v4.content.FileProvider”
android:authorities=”com.example.myapp.fileprovider”
android:exported=”false” //this will prevent other apps from //accessing your apps data>
</provider>
7. Obfuscation
Why: Obfuscating your app makes reverse engineering of the app very difficult.
Implementation:
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
8. Use Dexguard(a more powerful proguard tool)
Why: DexGuard provides advanced protection for Android applications.
9. Prevent Installation in Rooted Devices
Why: Rooted user can access the system directories of any app. They can be a serious security problem.
Implementation: If isDeviceRooted() returns true. Prevent the user from using the app.
public class RootUtil {
public static boolean isDeviceRooted() {
return checkRootMethod1() || checkRootMethod2() || checkRootMethod3();
}private static boolean checkRootMethod1() {
String buildTags = android.os.Build.TAGS;
return buildTags != null && buildTags.contains(“test-keys”);
}private static boolean checkRootMethod2() {
String[] paths = { “/system/app/Superuser.apk”, “/sbin/su”, “/system/bin/su”, “/system/xbin/su”, “/data/local/xbin/su”, “/data/local/bin/su”, “/system/sd/xbin/su”,
“/system/bin/failsafe/su”, “/data/local/su”, “/su/bin/su”};
for (String path : paths) {
if (new File(path).exists()) return true;
}
return false;
}private static boolean checkRootMethod3() {
Process process = null;
try {
process = Runtime.getRuntime().exec(new String[] { “/system/xbin/which”, “su” });
BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
if (in.readLine() != null) return true;
return false;
} catch (Throwable t) {
return false;
} finally {
if (process != null) process.destroy();
}
}
}
Mobile is where users are, and that is where hackers are lurking to try and steal sensitive information and compromise an app’s security. With a solid strategy for app security and a top-notch mobile developer on hand to help you respond quickly to threats and bugs, your app will be a lot more safe and secure for users. And will also ensure their loyalty (and your assets) in the future.