Checker SensitiveDataCaching

belongs to group Advanced
Identify sensitive data stored in cache or in external storage

Frameworks supported by this checker

  • android up to API level 28

Warnings generated by this checker

  • SensitiveDataExposureThroughCachingWarning: sensitive data might flow into a cache [ CWE524 ]
  • SensitiveDataExposureThroughCachingWarningWithFlow: sensitive data might flow into a cache [ CWE524 ]
  • SensitiveDataStoredInExternalStorageWarning: sensitive data might flow into a external storage [ CWE538 ]
  • SensitiveDataStoredInExternalStorageWarningWithFlow: sensitive data might flow into a external storage [ CWE538 ]
  • SensitiveDataStoredInFileWarning: sensitive data might flow into a file [ CWE538 ]
  • SensitiveDataStoredInFileWarningWithFlow: sensitive data might flow into a file [ CWE538 ]

Options accepted by this checker

  • allowCheckWithoutAndroidManifest: allow check without manifest
    The analysis use the android manifest information to inferrer warnings, enabling this option is considered the worst case
  • dumpAnalysis: dump extensive (very large!) log information about the analysis
    Only useful for debugging the analyzer
  • dumpCompleteGraphs: dump the complete backward flow graph derivated from a sink
    If set to true, it produces an archive with the complete backward flow graphs that are used for the extraction of source-sink subgraphs
  • dumpDotWithInvariants: dump the analysed code in dot format, with flow information
    This option dumps a dot file for each method or constructor that is reachable from the entry points of the analysis. At the beginning of each code, a flow invariant is reported
  • flow: where possible, reconstructs the instruction flows leading to injection issues
    If true, it reconstructs the flow and provides detailed information on the warning if successful.
  • flowComputingSpeed: efficiency of the flow reconstruction
    This speciefies the efficiency of the flow reconstruct. Interesting only if option flow is set to true. (AVERAGE by default)
    • AVERAGE: reconstruct graphs until max of 2000 nodes
    • FAST: reconstruct graphs until max of 1000 nodes
    • FASTEST: reconstruct graphs until max of 500 nodes
    • SLOW: reconstruct graphs until max of 4000 nodes
    • SLOWEST: reconstruct graphs until max of integer limit nodes
  • fullJaif: dump a jaif file with the information flow information of the program, containing both the selected properties of interest and their complement
    The generated jaif file is a compact report of the program places that might contain a secret (tainted) value. Differently from the -jaif option, this generates explicit information for the places that contain a non-secret value as well and is hence a more verbose version of the same information
  • fullyQualifiedNames: use fully qualified class names in the jaif files
    The generated jaif file is a compact report of the program places that might contain a secret (tainted) value. This option forces the use of fully qualified class names in the jaif file, also when referring to classes in the same package that is being reported
  • jaif: dump a jaif file with the information flow information of the program
    A jaif file is a compact report of the program places that might contain a secret (tainted) value. It can be used for reference and documentation, but can also be imported in the source code of the program by using the annotation file utilities (see http://types.cs.washington.edu/annotation-file-utilities)
  • mergeCreations: merge the creation points for the same type inside the same class
    This enhances the efficiency of the creation points analysis performed as part of flow analysis but, in general, reduces the precision of the analyzer. However, it can be an important option to select for the analysis of very large applications and in library mode, in the rare cases when the creation points analysis takes too long to complete. This option is automatically selected for large programs
  • noOracle: do not use an oracle semantics for the fields
    This largely reduces the precision of the analysis, since Julia will not track anymore the fields that are definitely initialized to a non-secret (non-tainted) value before being accessed. Mainly useful for profiling and statistics
  • noUnreachable: do not dump information on unreachable code
    By selecting this option, the jaif files become smaller
  • reportLocals: dump information on local variables
    By selecting this option, the jaif file contains information on local variables as well and consequently becomes larger

Annotations understood by this checker

  • none


Description

The SensitiveDataCaching checker is dedicated to the analysis of Android applications. The SensitiveDataCaching checker is able to produce a warning when a sensitive system data is stored or cached in unsafe locations, inside the mobile device.
How sensitive system data are considered:

  • IMEI (International Mobile Equipment Identity)
  • Location Information
  • Phone numbers
  • Network information


Examples

Consider the following classes:

package com.juliasoft.julia.tests.checks.sensitiveDataCaching;

import java.util.Locale;

import android.app.Activity;
import android.content.ClipData;
import android.content.ClipDescription;
import android.content.ClipboardManager;
import android.content.Context;
import android.provider.UserDictionary;
import android.telephony.TelephonyManager;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;

public class CacheLeak extends Activity {

	
	  public void MyMethod()
	  {

		    TelephonyManager telephonyManager = (TelephonyManager) getSystemService(this.TELEPHONY_SERVICE); 
		    
		    String imei=telephonyManager.getDeviceId();
		    
		    UserDictionary.Words.addWord(this, imei, 100,"imei", Locale.ITALY);
		    
	  }


	  public void MyMethod2()
	  {

		    TelephonyManager telephonyManager = (TelephonyManager) getSystemService(this.TELEPHONY_SERVICE); 
		    
		    String imei=telephonyManager.getDeviceId();
		    
		    ClipboardManager cpManage =  (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
		    cpManage.setText(imei);
		    
	  }
	  
	  public void MyMethod4()
	  {
		  
		    TelephonyManager telephonyManager = (TelephonyManager) getSystemService(this.TELEPHONY_SERVICE); 
		    
		    String imei=telephonyManager.getDeviceId();
		    
		    SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
		    Editor editor = sharedPref.edit();
		    editor.putString("key", imei);
		    editor.commit();
	  }
}

This checker issues the following warnings:

CacheLeak.java:24: [SensitiveDataCaching: SensitiveDataExposureThroughCachingWarning] Possible sensitive data cached into actual parameter "word" of method "addWord"
CacheLeak.java:37: [SensitiveDataCaching: SensitiveDataExposureThroughCachingWarning] Possible sensitive data cached into actual parameter "text" of method "setText"
CacheLeak.java:50: [SensitiveDataCaching: SensitiveDataExposureThroughCachingWarning] Possible sensitive data cached into actual parameter "value" of method "putString"

The warnings are all relative to the storage of sensitive system data into cache. The example shown an IMEI (International Mobile Equipment Identity) cached in three particular locations. The first one allows to improperly access at the IMEI using the spellchecker and word suggestions (the line 24 set the IMEI in the UserDictionary) by user. The second allows to improperly access at the IMEI performing a paste action (the line 37 set the IMEI in the ClipboardManager) by user. The last one allows to improperly access at the IMEI using preferences and the autocompiling fields (the line 50 set the IMEI in the SharedPreferences.Editor) by user. These behaviors are dangerous because they could unintentionally allow the user to disclose this sensitive information.

Consider the following code:

package com.juliasoft.julia.tests.checks.sensitiveDataCaching;

import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import android.app.Activity;
import android.os.Environment;
import android.telephony.TelephonyManager;

public class ExternalStorageLeak extends Activity {

	
	  public void MyMethod()
	  {

		    try {
		    	
			    TelephonyManager telephonyManager = (TelephonyManager) getSystemService(this.TELEPHONY_SERVICE); 
			    String imei=telephonyManager.getDeviceId();
			    
				usingBufferedWritter1(imei);
				usingBufferedWritter2(imei);
				usingFileWriter(imei);
				usingPrintWriter(imei);
				usingFileOutputStream(imei);
				usingDataOutputStream(imei);
				usingFileChannel(imei);
				usingPath(imei);
				
			} catch (IOException e) {
				e.printStackTrace();
			}

		    
	  }

	  public static void usingBufferedWritter1(String fileContent) throws IOException
	  {
	       
	      BufferedWriter writer = new BufferedWriter(new FileWriter("myfile0.txt"));
	      writer.write(fileContent);
	      writer.close();
	  }
	  
	  public static void usingBufferedWritter2(String fileContent) throws IOException
	  {
	       
	      BufferedWriter writer = new BufferedWriter(new FileWriter(Environment.getExternalStorageDirectory()+"myfile1.txt"));
	      writer.write(fileContent);
	      writer.close();
	  }

	  public static void usingFileWriter(String fileContent) throws IOException
	  {
	       
	      FileWriter fileWriter = new FileWriter("/sdcard/Android/data/myfile2.txt");
	      fileWriter.write(fileContent);
	      fileWriter.close();
	  }
	  
	  public static void usingPrintWriter(String fileContent) throws IOException
	  {
	       
	      FileWriter fileWriter = new FileWriter(Environment.getLegacyExternalStorageDirectory()+"myfile3.txt");
	      PrintWriter printWriter = new PrintWriter(fileWriter);
	      printWriter.print(fileContent);
	      printWriter.close();
	  }
	  
	  public static void usingFileOutputStream(String fileContent) throws IOException
	  {
	    	       
	      FileOutputStream outputStream = new FileOutputStream(new File(Environment.getExternalStorageDirectory(),"myfile4.txt"));
	      byte[] strToBytes = fileContent.getBytes();
	      outputStream.write(strToBytes);
	    
	      outputStream.close();
	  }
	  
	  public static void usingDataOutputStream(String fileContent) throws IOException
	  {
	       
	      FileOutputStream outputStream = new FileOutputStream(Environment.getLegacyExternalStorageObbDirectory()+"myfile5.txt");
	      DataOutputStream dataOutStream = new DataOutputStream(new BufferedOutputStream(outputStream));
	      dataOutStream.writeUTF(fileContent);
	    
	      dataOutStream.close();
	  }
	  
	  public static void usingFileChannel(String fileContent) throws IOException
	  {
	       
	      RandomAccessFile stream = new RandomAccessFile(Environment.getExternalStorageDirectory()+"myfile6.txt", "rw");
	      FileChannel channel = stream.getChannel();
	      byte[] strBytes = fileContent.getBytes();
	      ByteBuffer buffer = ByteBuffer.allocate(strBytes.length);
	      buffer.put(strBytes);
	      buffer.flip();
	      channel.write(buffer);
	      stream.close();
	      channel.close();
	  }
  
	  
	  public static void usingPath(String fileContent) throws IOException
	  {

	      Path path = Paths.get(Environment.getExternalStorageDirectory()+"myfile7.txt");
	    
	      Files.write(path, fileContent.getBytes());
	  }
}

This checker issues the following warnings:

ExternalStorageLeak.java:53: [SensitiveDataCaching: SensitiveDataStoredInFileWarning] Possible storing of sensitive data into actual parameter "arg 0" of method "write"
ExternalStorageLeak.java:61: [SensitiveDataCaching: SensitiveDataStoredInExternalStorageWarning] Possible external storing of sensitive data into actual parameter "arg 0" of method "write"
ExternalStorageLeak.java:69: [SensitiveDataCaching: SensitiveDataStoredInExternalStorageWarning] Possible external storing of sensitive data into actual parameter "arg 0" of method "write"
ExternalStorageLeak.java:78: [SensitiveDataCaching: SensitiveDataStoredInExternalStorageWarning] Possible external storing of sensitive data into actual parameter "arg 0" of method "print"
ExternalStorageLeak.java:87: [SensitiveDataCaching: SensitiveDataStoredInExternalStorageWarning] Possible external storing of sensitive data into actual parameter "arg 0" of method "write"
ExternalStorageLeak.java:97: [SensitiveDataCaching: SensitiveDataStoredInExternalStorageWarning] Possible external storing of sensitive data into actual parameter "arg 0" of method "writeUTF"
ExternalStorageLeak.java:111: [SensitiveDataCaching: SensitiveDataStoredInExternalStorageWarning] Possible external storing of sensitive data into actual parameter "arg 0" of method "write"
ExternalStorageLeak.java:122: [SensitiveDataCaching: SensitiveDataStoredInExternalStorageWarning] Possible external storing of sensitive data into actual parameter "arg 0" of method "write"

The warnings are all relative to the storage/caching of sensitive system data into files. Furthermore, the analysis detects whether the file path is on an external storage or not. Typically, the external memories are more sensitive because they could be read by other unauthorized apps and could lead to security issue.