December 10, 2024

    Improve Your Mobile App Security in Less Than 5 Minutes

    As an Android or iOS developer, you're likely familiar with common best practices for developing secure mobile apps, such as validating external inputs, safely managing memory, and avoiding weak cryptography. However, even the most carefully written code can contain bugs, some of which may lead to exploitable security vulnerabilities, especially in native code written in languages like C or C++.

    Over the years, several defensive techniques have been developed, many of which can be enabled with just a few simple compiler flags - no need to alter your source code. In this blog, we provide an overview of some of these security features:

    • The attacks they protect against
    • A step-by-step guide to enabling these features
    • A discussion on the relevance based on the target operating system

    Setting compiler flags

    Before we go through the individual security-related compiler flags, let’s briefly recap how to set these, since that depends on whether you have an Android or an iOS app. If you’re already familiar with this topic, feel free to skip ahead!

    Android

    Typically, native code for Android apps is either compiled using the ndk-build script or using CMake in combination with Gradle. In the case of ndk-build, adding new flags can be done in the Application.mk file:

    APP_CFLAGS += -my-c-or-cpp-flag

    If you’re using CMake with Gradle instead, compiler flags can be added in your build.gradle file:

    
    android {
        ...
        externalNativeBuild {
            cmake {
                cFlags "-my-c-flag"
                cppFlags "-my-cpp-flag"
            }
        }
    }
    
    

    iOS

    For iOS apps, you can set compiler flags via the project’s build settings tab in Xcode:

    1. Select the project file in the Project Navigator.
    2. Go to the “Build Settings” tab for your target.
    3. Add your flags to the “Other C Flags” and/or “Other C++ Flags” section.

    Improve-Your-Mobile-App-Security-in-Less-Than-5-Minutes-diagram-2

    Compiler-based security features

    Stack canaries

    One of the fundamental protections against buffer overflow attacks in native code is the use of stack canaries. Buffer overflows occur when an attacker overflows a buffer on the stack, potentially overwriting the return address of a function to execute arbitrary code. This can lead to serious security vulnerabilities, including unauthorized access and system compromise. Stack canaries can be enabled by using the -fstack-protector-strong compiler flag.

    Relevant for Android: ✅ Relevant for iOS: ✅

    If you’re interested in further information on this topic, you may want to consider the Wikipedia article on buffer overflow protection and the iconic “Smashing The Stack For Fun And Profit” Phrack post.

    Pointer authentication (PAC)

    PAC helps prevent control flow attacks by cryptographically signing pointers, especially those used for return addresses and function pointers. This ensures that if a pointer is tampered with, the verification will fail, stopping the attack in its tracks. Check out this Arm documentation if you’d like to learn more about the inner workings of PAC.

    This feature relies on special hardware support, which might at first seem like a source of compatibility issues due to the natural heterogeneity of the mobile device landscape. Luckily, this is not really an issue! All currently supported iOS devices already support PAC and on Android the compiler makes sure to only use instructions that are simply no-ops on older devices.

    Relevant for Android: ✅ Relevant for iOS: ✅

    How to enable this on Android

    • If you’re using ndk-build: Set LOCAL_BRANCH_PROTECTION := standard in each module of your Android.mk
    • In case of Gradle with CMake, add the -mbranch-protection=standard compiler flag

    In addition to PAC, Google also recommends enabling Control Flow Integrity (CFI). You can read more about this topic on LLVM’s website.

    How to enable this on iOS

    In your Xcode build settings, add the arm64e target to the Architectures section. The reason why iOS can use a dedicated target for PAC is that Apple controls both hardware and software, allowing consistent enforcement across its devices. On Android, PAC is enabled via a compiler flag since the platform must accommodate a wide range of hardware with varying support for PAC.

    Improve-Your-Mobile-App-Security-in-Less-Than-5-Minutes-diagram-1

    You can get more information about this in Apple’s article about preparing your app to work with pointer authentication.

    Relocation Read-Only (RelRO)

    RelRO helps protect your app from memory corruption attacks. It works by making certain sections of your app’s memory read-only after they have been initialized. This is particularly important for protecting the Global Offset Table (GOT), a structure used by your app to manage dynamically linked functions. By making the GOT and other critical areas read-only, RelRO prevents attackers from modifying these pointers to hijack your app’s execution flow. RedHat has a good blog post explaining some more details about this topic.

    Relevant for Android: ✅ Not relevant for iOS: ❌ (no GOT structure)

    Ensure your mobile app is secure

    Securing your app goes beyond writing safe code, it requires a comprehensive approach that also includes hardening the build process of any native code. Enabling the compiler flags mentioned above helps reach this goal, reducing the risk of exploitation from common attacks without requiring additional effort or notable performance impact. However, setting up a secure build process isn’t a one-time task - it requires ongoing monitoring. As your app evolves and your team makes changes, it’s important to ensure that these security configurations remain intact. By integrating MAST tools into your CI pipeline, you can automatically test the security of the final product, catching issues like regressions in the build settings before shipping the app to your users.

    If you want to check if your app is protected using the above mentioned techniques, scan your app for free.

    Tag(s): Android , iOS , Technical , AppSweep

    Samuel Hopstock - Software Engineer

    Discover how Guardsquare provides industry-leading protection for mobile apps.

    Request Pricing

    Other posts you might be interested in