Recent studies [Poeplau. 2014] showed that developers of Android applications and frameworks, even the most famous ones (e.g., Facebook, Google Mobile Ads SDK), need to load code dynamically. This technique has the advantages of minimizing the code memory footprint, and enabling silent updates strategies to decouple updates of the main application from those of its third-party libraries. Unfortunately, there are security drawbacks as well. Firstly, malware authors
may use dynamic code loading to bypass antivirus checks by loading malicious code at runtime from an apparently benign application. Secondly, Android does
not perform any code verification for dynamically loaded code. Therefore, a
man-in-the-middle attacker can effectively modify the dynamically loaded code executed on the victim’s machine without being spotted. These vulnerabilities appeared in 16% of the top 50 free applications of the Google Play Store in August 2013. Arguably, the main source of error is assuming that developers are security experts, which is not often the case.
In this work, we remove such assumption, and we purpose a backward-compatible redesign of the Android API functions needed for implementing dynamic code loading, making this functionality secure by default. We implemented our proposed design in a Java library, named Grab’n Run (GNR), that can be incorporated in any Android project. Differently from previous works, GNR requires no modification of the underlying runtime, ensuring easier adoption. To further help developers migrating existing applications, we also designed and implemented a repackaging tool, which rewrites dynamic-code-loading calls to port them to use our secure API.
We validated GNR through a case study involving 9 Android developers.
Without GNR, 6 of them introduced security vulnerabilities by using HTTP connection for retrieving the code instead of HTTPS, whereas 4 of them introduced another vulnerability by storing the code in a world-writable location, and, in the end, all of them forgot to implement custom integrity checks on the fetched code. The participants also confirms that the learning effort for GNR is little or close to zero, and that this library is easier to maintain, simpler to read, and more flexible than native DexClassLoader API. Finally, by comparing the performance of GNR against DexClassLoader, We found out that the overhead introduced by our library on load operations is negligible.