Contact Us

Use the form on the right to contact us.

You can edit the text in this area, and change where the contact form on the right submits to, by entering edit mode using the modes on the bottom right. 

         

123 Street Avenue, City Town, 99999

(123) 555-6789

email@address.com

 

You can set your address, phone number, email and site description in the settings tab.
Link to read me page with more information.

Mutation Based Soundness Evaluation of Security Focused Static Analysis Tools for Android Apps

Anonymous Authors

This web page is a companion to our USENIX 2018 paper entitled "Evaluating Security-Focused Static Analysis Tools for Android using Systematic Mutation".

TABLE OF CONTENTs

  1. Discovered Security Vulnerabilities
  2. Mutation Operators

Discovered Security Vulnerabilities

Here we provide the list of all the security vulnerabilities that were discovered using μSE. Please, click on a vulnerability for more details.

Discovered Security Vulnerabilities

RunOnUIThread

Description:

Android Activities have access to the Activity.runOnUiThread() method, which accepts Runnables and executes their run() method on the UI thread. This example submits a Runnable containing a simple data leak within its run() method to the runOnUiThread() method.

Code Example:

 
    runOnUiThread(new Runnable() {
    @Override
    public void run() {
        String dataLeak = java.util.Calendar.getInstance().getTimeZone().getDisplayName();
        android.util.Log.d("leak-1", dataLeak);
    }
});

ButtonOnClickToDialogOnClick

Description:

This snippet creates an AlertDialog with a listener that will execute onClick() when the user selects an item from the dialog’s list. The onClick() callback contains a data leak. This code is placed within a function registered as a Button’s callback in an XML layout file. Data is leaked when the user clicks the Button and then clicks an item in the AlertDialog’s list.

Code Example:

     
    public void leakData(View view) {
    CharSequence[] items = {"item1", "item2", "item3"};
    new AlertDialog.Builder(this).setTitle("example")
            .setCancelable(true)
            .setItems(items, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int i) {
                    String dataLeak = java.util.Calendar.getInstance().getTimeZone().getDisplayName();
                    android.util.Log.d("leak-1", dataLeak);
                }
            })
            .create()
            .show();
}
Mutated Xml
     
    <Button
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:onClick="leakData" />

DialogFragmentShow

Description:

A DialogFragment contains a leak within its onCreateDialog() callback, which is called when the dialog is instantiated via DialogFragment.show().

Code Example:

     
   @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    DialogFragment example = new ExampleDialogFragment();
    example.show(getFragmentManager().beginTransaction(), "ExampleDialog");
}

public static class ExampleDialogFragment extends DialogFragment {
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        String dataLeak = java.util.Calendar.getInstance().getTimeZone().getDisplayName();
        android.util.Log.d("leak-1", dataLeak);
        return new AlertDialog.Builder(getActivity()).setTitle("example")
                .create();
    }
}

NavigationView

Description:

An Activity implementing NavigationView.OnNavigationItemSelectedListener has an additional lifecycle callback onNavigationItemSelected() which is called when the user clicks on any item in the navigation menu. This example has a simple data leak within that lifecycle callback.

Code Example:

     
  public class MainActivity extends Activity implements NavigationView.OnNavigationItemSelectedListener {
    @Override
    public boolean onNavigationItemSelected(MenuItem item) {
        String dataLeak = java.util.Calendar.getInstance().getTimeZone().getDisplayName();
        android.util.Log.d("leak-1", dataLeak);
        return false;
    }
}

ExecutorService

Description:

An ExecutorService manages threads, accepting Runnables and executing their run() methods in an available thread. In this sample, a simple data leak is contained within a Runnable passed to an ExecutorService that manages a single thread.

Code Example:

     
  ExecutorService service = Executors.newSingleThreadExecutor();
service.submit(new Runnable() {
    @Override
    public void run() {
        String dataLeak = java.util.Calendar.getInstance().getTimeZone().getDisplayName();
        android.util.Log.d("leak-1", dataLeak);
    }
});

PhoneStateListener

Description:

A data leak is placed within a PhoneStateListener’s onDataConnectionStateChanged() callback, which is called when the device’s data connection state changes, such as when the device loses or regains connection to the internet.

Code Example:

     
  @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    TelephonyManager manager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
    manager.listen(new PhoneListener(), PhoneStateListener.LISTEN_CALL_STATE);
}

private class PhoneListener extends PhoneStateListener {
    @Override
    public void onDataConnectionStateChanged(int state) {
        String dataLeak = java.util.Calendar.getInstance().getTimeZone().getDisplayName();
        android.util.Log.d("leak-1", dataLeak);
    }
}

BroadcastReceiver

Description:

Android BroadcastReceivers execute the onReceive() callback when an Intent matching the receiver’s IntentFilter is broadcast to the system. In this sample, a BroadcastReceiver dynamically registers another BroadcastReceiver in its onReceive() callback. The second receiver’s onReceive() callback contains a simple data leak.

Code Example:

     
  BroadcastReceiver receiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        BroadcastReceiver receiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String dataLeak = java.util.Calendar.getInstance().getTimeZone().getDisplayName();
                android.util.Log.d("leak-1", dataLeak);
            }
        };
        IntentFilter filter = new IntentFilter();
        filter.addAction("android.intent.action.SEND");
        registerReceiver(receiver, filter);
    }
};
IntentFilter filter = new IntentFilter();
filter.addAction("android.intent.action.SEND");
registerReceiver(receiver, filter);

LocationListenerTaint

Description:

A LocationListener allows Android applications to react to changes in the user’s location. In this example, a LocationListener is registered to save a data source when the location provider’s status changes, such as when the user loses or regains cellular service, and leak the data when the user moves and changes location.

Code Example:

     
 @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    LocationManager locationManager = (LocationManager)getSystemService(LOCATION_SERVICE);
    locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
}

private LocationListener locationListener = new LocationListener() {
    private String dataLeak = "";
    @Override
    public void onLocationChanged(Location location) {
        Log.d("leak", dataLeak);
    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
        dataLeak = java.util.Calendar.getInstance().getTimeZone().getDisplayName();
    }
};

NSDManager

Description:

An NsdManager.DiscoveryListener can be used to discover network services. In this example, a data leak source is placed within the onDiscoveryStarted() callback of the DiscoveryListener, which is called when the listener begins searching for services. Sinks are placed within the callbacks of a ResolveListener for either successful service resolution or failure, instantiated within the onServiceFound() callback of the DiscoveryListener.

Code Example:

     
 final NsdManager nsdManager = (NsdManager)this.getSystemService(Context.NSD_SERVICE);
NsdManager.DiscoveryListener listener = new NsdManager.DiscoveryListener() {
    String dataLeak = "";

    @Override
    public void onDiscoveryStarted(String serviceType) {
        dataLeak = java.util.Calendar.getInstance().getTimeZone().getDisplayName();
    }

    @Override
    public void onServiceFound(NsdServiceInfo serviceInfo) {
        NsdManager.ResolveListener resolver = new NsdManager.ResolveListener() {

            @Override
            public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) {
                Log.d("leak", dataLeak);
            }

            @Override
            public void onServiceResolved(NsdServiceInfo serviceInfo) {
                Log.d("leak", dataLeak);
            }
        };
        nsdManager.resolveService(serviceInfo, resolver);
    }
};
nsdManager.discoverServices("", NsdManager.PROTOCOL_DNS_SD, listener);

ListViewCallbackSequential

Description:

A ListView is instantiated with an onItemClickListener() whose onItemClick() callback will be called when an element in the ListView is selected. The callback first captures the element selected, casting it to the appropriate “Example” class, and then calls two functions within the class. The first function, “foo()” saves the source of a data leak to a private variable, and the second, “bar()”, leaks it.

Code Example:

     
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    ArrayList<Example/> examples = new ArrayList<Example/>();
    examples.add(new Example());
    ListView serviceTable = (ListView) findViewById(R.id.listview);
    serviceTable.setAdapter(new ArrayAdapter<Example/>(this,
            android.R.layout.simple_list_item_1, examples));
    serviceTable.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?/> parent, View view, int position, long id) {
            Example example = (Example) parent.getItemAtPosition(position);
            example.foo();
            example.bar();
        }
    });
}

private class Example {
    String dataLeAk;

    public void foo() {
        dataLeAk = Calendar.getInstance().getTimeZone().getDisplayName();
    }
    public void bar() {
        Log.d("leak", dataLeAk);
    }
}

ThreadTaint

Description:

A data leak source is saved to a variable within some method, and a Runnable containing a sink for the variable within its run() method is submitted to a Thread. It is important to note that the Thread is first saved to a variable before Thread.start() is called, as opposed to “new Thread(…).start()”.

Code Example:

     
final String dataLeak = Calendar.getInstance().getTimeZone().getDisplayName();
Thread thread = new Thread(new Runnable() {
    @Override
    public void run() {
        Log.d("leak-1", dataLeak);
    }
});
thread.start();

Fragments

Description:

A Fragment from the Android Support Library contains a simple data leak within its onCreateView() lifecycle callback. This callback is called when the Fragment is instantiated using the FragmentManager transaction mechanism.

Code Example:

     
public class LeakyFragment extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        String dataLeak = Calendar.getInstance().getTimeZone().getDisplayName();
        Log.d("leak-1", dataLeak);
        return inflater.inflate(R.layout.fragment_leaky, container, false);
    }
}

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Fragment test = new LeakyFragment();
        getSupportFragmentManager().beginTransaction().replace(R.id.fragment, test).commit();
    }
}

SQLiteOpenHelper

Description:

A class extending the SQLiteOpenHelper abstract class contains a simple data leak within its onCreate() callback. This callback is called when the referenced database is created for the first time.

Code Example:

     
public class MySQLiteHelper extends SQLiteOpenHelper {
    public MySQLiteHelper(Context context) {
        super(context, "example", null, 1);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        String dataLeak = Calendar.getInstance().getTimeZone().getDisplayName();
        Log.d("leak-1”, dataLeak);
    }
}


Security Mutation Operators & Schemes

Here we provide descriptions of the security mutation operator and mutation schemes implemented within μSE. Please, click on a mutation operator or scheme for more details.

Mutation Operator

DataLeakOperatorAST

Description:

Injects data leak variable declarations, sources, and sinks at locations marked by a given mutation scheme. For example, the simple data leak used in our experiments used this replacement strategy:
  • Declaration: String dataLeak{{ SOURCE_NUMBER }};
  • Source: datLeak{{ SOURCE_NUMBER }} = java.util.Calendar.getInstance().getTimeZone().getDisplayName();
  • Sink: android.util.Log.d(“leak-{{ SINK_NUMBER }}”, dataLeak{{ SOURCE_NUMBER }});

Detection Technique:

AST

Code Example:

Before
 
void foo() {
  // Declaration Mark 0
  // Source Mark 0
  // Sink Mark 0-0
}
After
 
void foo() {
  String dataLeak0;
  dataLeak0 = java.util.Calendar.getInstance().getTimeZone().getDisplayName();
  android.util.Log.d(“leak-0-0”, dataLeak0);
}

Mutation Schemes

SingleMethodSchemeAST

Description:

Marks every method with a declaration, source, and sink location consecutively.

Detection Technique:

AST

Code Example:

Before
 
void foo() {}
After
 
void foo() {
  // Declaration Mark 0
  // Source Mark 0
  // Sink Mark 0-0
}

MultiMethodSchemeAST

Description:

First marks sources at every method for declarations at every parent class to the method. Then, marks sinks at every method for every declaration reachable within that method.

Detection Technique:

AST

Code Example:

Before
 
class Example {
  void foo() {}
  void bar() {}
  class SubExample {
    void baz() {}
  }
}
After
 
class Example {
  // Declaration Mark 0
  // Declaration Mark 1
  // Declaration Mark 3
  void foo() {
    // Source Mark 0
    // Sink Mark 0-0
    // Sink Mark 1-0
    // Sink Mark 3-0
  }

  void bar() {
    // Source Mark 1
    // Sink Mark 0-1
    // Sink Mark 1-1
    // Sink Mark 3-1
  }
  
  class SubExample {
    // Declaration Mark 2
    void baz() {
      // Source Mark 2 
      // Source Mark 3
      // Sink Mark 0-2
      // Sink Mark 1-2
      // Sink Mark 2-0
      // Sink Mark 3-2
    }
  }
}