I am using this library :
https://github.com/scottyab/safetynethelper
I have read the documentation on Android Deveoloper site and in the repository.
Everything works fine ,but something is not clear to me.
It is indicated that it is more secure to obtain the nonce from the server rather then creating it on the app it self.and why is it better to Pass the response from SafetyNet API to the server
Most commonly the SafetyNet Attestation API is used to decide whether you trust the device and app that is communicating with your server.
As such, you don't really want to be checking the JWS response within your Android app, otherwise an attacker could simply modify your app to remove any verification logic you have put in place. This is why it is better to pass the response to the server, and make any decisions there (you trust your server).
On your server you can verify the response and, if everything looks good, allow whatever action you are trying to protect - maybe permitting a sign-in, or the download of certain data.
Why is a nonce supplied from your server more secure? A nonce that is generated in your app (ie. essentially random and unknown to you) can be changed freely by an attacker. It is better if you control the nonce! This way when you are verifying the JWS response on your server you can check the nonce is correct.
A good approach for generating a nonce on your server may be to hash a session ID, or a combination of the user ID and timestamp.
Related
I'm developing an android app and I want to restrict access to my API to my website and mobile application. I'm not interested in having the user login into my app, rather, registering the client.
I've refrenced these resources for this task:
how to make google endpoints inaccessible from the web?
How do I protect my API that was built using Google Cloud Endpoints?
https://cloud.google.com/appengine/docs/java/endpoints/add-authorization-backend
How do I restrict Google App Engine Endpoints API access to only my Android applications?
Here is what I did thus far:
Generated an android and web client api key from the google cloud console. It looks something like this: ALzfShCF_mD_IVlVVVf2783TG9FG8x7u0s-ZFQE (not real key)
Made a constants class, added these to my API declaration for clientIds
clientId{android_key,web_key} && audience{web_key,android_audiance}
Added a User user param to each method
Rebuilt project, deployed.
All of these resources seemed helpful, especially the documentation. However, I didn't notice any difference. I expected to see, after I followed the documentation and redeploy my backend, both my website and app fail to call my endpoint functions. However, they both worked flawlessly.
Would following these posts or documentation prove my case, or is there something else I must do? I also dont want unauthorized access to my API explorer as well!
Any help would be greatly appreciated!
Edit:
I'm using the wrong keys, I was using the API key instead of the CLIENT Id. Once I updated that I saw that my API requests are failing because the user param is null. Now my question is, how can I not pass a non-null user object without getting the user to login?
I tried making a GoogleAccountCredintal and passing it to my ApiBuilder in my Async task, but its always null.
GoogleAccountCredential credential = GoogleAccountCredential.usingAudience(context,APIClientKeys.ANDROID_CLIENT_ID);
MyApi.Builder builder = new MyApi.Builder(AndroidHttp.newCompatibleTransport(),
new AndroidJsonFactory(), credential) ...
A very wise web developer once said
"Never Trust the Client".
No matter how sophisticated mechanism you come up with to secure your application, all it takes is a Network Inspector (Like one you can find in your web-browser) and a code inspector (which you can also find in your web-browser). Now some might suggest to obtrucify your client (that is mangling code enough that someone can not just see it). However, if someone really wants to de-obtrucify your application. With significant effort they will and once they have successfully reverse engineered your client, they can write their own malicious client to abuse your endpoints.
So what can you realistically do?
Rate limit usage on some endpoint using some rate-limiting technology (like Limitd) by an IP or other parameters and then start blacklisting IPs if they abuse your service this will make it really hard to abuse your apis.
Force users to login.
How about this:
Setup a secret key on your server and your app. Let’s say it’s SECRETKEY123. When making a request to your API, send an extra parameter called auth. In it pass the md5 (or any other, say bcrypt) hash of your parameters and the secret key. (Note: The secret key should not be posted)
So something like auth = md5(param1 + param2 + SECRETKEY123);
Then on your server perform the same hash using the secret key already stored on the server. Compare the two hashes – I.e the one you submitted and the one you generatd on the server. If they match allow access – otherwise restrict access.
I am building a mobile app that communicates to a server. I would like the communication to be as secure as possible, but I have no experience in this field.
Upon app first launch, app submits phone number to server, gets a 6-digits code via SMS and then submit those 6-digits to server. Assuming the 6-digits code is valid, server will then return the mobile app an API secret (long unique string) to be saved on the mobile app. I am doing this, so when the user re-installs the app on a another device, the server will revoke access to the old mobile device (i.e: the API secret will no longer be valid).
Where do I go from here? My intention is using the API secret to secure all future communications from mobile app to server (i.e: all communication following signup). I took the idea from different APIs I worked with previously where I had seen that each API user is given an API key/secret. On those API's I noticed that the API secret is used in the following manner, but I have no idea if that's what I need.
params = {"method": api_function_name,
"order": 'DESC'
"key": CLIENT_SPECIFIC_API_KEY,
}
params = urllib.urlencode(params)
H = hmac.new(CLIENT_SPECIFIC_API_SECRET, digestmod=hashlib.sha512)
H.update(params)
sign = H.hexdigest()
Can anyone help me figure out what I need to do from here?
what I need to do from here
For good security, one of the first things you should do is to figure out whom or what the communication should be secure against.
One thing to do for this particular app is to design a way for the server to determine which device should replace which device in the "re-install" case.
The code in the question looks like a decent way to authenticate the client over a confidential channel between the client and the server. The client sends (params, sign) to the server, right?
From your first post I can see you are calculating a hash of the CLIENT_SPECIFIC_API_SECRET. I assume this is so that you can store a hashed form rather than the raw CLIENT_SPECIFIC_API_SECRET? This is commonly done on the server side to prevent password's being exposed in the case of a hack. This is particularly important for service providers for which a single hack could lead to the exposure of a huge number of client passwords.
In terms of using the CLIENT_SPECIFIC_API_SECRET for authentication of the client instance there is definitely prior art. A good basic example of this would be the digest authentication mechanism specified in the HTTP Authentication RFC 2617 - look specifically at the section on Digest Authentication. Note that this RFC shows Digest Authentication for HTTP but the basic principles can be applied outside HTTP. For example, Digest Authentication is also used in IMS SIP.
To authenticate a device you could have a Digest Authentication step every time a device opens a connection to the server. Of course the connection should be encrypted (TCP with SSL) as well to prevent man in the middle attacks.
This is a messaging app. It has no login (username or password). This means it has to send messsages to a server, and the server must trust it is coming from the phone number it says it is coming from.
How do you do that?
1) Send token to phones with text message service
Unfortunately, you're not going to be able to guarantee with 100% certainty that the phone number reported to the server is the one it's coming from. The reason is that the client code can be reverse engineered, regardless of what you do. There are some things you can do however to make it a little more difficult, although it is important that you don't depend on this to be 100% secure. If you need 100% assurance, then you need to have the app authenticate to the server through traditional means.
The way that I would do this, is embed a token in each copy of the client that gets released, such that each client has a different token. The token should have extremely large entropy (such as a 128-bit or greater integer), and you should keep a list on the server of tokens you've issued with the phone number of the device, so you can check them for validity. Require re-installs of the app to use a new token, and blacklist the previous token so it can no longer be used. The UID can be used, but be advised that it can easily be spoofed by a rooted device.
Submit this token to the server each time and ensure that the phone number the app claims to have never changes. To make it harder for reverse engineers to find the token in your code, you can xor it one or more times with additional tokens, and you can also lay out a bunch of fake tokens throughout the code that are blacklisted on the server.
You can also encrypt it with a secret key that is retrieved from the server so that the embedded token must be retrieved by an RE during live interaction with the server. Again this in no way guarantees that the token won't be found and changed/stolen, but it raises the bar for potential reverse engineers.
To prevent someone from sniffing the wire and obtaining and/or tampering with your token, or from using a proxy like Burp Suite to capture/tamper with it, you should use an encrypted HMAC. If you've never used an HMAC before, be advised that unless you encrypt it, it only provides authentication and integrity, not confidentiality.
EDIT:
Should also add, that you should run your code through an Obfuscator before you deploy it. This won't obfuscate the token, but it will obfuscate the decompiled code so it looks like gibberish to the RE. This forces the RE to use the byte code/assembly code from your app, which is much, much harder.
Associate each phone number with a unique device identifier
Get the udid and send it with each request
Create a signature that follow each request to your server. The signature shoukd be something like: secret key1+msg+phone number+udid+secret key2, then SHA1 the string and attach to th request.
On server calculate the signature and compare to original that followed the message. If they match, ok, else don't send it.
Use strong keys, and use two, to make brue force extraction, almost impossible.
I have a android application which sends updates about the purchases for the server. What I do now is, I encrypt the purchases and some other shared details into MD5, using the same key generator in server side and Android Client side. But if some one decode the APK file that person can easily make the calls by generating keys. What is the best way to prevent these kinds of attacks?
Use HTTPS to communicate with you server in order to protect data in transit. Do not try to invent a secure protocol. If you want to restrict access to server API's use some form of authentication: username and password (over HTTPS) or better yet some sort of authentication token (OAuth, etc.). If you store keys and/or passwords inside the APK, anyone can extract them by decompiling the APK. If you want to protect against this, you need to use token authentication where tokens expire and can be invalidated if compromised.
Best Solution is that you implement some web service which will return you a access key(will change every time you want to get access key) which you will use every time to communicate with your server in POST method. This is most secure method and being used by every good sites like Facebook, Twitter etc.
Sine my problem was basically about updating the server with in-app purchases, I ended up doing Public/Private key authentication at the server end. Android suggest to verify receipts on client, but we just forward the receipts to server and did validation there using the public key.
I am trying to add a REST interface to Django for a mobile client. The mobile client will use JSON over HTTPS. I have not been able to find the "best" way to accomplish this for mobile devices. From searching around, it seems that #2 is more favorable to #1:
Use HTTP authentication and establish a cookie based session. All transactions will occur over HTTP and JSON messages will only contain commands or data.
Pass the username and password (encrypted) within each JSON msg for all transactions and do not rely on cookie-based sessions.
I would recommend sending the username / password first with a login call. The JSON will pass back an authToken or accessToken which the mobile device will send back for all subsequent calls. You will then check to make sure the authToken is valid. This is the approach many API's take. In their database they will bind the API key to the users account that they logged in with.
OAuth is overkill unless you want to make these services available to other developers (which they would access on behalf of your end users). Better to go with option 2, but I would recommend using Digest Authentication as opposed to Password Authentication. Combine that with SSL and you are definitely good to go.
Number 2 is preferable, and rather than roll your own, I would recommend using OAuth authentication if possible. Both client and server libraries are readily available for use on most platforms now. Check http://oauth.net for details.
So long as you're using actual encryption and not base64 or some homegrown obfuscation algorithm, #2 is fine and dandy. You might also want to consider the route many companies take, which is binding an API key to a username.