I'm developing an Android app which has a service to upload images/files to a FTP server.
To make that possible, the app on the device has to log in into the FTP server before sending data.
And here comes my problem. The user does not need to / have to know about the FTP login data. Only the app itself. I have to store the login data in the Java class. But how should I secure the user and password?
I could encrypt it or obfuscate it. But I think it would be possible for a hacker to read the password at the runtime when the "setPassword(passwordString) methods is called by the JVM:
String passwordString = "myPass";
JSch ssh = new JSch();
session = ssh.getSession(SFTP_USER, HOST_ADDRESS, 22);
session.setPassword(passwordString);
So how could I store my credentials inside the APK file and secure them? I don't want anyone to get access to my FTP server.
how could I store my credentials inside the APK file and secure them? I don't want anyone to get access to my FTP server.
The stated problem cannot be solved.
It does not matter how clever your obfuscation technique is. If you hide fixed credentials in the APK file then someone who analyses your app is going to find them.
If you take only one thing from this answer, let it be that having a single, static password for your server is extremely problematic, as you'll never be able to change the password server-side, because you'd break all the apps. It will be a matter of time before your password is public knowledge and there will be nothing you can do about it.
Any reasonable approach requires separate access credentials for every individual user.
A traditional user sign-up system that involves a confirmation email is a pretty good approach. You can use something like Google+ sign-in or Facebook Connect to minimize the hassle for the end user.
If you absolutely insist on having zero user interaction, an approach that might work (somewhat) is to have the app register for Google Cloud Messaging and then send it a push notification containing access credentials, which the app will store in the KeyChain.
If you generate a unique user ID and password for every app installation, you'll be able to monitor the server and block any abusive access credentials without affecting any of the other users. If you somehow factor the code signing identity of the APK file into the process, you'll have a basic defense against people repackaging your app. This approach will not protect you against an intelligent attacker, but it might raise the bar high enough for your purposes.
Also, regardless what you do, be sure to properly verify your server's SSL certificate. If you don't, an attacker will simply run your connection through a proxy server.
Related
We have an existing web application we developed and needed to port over to an android application for people in the field. So we have a shell of an android application that just points to the URL and displays it. I want to save the user credentials so if they timeout/close application and re-click the application it will auto log them in always after the first time.
I am looking at SharedPrefrences as other threads here have done, but not sure how to capture the creds from the web input elements. Can I use SharedPrefrences to accomplish this still? If so how do I target that input?
You do NOT save the user credentials. Ever. Saving them means they can be read by malware. And no, encryption can't help as the encryption key would need to be in your app or on your filesystem.
Instead, you have your login API return a token. This token will be sent back to the server with every request (either as a parameter or a cookie). The server will then use this token to look up the user id on the server and figure out who it is. That token can be saved to SharedPreferences. (This is the simplest version, there are more advanced things you can do as well, but this is sufficient).
Why is this safer than storing the password? Because passwords can and frequently are shared between multiple apps, so losing a password can compromise multiple accounts.
BTW, this is also how webapps work. They don't send the username/password with every request, when they login a cookie is saved with a token, and its sent back with every future request.
I am building a java web application that will automatically grant users Administrative Rights to their Windows PC's when a manager approves their request.
In order to accomplish this, I am going to write a script to automatically remote into the users computer and add them to the computer's administrative group. I figured in order to do this though, I will need to have an Administrative Service Account to access all computers.
My question would be, how can I go about securely storing the Administrative Service Account information? The application will need the credentials every time it needs to go and give a user admin-rights, so how can I go about letting the application use the Service Account without human interaction? Obviously I cant just put admin credentials in a plain-text properties file. The credentials shouldn't be open for any developers to see who might go in and change the application later.
Could there be a better way to do this? Someone mentioned to me once maybe having an account in Active Directory to impersonate, but I wasn't able to follow up for more details on that.
There is one method of protecting service account passwords that is occasionally used for services that use databases is based on the concept of inversion of control.
Here the service can call a stored procedure, which has anonymous access, that prompts the database to generate, set, and send the password to the service, whose address it knows, via a separate call.
While the anon call is normally IP limited to prevent DoS attacks, it doesn't matter if some other process calls it, because the stored procedure will only send the password to the service regardless of who calls it.
Problem Description
I am writing application which must connect to the server and download some data from the server. The URL of the file witch must be downloaded is formatted as follow:
http://www.myserver.com/file.xml?username=xxx&password=xxx
Question
URL and password are not provided by the user, I simply keep them in the code and add to the URL where I need. My question is how can I keep securely password and username on the Android device.
I would advise against keeping any kind of credential (username) and authenticator (password) stored on your device, as well as transmitting them around; this is often considered a security flaw, since middle-man attacks can intercept the HTTP traffic and easily identify both.
I would recommend instead the creation a token engine that would associate temporary identifiers to users and devices. For example:
User ID 100 receives a temporary token, code A1S2D3F4 (randomly generated.)
The code is associated with the device ID AND200.
Whenever device AND200 tries to access the server, it would generate the following URL:
http://www.myserver.com/file.xml?t=A1S2D3F4
Notice that there is no content identifying the user, nor its credentials or passwords. You may check if the device generating the URL is the one the token was originally associated with. Adittional controls may be implemented to detect tokens being used out of their lifespan, and help identify malicious users.
In Android you can use Md5 encoding method for password encoding and if you need to save those user details then it store in the shared preference
Did you see if you can use Google OAuth2: http://developer.android.com/training/id-auth/authenticate.html
If not, do not send user name and password in the URL but in a HTTPS POST and the correct way is using SOAP web services.
Just as a hint there is a good talk on google io conference about security of android apps.
Link
They don't cover secure server communication explicitly but give some hints about it and provide an encryption library to simplify any encryption tasks.
My company is building a RESTful API that will return moderately sensitive information (i.e. financial information, but not account numbers). I have control over the RESTful API code/server and also am building the Android app. I've setup the API to use OAuth 2 with authorization code grant flow (with client ID and secret), and I auto-approve users without them having to approve the client since we own both client and provider. We use CAS for SSO and I am using this for the Authorization server as part of the OAuth 2 process when the user logs in to retrieve the token.
I am contemplating various ways to secure the data on the Android app. I've concluded that storing the client id and secret on the device is definitely not going to happen, but am thinking that storing the auth token might work, since it is only risk to the individual user (and really only if they happen to have a rooted phone).
Here are two options I have thought of. They both require me to have a sort of proxy server that is CAS protected, does the dance with the API server, and returns the auth token. This gets rid of the need for storing the client id and secret in the app code.
Here are what I've come up with:
1) Require the user to enter their password to access data each time they startup the App. This is definitely the most foolproof method. If this were done, I'd probably want to save the userID for convenience, but in that case couldn't use the CAS login (since it's web-based). I might be able to use a headless browser on the backend to log the user into CAS and retrieve the token based on what they enter in the Android form, but this seems hacky. Saving the userID is similar to what the Chase app does (if you happen to use this one) - it saves the userID but not your password between sessions.
2) Store the auth token on the Android device. This is a little less secure, but almost foolproof. When the user starts the app for the first time, open the webpage to the CAS login of the proxy server that returns the token (similar to https://developers.google.com/accounts/docs/MobileApps). After the user logs in and the token is returned to the app, encrypt it and store it private to the application. Also, use ProGuard to obfuscate the code, making the encryption algorithm more difficult to reverse engineer. I could also work in a token refresh, but I think this would be more of a false sense of security.
3) Don't use CAS but come up with another way to get an auth token for the service.
Any advice of how others have implemented similar scenarios (if it's been done)?
Thanks.
Well the reason why standards like OAuth are developed is that not everyone has to rethink the same attack vectors again and again. So most often it is your best choice to stick to something already available instead of baking your own thing.
The first problem with clients that are not capable of secretly storing data is that the user's data could be accessed by some attacker. As it is technically not possible to prevent this (code obfuscation won't help you against an expert attacker), the access token in OAuth 2 typically expires after short time and doesn't give an attacker full access (bounded by scope). Certainly you shouldn't store any refresh token on such a device.
The second problem is client impersonation. An attacker could steal your client secret and access your API in his own (maybe malicious) app. The user would still have to login there himself. The OAuth draft there requires the server to do everything it can to prevent this, but it is really hard.
The authorization server MUST authenticate the client whenever possible. If the authorization server cannot authenticate the client due to the client's nature, the authorization server MUST require the registration of any redirection URI used for receiving authorization responses, and SHOULD utilize other means to protect resource owners from such potentially malicious clients. For example, the authorization server can engage the resource owner to assist in identifying the client and its origin.
I think Google are the first to try another approach to authenticate a client on such devices, by checking the signature of the application, but they are not yet ready for prime time. If you want more insight into that approach, see my answer here.
For now, your best bet is to stay on the OAuth way, i.e. having the access token, client ID and client secrect (when using the authorization code grant flow) on the device, and configure your server to do additional checks. If you feel more secure obfuscating these, just do it, but always think of it as if these values were publicly available.
Here's the problem: I'm developing a desktop application to interface with a server, and the client has to log in. Something like with Skype or IM applications. I want to give the client the option of being logged in automatically, ie. no need to type in their credentials every time the applications loads.
How can I achieve this, while protecting the client's information?
Thank you, I've been pondering this problem for days now and I can't seem to come up with a solution. Any help or guidance would be gold at this stage.
If you are using a secure communication channel to the server (like using SSL, for instance) then you could send the username and a hash of the password (using a cryptographically secure hash function like SHA-512 - there's no known feasible collision or preimage attacks).
What you save locally is the username and the hash of the password. Given that the communication channel to the server is secure nobody else will see the information sent (no replay attack possible). And using a cryptographically secure hash function means that it's a one-way function, no "going back" to the original input.
Another way would be to get a token of authentication from the server upon successful login. Then the protocol could accept authentication of user combined with the token within a certain duration of time. Then you don't have to store the hash of the password locally, only the username and the token. Thus if somebody gets the token it will expire at some point. But bear in mind that the token should not be reissued using another token, only with a correct username/password combination. Additionally, the user should not be able to change/see the password if logged in using a token either. If you want to go even further then you could also restrict the token to only work from certain IP address(es).