Securing React Native Applications
Reading Time: 3 minutesReact Native is a very popular cross-platform mobile application development framework. In React native components are rendered in Native UI instead of the Webview UI. In this article, we will focus on the security of React Native applications. Before that let’s analyze the React Native application.
Analyzing React Native App
React Native has a different approach for cross-platform mobile applications. Traditionally, other platform uses webview to render the application. But, React Native run the JS code in a JavaScript VM based on the JavaScriptCore. It uses the Native JavaScriptCore on iOS and uses JavaScriptCore Libs to bundle the APK on android.
In React Native, JS uses JavaScript bridge to render various components and communicate with the native platforms. All the js files are bundled into a single JS file, which is known as entry-file.
We should consider the following security things while building the React Native application.
- Securing app to server connection
- Securing Local Data
- Integrity checks and securing apps from reverse engineering.
Securing app to server connection
- Usually, in mobile apps, APIs are the main and core part of the app. APIs are used to communicate between mobile apps and servers.
- Most of the app doesn’t secure this portion of the app. And the result is a massive data breach.
- Insecure Communication is highlighted in the OWASP Mobile Top 10 at #3.
- To secure the app communication between mobile app and server
- Use SSL/TLS connection for APIs.
- User access tokens to secure your session and API accesses.
- For this, we can use the SSL Pinning technique.
- On the latest versions of iOS (from iOS 9) and Android (From Android 9), SSL is required for the API communication. Although we can disable it from the Info.plist and AndroidManifest.xml file, it is not recommended. In addition to that, we can add pin our server certificates into our app, Which is known as a SSL Pinning.
- SSL Pinning is a technique that we use in the client-side to avoid man-in-the-middle attacks by validating the server certificates again even after SSL handshaking.
SSL Pinning in React Native
We use either fetch or libraries like axios, to consume the apis in our mobile app. Notwithstanding, these libraries don’t have support for SSL pinning. So, we have to use third-party plugins like react-native-ssl-pinning and react-native-pinch.
- react-native-ssl-pinning: this plugin uses OkHttp3 on Android and AFNetworking on iOS to provide SSL pinning and cookie handling. For this library, we have to put the certificate inside the app and have to handle the use case when the certificate is expired. Remember one thing, we have to provide a new update to the users of the app before the certificate expires.
- react-native-pinch: this plugin is similar to
react-native-ssl-pinning
Securing local data
Frequently we store data in the local storage of the device. There are many ways to store the data locally in react native. Like Async-storage, SQLite, pouchdb, and realm.
This usually occurs when the development team assumes that users/malware will not have access to the local filesystem. But in reality, it is very easy to access the filesystem. And as a result, mobile apps face massive malware attacks and private information leaks.
So to secure it we can use,
- For SQLite DB
- SQLite is the most common way to store data. A very popular and open-source extension for SQLite encryption is SQLCipher.
- For that, there are many libraries available in the react Native like react-native-sqlcipher-2, react-native-sqlcipher-storage.
- For Realm
- it has support for encryption by default. It uses the AES256 algorithm and the encrypted realm is verified using SHA-2 HMAC hash.
- Keychain and Keystore Access
- iOS and Android provide a native techniques to store data securely on the device. Keychain services and Android keystore allows developers to store small chunks of data in an encrypted database.
- React Native has 3 libraries that provide this feature with biometric/face auth:
Integrity checks and securing apps from reverse engineering
Rooted/Jailbreak devices should be considered as the inscure. On rooted devices, users can manipulate the OS features and can directly access the DBs and all to spoof the data. So, to avoid this, the App should detect that the device is rooted and should avoid the execution of the app. For that, we have a library called JailMonkey
JailMonkey can detect that is device Rooted/Jailbreak as well as it can also detect that is a device using the Mock Location.
Additionally, we can use react-native-device-info to check if an app is running in an emulator.
Protecting the Application Logic
- In React Native, the communication between Native and JavaScript code is handled by a JavaScript Bridge. The source JS files are compiled into one single bundle file known as an entry-file. it’s fair to assume the entry-file as the core application logic.
- a third-party can retrieve the code, reverse-engineer sensitive logic, or even tamper with the code to abuse the app (such as unlocking features or violating license agreements)
- To prevent this we can use a library like Jscrambler.
- It provides a series of layers to protect JavaScript.
- Polymorphic JavaScript & HTML5 obfuscation
- Code locks
- Self-defending (anti-tampering & anti-debugging)
- It provides a series of layers to protect JavaScript.
To get started with protecting React Native source code with Jscrambler, check the official guide.