Skip to content

Android Findings

Android_Checklist.md

Android Insecure Sockets

Overview

All

Remediation Procedure

Blackbox

Whitebox

Check for the HttpURLConnection class

URL url = new URL("http://www.android.com/");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
try {
	InputStream in = new BufferedInputStream(urlConnection.getInputStream());
	readStream(in);
} finally {
	urlConnection.disconnect();
}

Check for the Socket Class

public void listenSocket(){
//Create socket connection
   try{
     socket = new Socket("kq6py", 4321);
     out = new PrintWriter(socket.getOutputStream(), 
                 true);
     in = new BufferedReader(new InputStreamReader(
                socket.getInputStream()));
   } catch (UnknownHostException e) {
     System.out.println("Unknown host: kq6py");
     System.exit(1);
   } catch  (IOException e) {
     System.out.println("No I/O");
     System.exit(1);
   }
}

Certificate Pinning

Overview

Remediation Procedure

If you are using a new version of Android (API 24) then you can use the Network Security Configuration.
Add a similar configuration to your AndroidManifest.xml or the res/xml/network_security_config.xml file. For more information see the Official Android Documentation

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <domain-config>
        <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>

Using OKHTTP framework. Use newer versions of the framework as older versions are vulnerable to a Public Vulnerability

CertificatePinner certPinner = new CertificatePinner.Builder()
        .add("appmattus.com",
              "sha256/4hw5tz+scE+TW+mlai5YipDfFWn1dqvfLG+nU7tq1V8=")
        .build();

OkHttpClient okHttpClient = new OkHttpClient.Builder()
        .certificatePinner(certPinner)
        .build();

Set a single Certificate Authority

// Load CAs from an InputStream
// (could be from a resource or ByteArrayInputStream or ...)
CertificateFactory cf = CertificateFactory.getInstance("X.509");
// From https://www.washington.edu/itconnect/security/ca/load-der.crt
InputStream caInput = new BufferedInputStream(new FileInputStream("load-der.crt"));
Certificate ca;
try {
    ca = cf.generateCertificate(caInput);
    System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
} finally {
    caInput.close();
}

// Create a KeyStore containing our trusted CAs
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);

// Create a TrustManager that trusts the CAs in our KeyStore
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);

// Create an SSLContext that uses our TrustManager
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);

// Tell the URLConnection to use a SocketFactory from our SSLContext
URL url = new URL("https://certs.cac.washington.edu/CAtest/");
HttpsURLConnection urlConnection =
    (HttpsURLConnection)url.openConnection();
urlConnection.setSSLSocketFactory(context.getSocketFactory());
InputStream in = urlConnection.getInputStream();
copyInputStreamToOutputStream(in, System.out);

Blackbox

Install Certificate and set up proxy.
Verify that no traffic is intercepted.

Whitebox

Do a Check for Key classes like the ones below
- SSLContext
- CertificateFactory
- X509Certificate
- KeyStore

SQL Injection Android

Overview

Without proper access control, an attacker can obtain data from a SQLite databases using SQL Injection.

Remediation Procedure

Use SQL Parameterized Queries and validate ids using a valid access control.

...
id = this.getIntent().getExtras().getInt("id");
cursor = db.query(Uri.parse(invoices), columns, "id = ? ", {id}, null, null, null);
...

Blackbox

Whitebox

Android Messaging

Overview

The program performs SMS operations without verifying the phone number.

Remediation Procedure

SMS operations must not be performed without cause or consideration. Malicious software exploits these APIs to steal money and data from unwary users.

Blackbox

Whitebox

Look for the sendTextMessage function

sms.sendTextMessage(recipient, null, message, PendingIntent.getBroadcast(SmsMessaging.this, 0, new Intent(ACTION_SMS_SENT), 0), null);

Android Application has debugable set

Overview

When debugging is enabled
Debugging messages help attackers learn about the system and plan a form of attack.

Remediation Procedure

Make sure that debug flags are not set in production applications.

Blackbox

Whitebox

Look for the debuggable=true flag in the AndroidManifest.xml. It should be an element in the application tag.

Android Application has backup set

Overview

The program uses Android's backup service to save persistent application data to a remote cloud storage or locally depending on the backup Agent.

Android applications can be configured with this backup service by setting the allowBackup attribute to true (the default value) and defining the backupAgent attribute on the <application> tag.

Android however, does not guarantee the security of your data while using backup, as the cloud storage and transport vary from device to device.

Remediation Procedure

Make sure that backup flags are not set in production applications.

Blackbox

Whitebox

Look for the allowbackup=true flag in the AndroidManifest.xml. It should be an element in the application tag.

Android Application stores data in the external storage

Overview

The program requests permission to write data to Android's external storage and stores sensitive data to the external storage.

Remediation Procedure

Files written to external storage are readable and writeable by arbitrary programs and users. Programs must never write sensitive information, for instance personally identifiable information, to external storage. When you connect the Android device via USB to a PC or other device it enables USB mass storage mode. Any file written to external storage can be read and modified in this mode. In addition, files in external storage will remain there even after the application that wrote them is uninstalled, further increasing the risk that any sensitive information stored in them will be compromised.

Blackbox

Whitebox

Check for this line in the AndroidManifest.xml file.

 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> 

Check for Mentions of getExternalStorageDirectory

 private void WriteToFile(String what_to_write) {
        try{
            File root = Environment.getExternalStorageDirectory();
            if(root.canWrite()) {
                File dir = new File(root + "write_to_the_SDcard");
                File datafile = new File(dir, number + ".extension");
                FileWriter datawriter = new FileWriter(datafile);
                BufferedWriter out = new BufferedWriter(datawriter);
                out.write(what_to_write);
                out.close();
             }
        }
   }

Insecure SSL

Overview

The application implements a custom SSL interface.

When making a custom SSL interface there are many things to consider and implementing it without a library will introduce flaws into the application.
When applications that use custom SSL implementations applications may be vulnerable to vulnerable to a man-in-the-middle attack or other SSL vulnerabilities.

Android Hostname Verification Disabled

The use of AllowAllHostnameVerifier() or SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER turns off hostname verification when using SSL connections. This prevent SSLExceptions from triggering and could allow man-in-the-middle attacks.

Remediation Procedure

Blackbox

Whitebox

Example 1: The application sets the hostname verifier as below.

SSLSocketFactory sf = new CustomSSLSocketFactory(trustStore);
sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
//sf.AllowAllHostnameVerifier()

When Android calls createSocket() make sure that there is a hostname verification of the SSL Certificate.


Look for Calls to getInsecure(). This disables all SSL Certificate Checks


Android Insecure use of Shared Preferences

Overview

Saving private information, such as customer passwords, secret keys, and session tokens in to the Android Shared Preferences is insecure.

By default the Android Shared Preferences can only be accessed by the same application or an application in the same user group. The file itself is an unencrypted file in the Application directory and could be accessed if an attacker has physical access to the device.

Many developers trust the file system as a safe storage location for data, but it should not be trusted implicitly, particularly when privacy is a concern.

Remediation Procedure

Blackbox

Whitebox

Example 1: The following code stores user preferences using Android's SharedPreferences class. Among other values that are stored, the user supplied password is stored on the device in plain text.

SharedPreferences userPreferences = this.getSharedPreferences("userPreferences", MODE_WORLD_READABLE);
SharedPreferences.Editor editor = userPreferences.editor();
editor.putString("username", userName);
editor.putString("password", password);
...
editor.language("language", language);
...

Android Exported Activity

Overview

By default the value of Activity, Receiver or a Service that contains a intent-filter is exported. When the explored flag is enabled the specified component is accessible to other applications on the Android device.

 <activity android:name=".AndroidActivity"/> 
   <intent-filter android:label="activityName"/> 
    <action android:name=".androidAction"/> 
   </intent-filter> 
    ... 
 </activity> 
 ```

If target API is set to 16 or lower then the default exported activity is set to true

```xml
 <provider android:name=".AndroidProvider"/> 

Receiver without broadcastPermission:

When a receiver is registered in code without a broadcast Permission all broadcast will be captured by the receiver.

The code below shows an registerReceiver without the broadcastPermission.

...
context.registerReceiver(broadcastReceiver, intentFilter);
...

Broadcast without receiverPermission:

When a Broadcast is sent without a receiver Permission it can be intercepted by a malicious application.

The code below shows an registerReceiver without the receiverPermission.

...
context.sendBroadcast(intent);
...

Sticky Broadcast:

A Sticky Broadcast can not have a permission to specify with it and will always

Remediation Procedure

Use the registerReceiver function with a broadcastPermission.

registerReceiver(BroadcastReceiver receiver, IntentFilter filter, String broadcastPermission, Handler scheduler) 

Use the sendBroadcast function with a receiverPermission.

sendBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission) 

Blackbox

Whitebox

Permission Protection level set to Normal

Overview

When declaring a custom permission, there are four protection Levels normal, dangerous, signature, and signature or system.
- Normal permissions are granted to any application that requests them. (Depending on API level only after user confirmation)
- Signature permissions are granted only to applications signed by the same developer key as the package that defines the permission.
- Signature or system permissions are similar to signature permissions, but are also granted to packages in the Android system image.

Example 1: Below is an example of a custom permission declared with the normal protection level.

<permission android:name="custom.PERMISSION"
            android:label="@string/label_permission"
            android:description="@string/desc_permission"
            android:protectionLevel="normal">
</permission>

Remediation Procedure

Set protectionLevel to "signature" or "signature or system" depending on the needs of the application

Blackbox

Whitebox