You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 3 Next »

Android apps that use SSL/TLS protocols for secure communication should properly verify server certificates. The basic verification includes:

  • verify that the subject (CN) of X.509 certificate and the URL matches
  • verify that the certificate is signed by the trusted CA
  • verify that the signature is correct
  • verify that the certificate is not expired

Android SDK  4.0 and later offers packages to implement capabilities to establish network connections. For example, by using java.net, javax.net, android.net or org.apache.http, a developer can create server sockets or HTTP connection. org.webkit offers functions necessary to implement web browsing capabilities.

A developer has the freedom to customize their SSL implementation, and thus has a responsibility to properly use SSL depending on the intent of the app as well as the environment the apps are used in. If the SSL is not correctly used, a user's sensitive data may leak via the vulnerable SSL communication channel.

Fahl et al [Fahl 2012] summarises the following patterns of the insecure use of SSL:

Trusting All Certificates

  • The developer implements the TrustManager interface so that it will trust all the server certificate (regardless of who signed it, what is the CN etc.)

Allowing All Hostnames

  • The app does not verify if the certificate is issued for the URL the client is connecting to.
  • When a client connects to example.com, it will accept a server certificate issued for some-other-domain.com.

Mixed-Mode / No SSL

  • A developer mixes secure and insecure connections in the same app or does not use SSL at all.

On Android, using HttpURLConnection is recommended for HTTP client implementation.

Noncompliant Code Example

The following code implements a custom MySSLSocketFactory class that inherits javax.net.ssl.SSLContext:

public class extends SSLSocketFactory {
            SSLContext sslContext;
            public MySSLSocketFactory (KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, 
KeyStoreException, UnrecoverableKeyException 
            {
                super(truststore);
                this.sslContext = SSLContext.getInstance("TLS");
                this.sslContext.init (null, new TrustManager[] {new X509TrustManager() {    
                    public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException
                             {
                    }
                    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException
                             {
                    }
                    public X509Certificate[] getAcceptedIssuers() {
                        return null;
                    }
                }}, null);
            }
            public Socket createSocket() throws IOException {
                return this.sslContext.getSocketFactory().createSocket();
            }
            public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException
                    , UnknownHostException {
                return this.sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
            }
        }
<tt>checkClientTrusted()</tt> and <tt>checkServerTrusted()</tt> are overriden to make a blank implementation so that 
<tt>SSLSocketFactory</tt> does not verify SSL certificate. <tt>MySSLSocketFactory</tt> class is used to create an instance of 
<tt>HttpClient</tt> in other part of the application:
        public static HttpClient getNewHttpClient() {
            DefaultHttpClient v6;
            try {
                KeyStore v5 = KeyStore.getInstance(KeyStore.getDefaultType());
                v5.load(null, null);
                MySSLSocketFactory mySSLScoket = new MySSLSocketFactory(v5);
                if(DefineRelease.sAllowAllSSL) {
                    ((SSLSocketFactory)mySSLScoket).setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
                }
                BasicHttpParams v2 = new BasicHttpParams();
                HttpConnectionParams.setConnectionTimeout(((HttpParams)v2), 30000);
                HttpConnectionParams.setSoTimeout(((HttpParams)v2), 30000);
                HttpProtocolParams.setVersion(((HttpParams)v2), HttpVersion.HTTP_1_1);
                HttpProtocolParams.setContentCharset(((HttpParams)v2), "UTF-8");
                SchemeRegistry v3 = new SchemeRegistry();
                v3.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
                v3.register(new Scheme("https", ((SocketFactory)mySSLScoket), 443));
                v6 = new DefaultHttpClient(new ThreadSafeClientConnManager(((HttpParams)v2), v3), ((HttpParams)v2));
            }
            catch(Exception v1) {
                v6 = new DefaultHttpClient();
            }
            return ((HttpClient)v6);
        }   

Proof of Concept

Typically, an application stores files in the directory as follows:

/sdcard/Android/data/com.company.app/files/save/appdata/save_appdata

Compliant Solution (Save a File on Internal Storage)

The following code uses the openFileOutput() method to create "myfile" in an application data directory with permission set to MODE_PRIVATE so that other apps cannot access the file:

 

private String filename = "myfile"
private String string = "sensitive data such as credit card number"
FileOutputStream fos = null;

try {
   fos = openFileOutput(filename, Context.MODE_PRIVATE);
   fos.write(string.getBytes());
   fos.close();
} catch (FileNotFoundException e) {
  // handle FileNotFoundException
} catch (IOException e) {
  // handle IOException
} finally {
  if (fos != null) {
    try {
      fos.close();
    } catch (IOException e) {
    }
  }
}

Risk Assessment

Storing sensitive information on external storage can leak sensitive information to malicious apps.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

DRD00-J

high

probable

medium

P12

L1

Automated Detection

It is possible to automatically detect whether an application writes to external storage. It is not feasible to automatically determine whether such output could be stored internally.

Related Vulnerabilities

  • JVN#92038939 mixi for Android information management vulnerability
  • JVN#05102851 Yome Collection for Android issue in management of IMEI

Related Guidelines

Android Secure Coding Guidebook by JSSEC

4.6 Secure File Handling
4.6.1.4 Handling external storage files
4.6.2.1 When creating new files, make them private
4.6.2.2 Don’t create files accessible from other apps with read/write privilege
4.6.2.3 Minimize the use of files stored in external storage such as SD card
4.6.2.4 Consider the lifetime of files when designing apps

Bibliography


 

      

 

  • No labels