How to avoid interceptions of the connection to the server in Android? - android

In my Android app, I am getting the user information from server using a HttpURLConnection. Each user has a unique Id which may be accessed publicly.
Problem is if a third party, say, UserB has the Id of UserA, then they can abuse it by setting it inside my app (we know that how easy is to decompile Android APKs) then calling the server using my app and getting the output from server (including sensitive private information of UserA).
How can I prevent this from happening? What security tricks do you recommend?
Side note 1: I already have used encryption/decryption methods. But they are not going to stop UserB from abuse because when the UserB sets the Id of UserA, the app calls the server and then they have access to final decrypted output.
Side note 2: I have thought about Phone Number verification, but it is not operational for my app currently.
Side note 3: I cannot restrict the user to a specific device because they have to be able to use it on their different devices.
Side note 4: Libraries like Firebase, Gcm and the like are so secure. It would be a good idea to find out what ways they use to keep hackers from accessing another user's information!
Side note 5: Thanks to Gabor, I noticed that I had to mention that I cannot use a login interface unfortunately. If I could, that would be for sure a primary choice. It's the nature of my app and I can't change it!

That's actually a very good question and a holy grail of all security officers :)
What's I learned is that whatever you do, as long as you cannot protect the physical device against unauthorized access, there's always a risk. The problem is:
* On the one hand, you wish that the app will keep and store an information which authorizes the owner of the device
* On the other hand, you have to protect this information on the device, but because your app needs to be able for accessing it, also the accessing algorithm must be available on the device.
So I would say, there's no "clear" way. What you can do, is to make the cost of obtaining information (in your case) unprofitable.
You said that the user ID is "publicly available". That's ok, but it means that the UserID is not "secure information". I would say, that your users need to be authorized first, and then the server should generate a UNIQUE token, that will be used in replacement of UserID when calling next requests.
You can implement it in many ways, but I will recommend one way, that should be not complex for your users:
Let's assume that all your users are registered. During the registration, each user needs to provide his email, UserID (could be generated) and password. Note that registration could be done in the mobile app or on the web portal.
When the app is going to start for the first time, a user should provide hist UserID (or simply email) and password.
With the first call to the server, the userID and password should be sent to the server, and server generated a Token (unique for every first login so even if the user will use two or more mobile devices each one will use the new token).
With every next call to the server, only the token needs to be provided to authenticate the user/device.
Where to store that token? No matter. I would say in any private storage of the app. You can and should, of course, encrypt it, obfuscate a so one, but whatever you do, if one has access to the device, he can always copy it.
You will say now, that it's not 100% secure. That's right. So I would say if it could not be secure, we should minimize the risk of abuse.
There are also some ways how one can do that.
First of all, in case of abuse, your users should be informed about it. Having a token algorithm, the user can take and action, and simply disable stolen tokens.
In case if the device has been for instance stolen, your users can/should be able to disable tokens (devices) on the web portal (or in another instance of the app) after signing in using email/password authentication.
The only one problem is how to detect that the mobile device has been "cloned". In that case, the user is physically not aware of the abuse.
My guess here is to implement the following algorithm (auth pooling):
1. Let the mobile app send the "keep alive" message with the Token to the server at the certain time when the app is inactive (let's say user xyz#gmail.com should send keepalive always at 10:00, 12:00 and so one).
2. Let the app send the keep alive, with some frequency when the user is logged in (app is active).
3. These frequencies/schedules must be know for the server and app (and could be even public).
In case if the server detects the same token in keep alive nearly the same time, the user should be informed (by the different channel, it could email) about possible abuse.
* NOTE: this is only an idea, I never did that, and I'm also wondering what other things about it, but in my opinion, this is quite simple to implement, and gives you a good change to minimize the risk.

When a user starts using the app, they should log in using their credentials (eg. username and password). From the app's perspective, this is a roundtrip to the server to obtain a token. The token is then stored in the appropriate credential store for the platform you are using, and can be used to impersonate the user in further requests (the token can be sent with requests as for example an Authorize header, practically a bearer token). It also should have an expiry time, after which the user has to provide his credentials again.
Such a token can be a plain jwt you create, or it may come from something like a full oauth2 / openid connect implementation. If you decide to implement it yourself, be careful, it is not straightforward to get it right.
This way, you have proper authentication in place, you know who your users are in subsequent requests, and this way you can enforce access control rules on the server.

Related

Minimising the value of database

I am thinking of creating a app that will contain personal user information for a memberships scheme, the basics, name, dob, a user ID and a valid from / expiry date.
I want to reduce the instance of hacking and having the data stolen. So I was thinking that I add the user information in the database, when the user logs in for the first time, the app connects to the data and downloads the users information to their phone and all personal data is removed from the database, the ID is used for the app to display valid from/expiry dates etc.
I am unfamiliar with iOS/Android app development. Can this work, do I store in a separate file and download to a user area in the app package or do I download a database to the phone, and what about when I need to update the app?
This is not good system design
In reality if a system is designed properly, with a security focussed mindset and deployed in a properly designed environment, this should not be a concern that warrants causing end users such potential issues.
In fact, user data would be considerably more secure on a properly designed, controlled system than on a user's device; How many people do you know that don't have a passcode on their phone, or have it set as their date of birth? I know a whole bunch of these types of people (and by logical extension, the passcodes to their phones).
You also mentioned that the data will be deleted from the database. How exactly will it end up back in that database in the event of a support ticket? If it's by emailing it back to you, that would be a bigger security risk because plain text email is not secure.
What you should do instead
Build a web service to sit between your app and the database
Pass the login details from the application to the web service and perform authentication/authorisation there. If successful, pass back an access token of some description. Save this access token to the database with an expire-time value.
Have the app call various api endpoints, passing the access token as part of the Authorization header (so it doesn't get cached or end up in the logs of proxies and web servers etc). If the token is valid, fulfil the request and return the requested data back to the app from the web service
On log-out/quit, have the app remove any sensitive information from the device memory if security is such a concern.
Additional Notes
As with any such design, you should ensure that all communications are done over a secure channel.
Ensure passwords are stored in a secure format and not transmitted or stored in plaintext anywhere. Use a secure channel for passwords in transit, Bcrypt is good for storing passwords or consider implementing Secure Remote Password Protocol.
Ensure that direct access to the database is only allowed from your web service and not the wider internet
Ensure that your webservice sanitises input, escapes output and is not vulnerable to SQL Injection attacks.
The benefits of this approach are obvious:
Your app data remains secure so long as the environment is secured using the correct tools. If you choose the right hosting provider they'll also be able to provide help and support securing your web server and database.
In the event of a user changing their device, logging out or whatever else they'll be able to log back in as they see fit. This will meet the already well established expectations of users and reduce potential support calls.
If you decide to expand on the features of your app later on, you can add new tables to the database, new endpoints to the webservice and new functionality within the app to consume said endpoints.
Many users tend to have a bad habit of reusing passwords; With a properly designed system you're able to audit login attempts, lock users out for a period of time after so many incorrect password attempts, force password expiry or resets and allow for self servicing of password changes to the whims of your more security conscious users.

Secure an API for mobile apps call

I've been doing a lot of search about secure my api for mobile apps for Android or IOS.
Almost all examples tell user provides an user id and password somehow in a exchange for a token.
But how to prevent someone else to consume my api without my consent?
Face the following scenario:
I expose an API,
I develop, then, an app for android to consume it,
I develop, then, an app for IOS to consume it.
Other developer performs a rev. engineer in my app, creates his own app and starts to consume it without authorization.
How to prevent that?
Short answer: you can't.
Little longer answer: If you know what you are doing you can always reverse engineer a given application and use its api. You can only make it more difficult and time consuming, using authentification via tokens and device ids or usernames is a good first step. Apart from that: why would you want to close your api to outsiders? If your server code is written well there is nothing to worry about.
You can maybe secure your API on a legal basis and sue developers who use it, but that is a completely different topic.
Some clarification regarding securing the API and securing content via the API. Assume you create a server where you can send user/password and receive a token if that combination was correct. For the account-page you send said token over and the server verifys that that token is valid and returns your account page. You secured the actual content of the API. That is obviously very possible and almost a must-have unless you have no user-specific data. But still everybody can send the exact same initial request from their custom app, sending a user/pass and again receive a token, etc. You cannot really prevent the request itself or even determine that it was not send by some service not authorized by you. You can send some hashes along the request to add some security by obfuscation, but since your app has to compute them, so can the reverse engineer.
Yes, login api are open but they return a token only on successful match in your database. You should focus more on security of your data than unknown hits at your api.
SignUp API can be used for creating a user, and login for returning token of that user. Only if malicious developer has credentials, then he can access tokens and auth APIs. There is also something about DDOS attacks so you can maybe write logic to temporarily block IPs where hits frequency is high.
You can also store device ID of signing user, which seems idle for your scenario. Entertain hits from that deviceID only. Similarly, user can add more devices with their credentials. I think even Google does that (generate alerts if user creds are signed in from new device and add the device to list if user confirms). Hope this helps.

Storing API key on mobile device

I've read many, if not all, answers to previously asked questions about the same topic, but questions themselves are not exactly about my case.
I have an OAuth 2.0 server running. It has an endpoint that provides access tokens to users. Programs and websites requesting the access token may or may not be owned by me, in other words, I may add a tool for website users and locate it on the same or neighboring website and my users may create an app and with their API key request access to user's data. Now I am developing the app that will operate user's data.
I realize that storing the API secret on the device is not a good solution. I have read about creating an end-point to which I make request directly from the app and then the endpoint makes API requests, but the endpoint will have to exist on the same host and probably server as OAuth server.
Is there a way to authorize mobile application to access user data when I am in controll of the application and the OAuth server? Should I create a separate end-point? Should I pass it device ID and/or any other information?
P.S. I know that plain old authorization would work here, but then what if some user wants to create his own mobile extension (not allowed currently for security reasons)? Also, current system has a button that is recognized by many people and they know what exactly will happen after clicking it. With the app, it may be an issue when the user sees a login dialog instead of the "Login with *" button. I really hope there is a clever solution to this.
Your concern is spot on. Your API Secret should not be stored on the device.
However, I am not sure why you would be concerned to build a separate endpoint, since OAuth 2 has a authorization flow for these use cases.
https://www.rfc-editor.org/rfc/rfc6749#section-9
In your use case, I'd suggest using the implicit grant flow to fetch the access token and store that on the local device. There would be no refresh tokens and the access_token can have an expiration date. Of course, the token on the device can be compromised, but the damage will be limited to a particular user and not the entire application.
If this level of security is not acceptable, then you can look at splitting up your API Secret in different parts of your app and then assemble it at run time in your app.

Verify Android user is human (without a CAPTCHA)

I have an app where users can add ratings, and I don't want them to have to register to do it, but I also don't want it to be easy for bots to game the ratings.
Is there a way I can be reasonably (doesn't have to be 100%, but I don't want to use reactive heuristic methods) sure that my users are human? Without requiring any kind of CAPTCHA / sign-in / other action. Normally I would say that this is impossible, but since my app runs on Android I think we can do better than nothing.
Gmail address.
My first thought was to get their gmail address from AccountManager, but I can't see a way to verify that they own that email address - i.e. a bot could just send made-up emails to my server, so I don't think this can work (and I don't want to make them authenticate my app using their google account; they are unlikely to do this).
GCM
My next thought was to use Google's Cloud Messaging thing. I can get a cloud messaging ID from the device, send it to my server, send a random cloud message from the server back to the device, and send that message back to the server. I think this at least verifies that they do have an Android device with a gmail account, which is good enough.
SMS
Of course I could send them an SMS, but that costs money and to be seamless means that I need to have permission to read their messages, which I'd really like to avoid (especially as the rating is an optional feature).
Android Licensing Server
Maybe it is possible to use the Licensing Verification Library to get a signed assurance from Google that the user downloaded it from the market, but due to the nature of my app I can't put it in the market.
Device ID, EMEI, phone number, etc.
Of course I can't use these. Bots could just make them up!
So GCM looks like the best (and only) option. Can anyone think of anything else?
Show some popups randomly and place their close buttons at different place, so user has to close them.
OR
Using drag drop API ask user to drag and drop button into some area on screen and then submit rating. You can randomize placing of button.
There could be multiplaces where you can drag button but you can instruct user to put in the right one.
As you control both sides of the communication, you could do something like this:
Flow
App: Request one-time secret token from server.
Server: Create one-time secret token and a tracking-id and send both to the App, while keeping track of the secret token by using the tracking-id.
App: encrypt the voting using the one-time secret token (see below about encryption)
App: send encrypted message and tracking-id to server.
Server: Find secret token using tracking-id, make sure it hasn't been already used and decrypt the voting using the secret-token.
Encryption
You can use any symetrical encryption technology. A very simple example would be to XOR your message (i.e. voting) with the secret-token on the App-side. On Server-side XOR-ing again with the same secret-token gives the plain message again.
This method is safe as long as your method of encryption is not known to the attacker. If it is known of course he can just simulate the requests the App does, but it would hold true for every method, so you probably should use something better than simple XOR-ing.

How to create a password-less login for mobile app

I'm intested in building some kind of password-less login between a mobile app and an API (assuming I can control both). The motivation is that having to login is very annoying for users and has security risks (eg. users will reuse existing passwords) and I want the users to be able to get started with the app immediately.
I'm wondering if there are some techniques that could work. For instance:
Generate and random login/password on the mobile device and store the password in the keychain.
Signup with the API using this login/password combination. This returns a token.
Token is used in subsequent calls
The drawbacks are:
Login/passwords can be lost if user deletes app (this could maybe be mitigated by using iCloud to store the login - but that would be bad for the password?)
Password is stored on the device (however it's in the keychain)
So my questions: is something like this feasible and secure enough? Are there known techniques to do that?
Here's what we did:
Basically, the idea is pretty similar to the "forgot password" most services offer:
Ask the user for an email
Send an email with an activation link. The email contains a deeplink with a one time token, something like myapp://login?token=......
User opens the email on the device where the app is installed this is crucial for the deep link to work, but it what happens on 99% of the cases anyway. The user clicks the button with the deeplink
User is redirected back to the app, you extract the token from the deeplink on the app and send it to the server api to authenticate. After authentication is done, create a session for the user so they won't need to authenticate again
The good:
More secure: Users don’t have to think of new passwords (which are usually too simple) and there is no risk of users reusing passwords. For us as developers, it offers a solution that has only one (and simple!) path of authentication that is easier to understand and hence to protect. Also, we don’t have to touch any user passwords / hashed passwords.
Smoother onboarding flow to the user: if you pre-enter the email in the input field the login flow can be as short as 2 button clicks and they're in. (unless you wanna take their name / other details as well but that requires additional input fields in traditional login as well)
The less good :)
Users might not be used to this flow very well and might wonder why they don't need a password. I would add a small link explaining "why we don't need passwords?"
If app is deleted or the user logs out, they will need to use their email to log in again. This is less of a problem for mobile apps where users don't occasionally log out and in etc
I've already implemented this flow into our app, you can read a more in depth explanation here:
http://www.drzon.net/passwordless-login-in-mobile-apps/
Some more considerations:
To make it more secure, make the token available to use one time only and also put an expiration on it (like an hour). You can also tie the token to the specific device by sending the server a unique device id of some kind along with the email address. This way the user can't simply forward the email to another person and he will open it instead
About the deep link - I found that some email providers block the use of links with custom url schemes like app://. The way to overcome this is by making the link point to your server instead and redirect there to the actual deep link
https://myserver.com/login?token=... ---> myapp://login?token=...
Mozilla wrote about it as well here
This is very open ended, but generally: don't reinvent the wheel, use a standard solution such as OAuth and/or OpenID Connect (uses OAuth). This has the drawback that users might required to login via a WebView or similar to get a token, but you won't have to store the passwords.
Things to consider:
you can't really generate a random password, since the server needs to know it as well
Android doesn't have a public keychain-like API, so you have to take care of securing the password yourself.
As for 'secure enough', pretty much everyone uses OAuth nowadays(Twitter, Facebook, etc), so it's at least proven. The actual security will depend on your particular implementation.

Categories

Resources