5

Hello I am working on android application in which i required to execute few https web services so all my webservice URL and Web API KEY are in the code plus ip address of the server. When anyone do reverse engineering of my app then that guy can get my web service URL as well as API KEY then can simply hit it using rest client.

How to secure such that any attacker can't get anyhow my WEB API KEY which I defined in the strings.xml

<string name="WEB_API_KEY">XXXXXXXXXXXXXXXXXXXXXXXXXXX</string>

Thanks in advance.

N Sharma
  • 33,489
  • 95
  • 256
  • 444
  • 1
    It is fundamentally impossible to distinguish between requests from your app and an attacker. – SLaks Oct 19 '14 at 19:28
  • @SLaks that we all know. we can't distinguish but there should be a way to make system secure – N Sharma Oct 19 '14 at 19:30
  • 2
    That is fundamentally impossible. – SLaks Oct 19 '14 at 19:32
  • so every system is unsecure according to you ?? can't we secure WEB API KEY which is in strings.xml ? – N Sharma Oct 19 '14 at 19:40
  • 2
    If your app can read the string, an attacker who can run the app can also read the string. If your app can make a request, an attacker can make an identical request, and you can't tell the difference. What exactly do you expect to do? – SLaks Oct 19 '14 at 19:44
  • @SLaks This is why i have WeB API KEY & attacker won't have that WEB API KEY. Main Question Any way to secure Web API KEY so that attackers can't get from my source code if they do reverse engineering – N Sharma Oct 19 '14 at 19:46
  • 3
    Your API KEY will be in your code. So everyone can decompile your app and read it. You cannot secure it as your app need to access it. – Dimitris Fousteris Oct 19 '14 at 19:49
  • @DimitrisFousteris yes exactly even ssl approach can fail here – N Sharma Oct 19 '14 at 19:51
  • 1
    Yes. It is completely impossible to do this. Instead, put the key in your server, and validate requests to make sure they don't do things you don't want. – SLaks Oct 19 '14 at 19:52
  • You cannot make any published shared secret secret. But you can still somehow control the TTL of it, rotate it, and fast operations to void a key when it is is being abused. – Dennis C May 17 '18 at 15:21

5 Answers5

3

I have faced the same issue. First to ensure that this is the app that I have created is calling the webservice only. even if they get the key by reveres engineering. secondly the valid user is calling the application. The following checks are done in the server.

1)Verify that it’s really signed by Google.

2)Verify that it’s really meant for you.

you need to use Google developer console https://console.developers.google.com/project?authuser=0 create two Client Ids (One for the server and other for the android application.) under the Menu API & auth. To create client ID for the android application you can use keytool keytool -exportcert -alias <your-key-name> -keystore <your-key-store-file> -v -list

I have followed the steps from here

Serverside php sample is given below

function checkSession($token){
$result = Array();
if(isset($_SERVER['HTTPS']))
{
    if ($_SERVER["HTTPS"] == "on") 
    {
        $secure_connection = true;
    }
}
if($secure_connection){
try {
$client = new Google_Client();
$client->setClientId(CLIENT_ID);
$client->setClientSecret(CLIENT_SECRET);
$ticket = $client->verifyIdToken($token);
$validtocken = false;
  if($ticket){
   $token_data = $ticket->getAttributes();
   if($token_data ["payload"]["aud"]==CLIENT_ID &&
      $token_data ["payload"]["azp"]==ANDROID_ID){
       $validtocken = true;
       $result["Email"]=$token_data ["payload"]["email"];
      }
   else  
   { 
    log_message(serialize($token_data)); 
   }
  }
  } catch (Exception $e) {
  $result["Details"]=$e->getMessage();
  }
}
kirant400
  • 327
  • 3
  • 14
  • will it work only with AppEngine or with any server? – Mehul Joisar Dec 22 '14 at 04:42
  • The code is in php and it works in any server that support php. This utility functions available for other programming languages like ruby and java too. Google itself provide those. – kirant400 Dec 23 '14 at 03:21
1

the best way is receive the web api key from server at first time app open.

in this case app store the key on internal storage not in apk.

Elango
  • 412
  • 4
  • 24
  • 3
    Hackers can hit that url to get the web api key then access other URLs – N Sharma Dec 17 '14 at 05:55
  • you can add imei parameter for access service. and you have to generate the web api key for every imei no. And also check both(imei and web api key) at other url access. – Elango Dec 17 '14 at 06:23
  • this is an prototype, so you have to encrypt all parameter details before send request – Elango Dec 17 '14 at 06:25
0

You can not rely on something hardcoded in your code to identify if a request is coming from your app or a rogue client. What you must do is make the webservice require some sort of authentication before it accepts any request. An example would be requiring username/password pair, or making the webservice accept/reject clients based on their SSL certificate. That way only authorized users would use the webservice.

Dimitris Fousteris
  • 1,091
  • 8
  • 12
  • But if i use ssl certificate as well and reject/accept on basis of client then attacker can create another android app & they can hit the Web API from that also. Again it will be unsecure way – N Sharma Oct 19 '14 at 19:47
  • The SSL certificate will be given only to authorized clients, and it wont be hardcoded in the app. This is applicable to the scenario where only authorized users would use the service – Dimitris Fousteris Oct 19 '14 at 19:49
  • But if i copy that ssl certificate to my project then they can get that certificate file from it when they do reverse engineering – N Sharma Oct 19 '14 at 19:50
  • Maybe i am not making myself clear. The SSL certificates won't be distirbuted inside the app. That would be stupid. They will be distirbuted only to authorized users. For example one would download it to his mobile phone after granted access – Dimitris Fousteris Oct 19 '14 at 19:53
  • ah ok i got but nobody want to download & add that certificate that will increase the complexity. user won't do that means user won't use app – N Sharma Oct 19 '14 at 20:04
  • what do you mean of "after granted access " ?? – N Sharma Oct 19 '14 at 20:05
  • see users here saying all copy bks file to sd card http://stackoverflow.com/a/9582529/1741671 then it is very easy for atackers to get that file after reverse engineering then hit api – N Sharma Oct 19 '14 at 20:12
0

Storing the API_KEY in the app is not a good idea, it can be easily reverse engineered, especially if it was in XML resources. You have to put it on the server side and then make calls to the services.

App --- Call ---> [Service1.php which has API_KEY ] --- Call --> Payment Service.

App <--- Response --- [Service1.php] <--- Response ---- Payment Service.

It's like having middle-ware layers in between the payment service and your app. Like this the hacker can't get his hands on the key.

0

Securing an app with only hardcoded credentials is as allready mentioned not safe.

I should suggest you use some login like structure. Where you first of all ask for username/password.

Then you build upp a API call using a signature you compile at run time. By doing this you never need to send the users password over the open web.

You can achieve this by do a call like this:

APIkey = "a specicic APIkey"; //To identify the specifik app "not secret"
Username = "usersname"; //To identify witch user trying to make the call
Request = "you needed request data"; //Your actual requst parameters.
Timestamp = "Current_timestamp";  //Current timestamp user to get unique signatures for every call
Signature = sha256_hash(APIkey + Username + Request + Timestamp + Password); //Signature using the users password(Secret).

You can then validate the call by recompiling the signature serverside aswell using the stored password in your database. If the signatures match, the call should be authentic. You should also set a timelimit and denying every call that is to old.

Note: you would probably need to adapt and change it to working code in your language, but you get the idea.

Philip G
  • 4,098
  • 2
  • 22
  • 41