Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to hide API URL and parameters in Android APP?

I'm curious to know that without commercial product for obfuscation, is there any way where I can store API url and parameters safely which cannot be compiled in reverse engineering? I have tried all my apps and their API url and code is easy to read. I'm concerned about security.

like image 566
Chirag Joshi Avatar asked Oct 18 '17 18:10

Chirag Joshi


3 Answers

I found a solution to hide base url to keep api secured with NDK. Keep base64 encoded string inside cpp file and call that from java class and decode base64.

Include c++ (NDK) support to your project. You can include this to your new or old project.

Your cpp file name can be like (native-lib.cpp)

Search online base64 encoder and encode your base url. Now keep encoded string inside cpp file

Inside cpp file sample code is like:

#include <jni.h>
#include <string>

extern "C" JNIEXPORT jstring JNICALL
Java_com_touhidapps_MyProject_utils_MyConstants_baseUrlFromJNI(JNIEnv *env, jobject) {
    std::string mUrl = "aHR0cDovL2FwaS5leGFtcGxlLmNvbS8="; //"http://api.example.com/";
    return env->NewStringUTF(mUrl.c_str());
}

Inside MyConstants.java class: (where I kept all api urls.)

// load c++ library
static {
    System.loadLibrary("native-lib");
}

public static native String baseUrlFromJNI();

// decode base64 to a string and get normal url
public static String getSecureBaseUrl() {
    String mUrl = baseUrlFromJNI();
    try {
        String text = new String(Base64.decode(mUrl, Base64.DEFAULT), "UTF-8");
        return text;
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }
    
    mUrl = "http://demo.example.com/"; // don't change this link. This will not execute normally, if exception happens then it will return a demo url.
    return mUrl;
}

Now you can get your original url like below:

public static final String API_BASE = "" + getSecureBaseUrl();
like image 127
Touhid Avatar answered Sep 20 '22 23:09

Touhid


Your question is not ideal for the StackOverflow as the topic is too broad and primarily opinion based. However, I thought I can share some of my thoughts as an answer here.

Hiding API urls with code obfuscation is definitely a good idea and it may work in some cases as well if you want to hide those. You might consider encrypting the API url in your code as well and store the encrypted url in your SharedPreferences or in local storage which needs to be decrypted again each time when you're using your API url to call a web service.

But none of these can't ensure that your API urls are uncrackable. If someone really wants to get your API urls s/he can easily get those by tracking the network that you're using to call the web services.

So encrypting API urls and obfuscating the variable names to hide the API urls will not work in most of the cases as you expected. And yes, I don't see any security breach in getting your API urls either. Because, the API server should be designed in a way that it can block unwanted service calls an attacker is making through an API. You might consider thinking of setting up a firewall in your host machines or can setup a basic authentication protocol which will protect your data. There are a lot of ways to prevent these security breach activities. You might also consider reading this article which I found useful to get a heads-up on how you can protect your APIs to be abused.

Hope that helps.

like image 29
Reaz Murshed Avatar answered Sep 19 '22 23:09

Reaz Murshed


Hide Url in Environmental variables,BuildConfig and Android Studio

One simple way to avoid this bad practice is to store your values inside an environmental variable, so only your machine knows it, then read this values in some way and inject them in your code at build time. Let’s see how to do that using Android Studio, Gradle, and BuildConfig.

First, we need to create these environmental vars. In Linux and Mac, create or edit the file ~/.gradle/gradle.properties (pay attention to the actual Gradle User Home directory position) and add some values:

WEBServiceBaseURL="http://192.168.2.102:2323/"
WEBServiceBaseSMSURL="https://www.example.com/"

enter image description here

Second, in your module’s build.gradle file, add these lines

//Add these lines
def Base_URL = '"' + WEBServiceBaseURL + '"' ?: '"Define BASE URL"';
def SMS_Base_URL = '"' + WEBServiceBaseSMSURL + '"' ?: '"Define SMS BASE URL"';

android.buildTypes.each { type ->
    type.buildConfigField 'String', 'Base_URL', WEBServiceBaseURL
    type.buildConfigField 'String', 'SMS_Base_URL', WEBServiceBaseSMSURL
}

enter image description here

Use in Java File Like

BuildConfig.Base_URL it will return URL String

  public static Retrofit getClient() {
        if (retrofit==null) {
            retrofit =new Retrofit.Builder()
                    .baseUrl(BuildConfig.Base_URL)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
        }
        return retrofit;
    }
like image 45
Mallikarjuna Avatar answered Sep 17 '22 23:09

Mallikarjuna