This question already has answers here:
Handling passwords used for auth in source code
(7 answers)
Closed 7 years ago.
I'm writing a Java class that connects to a server and reads messages in a given queue.
I would like to protect the username and password, which, right now, appear as plain text in the source code.
What I'm wondering, is, what is a good way to do this? If I encrypt the username and password in a text file, won't I need to store the key, in plain text, in any source code that accesses this file? And then anyone else who decides to use my class will be able to gain access to these fields.
There is no prompt where someone can enter the key, either, as this class will autonomously be used by the system.
EDIT: this will become a java lib file. But those can easily be decompiled and thus are basically the original class files anyway, right? And the people this is being protected from are fellow developers of other systems who will gain access to this lib file.
My End Goal: is to have the username and password strings not appear as plain text anywhere, and for them to be as difficult as possible to crack.
It is not possible to do this. Even if you encrypt the login/password and store it somewhere (may it be your class or an external file) you'd still need to save the encryption key somewhere in plain text. This is actually just marginally better than saving username/password in plain text, in fact I would avoid doing so as it creates a false sense of security.
So I'd suggest that your class takes username/password as a parameter and that the system which is using your class will have to care about protecting the credentials. It could do so by asking an end user to enter the credentials or store them into an external file which is only readable to the operating system user that your process is running as.
Edit: You might also think about using mechanisms such as OAuth which use tokens instead of passwords. Tokens have a limited life time and are tied to a certain purpose so they pose a good alternative to access credentials. So your end users could get an access token with their,say, Windows credentials, which is then used inside your class to call the protected service.
This is a classic authentication issue, except that here, Eve can wear Bob's skin like a suit. Is that stretching the metaphor? I'm not sure.
The short answer is that there is no true answer, because what you want is something that basically violates information theory, in that anything transmittable is copyable and thus anything accessible can be viewed as no-longer-unique. Even if you had a magic box, they could just yank out the magic box with some serious JVM hacking.
The long answer is that there are a few solutions that are almost pretty okay, by making it really quite darn hard. I suggest you read the article linked, acquaint yourself with the ideas behind SRP, the vulnerabilities the spec entails, and try to figure out how to get the right to use and implement it. The problem is still there though. It's that you want a system that ensures Bob can never become a flesh-chariot, or fall to the dark side.
Fundamentally, you're breaking the tenth law. I agree with Kork, there's no solution that really does what you want, because you're trying to solve a social problem with a technical feat, one that is quite nearly provably impossible.
There are a few ways of handling this problem. The challenge as you've noted is associating an account with this automated process. So, here are some of the possibilities (from least secure to more secure):
Encrypt the username and password with a calculated key.
The calculated key is based on something both the client and the server can infer (like machine name and IP address)
Associate an authentication token with the client (OAuth style).
The token is negotiated by a one time user interaction to set up the client
The negotiated token is used for all future requests
The negotiated token is only valid for that client on that machine using that user account (server uses socket info to determine the match)
Use multiple forms of authentication
OAuth style token
Calculated token based on time + secondary id (requires clients and servers to be synched to the same time server)
It is important to note that your security measures should be more restrictive than it is worth to crack. In short, if all the potential bad guy is only going to be able to get your food preferences of the day you might not need to be as vigilent as protecting something more high profile like a bank account. User names and paswords are not the only means of authentication.
It's not clear which code has to know the user name & password. Are these credentials just for the queue being read? If so, only the server code would need to know them. In that case, you could store them in a server file whose permissions allow only the server code to read them. The file permissions would then be enforced by the server operating system, which presuambly is much better at security than most programmers will ever be.
I know this question is long since abandoned, but I want to point out that of course you can do this by requiring typed credentials at runtime but only storing a hash of the password. Of course, it needs to be a really good hash. Use a standard one, don't make up your own. The whole point of a hash is that even if you plain text the hashed result, no one else will be able to come up with a string that yields that hash, even if they know how the hash is computed.
Of course users can try a brute force attack, and since they know the result they want they can run it fast, so you need to use a highly secure password.
Related
This example shows how to validate the entered data on the form:
Validating Form Input
And is it correct to do validation on the Server?
I thought the validation should be done by frontend.
Those are not mutually exclusive.
The following things are general lessons and don't just apply to Java but to all programming in general:
The server side is way more important. Never trust user input. Never. The only reason to validate in the form/frontend/client is to make it easier for the user to send you proper input.
Update:
Don't confuse "don't trust user input" with "don't trust anyone". Trusting user input is effectively putting out a wildcard check out there signed in your name.
While including code you found is just trusting exactly the code you included. Or to go with the money metaphor again: a fixed amount. Of course you should in my opinion do at least some backgroundd check. But most shady individuals bank on impulse. So they don't put much work in a clever disguise or even building rputation. So usually you can trust established libs to some degree.
You still always need to verify the data on the server-side. Because the client could be manipulated. And that does not even require the malicious intent of the user. Or even the user's knowledge at all. See the man in the middle attacks for example. A third party might manipulate the data on the way to the server.
Assume I have a single servlet in a web app, and all users need to be logged in before they can do anything. So in the get and post methods there is an if block to test if the user is logged by trying to extract a session attribute in to process request, and else to redirect to login page if not logged in.
Given this scenario, is there a way an intruder can manipulate the system to gain entry without knowing the password? Assume the password is hard-coded into the servlet. If yes, where would he start?
I would look at http://docs.oracle.com/javaee/5/tutorial/doc/bncbe.html#bncbj and the section linked from that section about specifying authentication mechanisms.
See also (on Stackoverflow) Looking for a simple, secure session design with servlets and JSP and How do servlets work? Instantiation, sessions, shared variables and multithreading
In short, you don't need to do much yourself about checking for a session attribute if you use the mechanisms described on those pages. Your login form can be used in the 'form-login' configuration requiring authentication.
The key of security is around your comment extract a session attribute -- how are you doing this? Are they sending you a query string param? Are they sending you credentials in the method headers?
To #Hogan's point, unless this is over HTTPS the answer is: "No, it is not secure. A man-in-the-middle (MITM) can get the password from your submission and simply re-use it to mask its own nefarious requests".
If the communication IS done over HTTPS, then you should be fine. Having a single hard-coded password is fine, but consider the case where the password gets compromised; now every single client/user/etc. has to change their code.
A better design is to issue clients a key they can send along with their requests that you can use to identify who they are and if a key gets compromise, re-issue a new one to that user/client/etc.
This assumes traffic is over HTTPS
If traffic is not, a lot of this breaks down and you need to look at things like HMAC's. I wrote this article on designing secure APIs -- it should give you a good introduction to how all this nightmare of security works.
If your eyes are rolling into the back of your head and you are thinking "My god, I just wanted a YES/NO", then my recommendation is:
Require all traffic to be over HTTPS
Issue individual passwords to each client so if one gets compromised, every single one isn't compromised.
That should get you pretty far down the road.
Hope that help. This topic is super hairy and I know you didn't want a history lesson and just want to solve this question and move forward. Hope I gave you enough to do that.
i intend to use JSON to implement a client server communication. My goal is for a Java-server to receive data via HTTP-Post from an Iphone-app.
I'm concerned about the fact of how I can be sure, that the data the Java-server receives only come from the Iphone-app? It may be possible that somebody else is catching the Java-Server URL and send rigged data?
Do I have a chance to recognize that? SSL encrypts transferred data only, but doesn’t solve the problem, i think.
kind regards
stormsam
You could send a token that is hardcoded into your application. Everything that comes without this valid toke should be rejected. Or you can use .htaccess and specify a user and password within your app.
You could use public key encryption, with users having their own keys and you keeping track of who are the legitimate users. This is the most reliable scheme I can think of. That, or giving each user a username and password. However, it's probably a lot more trouble than it's worth, and still doesn't protect against users that have registered with you but are still malicious.
Embedding a token in your application and then sending it with requests, as Cyprian suggests, is probably the easiest scheme and would probably work pretty well, but might be relatively easy to reverse engineer.
A somewhat better solution might be to program into your app a function that transforms any given input into an output; then, your server responds to a request by giving the app a piece of data to transform, and checks the result. A client that passes the test gets a session token which allows it to proceed. This does require an extra round-trip for authentication, though. And it's still not immune to being reverse engineered, since all the information needed to do so is stored in the app that's present on the user's machine.
Assuming you can reasonably protect your iOS app from being dissambled, you could use "signed requests" like the Facebook API (and probably others):
You'll need a shared secret on both client and server (e.g. a random string/byte array). The iOS app then hashes all request parameters plus the shared secret and appends the hash as additional request parameter, e.g. myserver.com/ws?item=123&cat=456 becomes myserver.com/ws?item=123&cat=456&hash=1ab53c7845f7a. Upon receiving a request, the server then recomputes the hash from the regular parameters and the shared secret and compares it to the value sig parameter. If both are equal, the request is considered valid (assuming integrity of your iOS app).
An advantage of this method is that it doesn't require additional round trips to fetch any one-time/CSRF-prevention tokens and does not require encrypting requests and responses (as long as you only care about the integrity of requests, not confidentiality).
You might have to take a look at this. It may give you some directions.
Suppose there is a String variable that holds a plain text password.
Is there any possibility of reading this password using a memory dump. (Suppose using cheat engine.) I am puzzled with this JVM thing. Does JVM provide some sort of protection against this. If no what are the practices that I need to use to avoid such "stealing".
A practical threat would be a Trojan; that sends the segments of the memory dump to an external party.
As already noted, yes, anybody can extract the password, in various ways. Encrypting the password won't really help -- if it's decrypted by the application, then the decrypted form will also be present at some point, plus the decryption key (or code) itself becomes a vulnerability. If it's sent somewhere else in encrypted form, then just knowing the encrypted form is enough to spoof the transaction, so that doesn't help much either.
Basically, as long as the "attacker" is also the "sender", you're eventually going to get cracked -- this is why the music and video industries can't get DRM to work.
I suggest you pick up a copy of Applied Cryptography and read the first section, "Cryptographic Protocols". Even without getting into the mathematics of the actual crypto, this will give you a good overview of all sorts of design patterns in this area.
If you keep the password in plain text in your application then someone can read it by playing with memory dumps regardless of the language or runtime you use.
To reduce the chance of this happening only keep the password in plain text when you really need to, then dump or encrypt it. One thing to note here is that JPasswordField returns a char[] rather than a string. This is because you have no control over when the String will vanish. While you also have no control over when a char[] will vanish you can fill it with junk when you are done with the password.
I say reduce as this will not stop someone. As long as the password is in memory it can be recovered, and as the decryption has to also be part of the deliverable it too could be cracked leaving your password wide open.
This has nothing to do with Java - the exact same problem (if it really is one) exists for applications written in any language:
If the executable contains a password, no matter how obfuscated or encrypted, everyone who has access to the executable can find out the password.
If an application knows a password or key temporarily (e.g. as part of an network authentication protocol) then anyone who can observe the memory the application is executing in can find out the password.
The latter is usually not considered a problem, since a modern OS does not allow arbitrary applications to observe each other's memory, and privilege escalation attacks typically rely on different vectors of attack.
If the program knows the password, anybody using the program can extract the password.
In theory you could just hook it up to the debugger... set a breakpoint...and read the string contents
This question already has answers here:
How do I securely store encryption keys in java? [closed]
(4 answers)
Closed 7 years ago.
I'm working on a software project where the application will end up being run in an untrusted environment. I have a need to perform some ancillary cryptographic signing (meaning this is not the primary means of securing data), but do not wish to leave the key in plain view as such:
private static final String privateKey = "00AABBCC....0123456789";
What method can I use to reasonably secure this? I'm aware that nothing is full proof, but this will add an extra layer in the security wall.
For clarification: I've got what is essentially a String that I don't wish to have easily pulled out in a debugger or via reflection. I'm aware that decompilation of the class file could essentially render this moot, but that's an acceptable risk.
Obviously storing the key offsite would be ideal, but I can't guarantee Internet access.
It's impossible to secure a key in an untrusted environment. You can obfuscate your code, you can create a key from arbitrary variables, whatever. Ultimately, assuming that you use the standard javax.crypto library, you have to call Mac.getInstance(), and sometime later you'll call init() on that instance. Someone who wants your key will get it.
However, I think the solution is that you tie the key to the environment, not the program. A signature is meant to say that the data originated from a known source, and has not been tampered with since that source provided it. Currently, you're trying to say "guarantee that my program produced the data." Instead, change your requirement to "guarantee that a particular user of my program produced the data." The onus is then shifted to that user to take care of his/her key.
Forget about obscuring it in the code. It will only make your software harder to read, debug and maintain. You'll also be nailed if your software has to go through a security audit.
If you can't put the key in secure storage (securely on disk, secure memory or a passphrase in someones head), don't bother with anything else.
If you're in a *nix environment, storing the key on disk with root/root 400 permissions might be "good enough".
On Windows, you could use the DPAPI to store the data in Microsofts secure memory.
You could also use a lightweight PBE to encrypt the sensitive key and have the user enter the passphrase when the application starts up.
Whose private key is that? The private key is supposed to be private, so it is wrong to distribute it.
First off - good on you for thinking about this problem!
Is it possible to instead generate a private key, communicate with your Certificate Authority and have it sign the key (and manage a CRL as well)?
As an alternative, if this is going to be running on Windows, you can use the Crypto API to securely store a private key that is marked as not-exportable. How you distribute that key securely can be another challenge though.
Can you break the private key out into two parts: store one in your program, then interactively request the second half - when your app starts ?