Sending password from client app to server - JAVA - java

I'm developing an application that requires a user to login. On the server side I'm using PBKDF2 algorithm to hash passwords, but currently I'm sending password to the server as a plain text - String. And I do not know how change it. Now it is prone is sniffing.
What should I do to make this more secure?

I've dealt with the same problem, here's how I solve it
the client hash the password (SHA3-512) and sent it to the server, the server get this and hash it again using random and changing salt function, all connection is done via SSL and with POST methods
user enter 1234 -> client send hduhd73y743fhiuj4u -> server store on the database 37y487f.f4u4uj4o3i5885 (not actual values)
by this approach, the server will never know the actual password, so a man in the middle will can't get this actual password, keep in mind it doesn't stop a man in the middle to imitate this hashed password and sent it to the server to login as the user

Related

How to verify a password without sending it unencrypted to a server

I want to build a login application, that has a client for username and password input, as well as a server, which then recieves the username and the password.
The server should then check, wheather the password it recieved matches the already stored hash, or not.
I thought it would be smart not to send the password unencrypted (just in a String) from the client to the server, so I already encrypted it on the client side with BCrypt.
But now i have two hashes on the server-side, but BCrypt only offers the methode to compare a plaintext with a hash, not a hash with a hash.
Should I now send the password in plaintext to the server or is there a way to compare two hashes?
Thanks for your help
The simplest way would be to use TLS https://en.wikipedia.org/wiki/Transport_Layer_Security
"Challenge-Response" is the term you should google for.
The Principle:
On server side you have stored a hashed (salted) password and the salt.
The client sends first the login name.
The server looks up the salt of the login in the database and sends this to the client, together with a random string (That's the Challenge).
The Client has now to calculate an encrypted password in the following way: Concatenate login password with salt and hash it. Concatenate the result with the random string from the challenge and hash it. Send the result to the server.
The server now concatenates the hashed password (stored in user database) with the random string sent together with the Challenge and calculates the hash. The result must be exactly the same as the result recieved from the client.
You can fetch hashed value from database and compare it with sent value

How to connect to PostgreSQL server using encrypted password

In usual scenarios, the connection string contains the password in plain text, but this can be captured by Wireshark, so I want to use the encrypted password in a connection string. I found the below excerpt from the Postgres documentation:
Encrypting Passwords Across A Network The MD5 authentication method
double-encrypts the password on the client before sending it to the
server. It first MD5-encrypts it based on the user name, and then
encrypts it based on a random salt sent by the server when the
database connection was made. It is this double-encrypted value that
is sent over the network to the server. Double-encryption not only
prevents the password from being discovered, but it also prevents another
connection from using the same encrypted password to connect to the
database server at a later time.
If I understood it correctly, to get the salt, I need to connect to the database, but doean't that mean that the password can be spoofed?
I tried to google around but did not found a satisfying solution. I want to understand how can I get the random salt from PostgreSQL server using java and then encrypt the plain password with it and use an encrypted password to establish a connection.
If you, user arvind, set the password to secret, the actual password is set to
'md5' || md5('secret' || 'arvind')
that is md50624d6c2e831004efb7f4173699a1775. That's what you'll find in the pg_authid system catalog.
Now the establishment of a connection works like this:
client to server: I want to connect to database mydb as user arvind.
server to client: Ok, I want MD5 authentication. Your salt is g73j.
The client has been given secret as password.
First, it uses the formula above to get the real password (first hashing).
Then, the client hashes the password a second time using
'md5' || md5('0624d6c2e831004efb7f4173699a1775' || 'g73j')
client to server: the hashed password is md573ae1f550fb4bcd28411cefb24b800bc.
The server calculates the same hash and compares the result to what it got from the client.
If that is the same, the server knows that the client must have the real password, otherwise it couldn't have calculated the correct hash.
The password itself is not transferred, so it cannot be stolen by an eavesdropper.
server to client: Ok, you're in.
The actual messages look different of course, but that's all in the documentation.

How to securely send/store password in a Spring RESTful login service

In the login service, a user is posting a json as payload to a Spring RESTful login service like below:
{
"username": "john",
"password": "doe"
}
Once the Spring RESTful service receives the call, it compares the password with the one store in the database in plain text.
I see two problems in the current implementation.
The password is sent through HTTP as a POST payload in plain text.
The correct password stored in the database is in plain text.
For issue 2, I decided to use bcrypt to encrypt the password stored in the database as mentioned in this post. Is this a good way?
For issue 1, I don't know if there is a best practice for it. Can some one share your insigts? Thanks!
Edit:
Sorry that I forgot to mention that the client and server talks through HTTPS. And the password is sent in POST payload.
In this case, the solution to issue 2 (store bcrypted correct password) in the database is okay, right?
What about in issue 1, in this case, the password can be sent in the post payload in plain text?
Use HTTPS.
Password should be in request body, so use POST.
Don't hash the password before sending.
Compare hash stored in the db with hashed received password.
There is no reason to encrypt passwords. It's a bad idea. They should be hashed and preferably salted. In case someone stoles your database, it'll be harder to compromise your users' passwords.
How to securily store passwords.
As I understood, you want to hide/secure even when saving password. So that nobody can see password from request body.
Password should be hashed when saving in database. Even anyone steel your db he won't be able to compare passwords because he will get hashed password.
Usually, we send request body in logs from where we can take body in case of any error occurs for testing. You can stop request body to send in logs file only when you are saving password only.
In this way, only user will know the password. None of the developer can get password. But this can be a problem when user will get unknown error that you will have take care separately.
I am not shure to understand your requirement.
If you want the good practice, so xenteros is right :
Use HTTPS.
Password should be in request body, so use POST.
Don't hash the password before sending.
Compare hash stored in the db with hashed received password.
There is no reason to encrypt passwords. It's a bad idea. They should
be hashed and preferably salted. In case someone stoles your database, it'll be harder to compromise your users' passwords.
If you absolutly want to use HTTP and not HTTPS you can hash your password with javascript. Don't use encryption with javascript. Someone can reuse it to decrypt the password. And in general don't use encryption to store password for security reasons.
fastest MD5 Implementation in JavaScript
you should trully prefer the solution of xenteros

Android/ASP RESTful API authentication without SSL/HTTPS

A common SO question, but no specific solid answers.
My setup:
I have a website running on Classic ASP with backed DB. Unfortunately, no SSL Certs are available
I have an Android application that will send a Google Volley to request data from the site using a bespoke but simple API
Currently:
I am still in testing, privately, so currently I just access the site as such:
On the app, the user enters a UserId and Password once.
User navigates to a Fragment which is associated with a specific ASP Page which will return some data
A Volley is sent to /mysite.com/_api/apage.asp?m=md5hashhereabcdefghijk
The server searches user records for a matching hash (built on UserID+SALT+pass). On matching record, it uses the found userid as the User's ID
apage.asp does some sql queries and returns a JSON object
app receives this JSON response and parses.
The problem:
Anyone packet sniffing, or MITM, would be able to plainly see the URLs being accessed (and server responses) and be able to replicate the query via their browser. This is what I'm trying to stop. Any SALTs or secret keys in the app would be easily seen by decompiling the APK.
Issues:
I've read all sorts of different solutions, but none of which really fit my environment. I can't use ASP session variables (RESTful being stateless), I cant use HTTPS(SSL/TLS) as there are no Certs on the Server. I can't use an App-based password as this can be decompiled and easily seen.
I appreciate that you will never get something 100% secure, but can only make people disinterested in hacking a system, or not make it worth while.
Proposed solution:
I want some feedback/thoughts on the following proposed method:
Each request will have its own handshake to authenticate the app
This will go as such:
User opens app for the first time and enters UserID/Password. This will remain with the app until it is uninstalled (or logged out), but I intend to keep the user's app logged in
User navigates in the app to a Fragment that corresponds with a specific page on the server
Volley is sent with :
UserAgent HTTP header 'some value'
generate the same authentication hash for (userid+salt+pass)
encrypt this hash with a public key
one query string /apage.asp?q=abcdefghijk.... sent to server
server decrypts using its private key
server checks this hash as I do currently.
page returns plaintext JSON values (not encrypted)
The same problem happens here whereby a MITM or sniffer could replicate the URL and get the same information back
A Second Proposed Solution:
Would it be better with every request actually starting with a whole handshake?
App sends volley to server requesting a handshake (HELO)
Server gross error check with UserAgent HTTP Header
Server logs the timestamp and IP of the request and generates a unique random code
App receives this code and builds a new hash using that unique code as a Salt
App sends second volley to /apage.asp?m=MD5(UserID+UniqueCode+Password)
Server Gross error check with originating IP, timestamp+-tolerance (30 seconds between the two requests?), UserAgent Request Header.
APage.asp uses this hash to authenticate the request, providing previous steps have successfully passed.
APage.asp returns a JSON object, as requested.
Server flags the log of originating IP/timestamp as EXPIRED, or, just remove the record.
This initial step would make it a lot harder for a sniffer or MITM to replicate the URL calls, as A) Each request would have a randomly returned code B) each code/hash combo can only be used once.
The only thing I can think of is someone decompiles the App, and sees the method of handshake, so could try to replicate this. However, the username/password hash would never match as that is the only thing they cannot get from the hash (as it is salted with the random code)
Thoughts? Could it be improved with some RSA public/private key cryptography? Could I generate my querystring apage.asp?m=abcdeghi..., Generate an MD5 Hash of that, append onto the end, then encrypt before sending?
Many thanks in advance

Securing REST Web Service using token (Java)

This question is in some way related to the below linked question. However, I need a little more clarity on some aspects and some additional information. Refer:
REST Web Service authentication token implementation
Background:
I need to implement security for a REST Web Service using token
The webservice is intended for use with Java client. Hence, form
authentication and popups for credentials are not useful.
I'm new to REST security and encryption
This is what I have understood till now:
For first request:
User establishes https connection (or container ensures https using
301)
User POSTs username and password to login service
If credentials are valid we:
Generate a random temporary token
Store the random token on server mapping it to actual username
Encrypt the token using a symmetric key only known to server
Hash the encrypted token
Send the encrypted token and the hash to the client
For subsequent requests:
Client sends this encrypted token and hash combination (using
username field of basic?)
We make sure the encrypted token is not tampered using the hash and
then decrypt it
We check the decrypted token in the session-tracking-table for a
not-expired entry and get the actual username (expiry to be managed
by code?)
If the username is found, based on allowed roles, allowed operations
are configured
More details:
Since client is a java client, the first request can be a POST
containing the credentials. However, this looks like it may expose
the credentials before the https gets established. Hence should
there be a dummy GET to a secured resource so that https is
established first?
Assuming above is required, the second request is a LoginAction POST
with credentials. This request is handled manually (not using
container's authorisation). Is this right?
The above LoginAction returns the user the combination of encrypted
token + hash
User sets it to the header that is used by BASIC authentication
mechanism (field username)
We implement a JAASRealm to decrypt and validate the token, and find
the roles allowed
The rest of authorisation process is taken care of by the container
with the WebResourceCollection defined in the web.xml
Is this the correct approach?
Why not simplify it to the following?
For first request:
User establishes HTTPS connection to server (service does not listen on any
other ports) and POSTs credentials to login service.
Server replies with HSTS header to ensure all further communication
is HTTPS.
If credentials are valid we:
Generate a random temporary token which is securely generated using a CSPRNG. Make this long enough to be secure (128 bit).
Store the random token on server mapping it to actual username.
Send the random token to the client
For subsequent requests:
Client sends token in a custom HTTP header over HTTPS.
Token is located in the DB and mapped to the username. If found access is configured based on allowed roles and allowed operations.
If not found user is considered unauthenticated and will have to authenticate with the login service again to get a new token.
On the server side the token will be stored with an expiry date. On each access to the service this date will be updated to create a sliding expiration. There will be a job that will run every few minutes to delete expired tokens and the query that checks the token for a valid session will only check those that have not deemed to have expired (to prevent permanent sessions if the scheduled job fails for any reason).
There is no need to hash and encrypt the tokens within the database - it adds no real value apart from a touch of security through obscurity. You could just hash though. This would prevent an attacker that managed to get at the session data table from hijacking existing user sessions.
The approach looks ok. Not very secure.
Let me highlight some of the attacks possible with the request.
Man-In-the-middle attack in a POST request, the user can tamper with the request and server does not have any way to ensure the data is not tampered.
Replay attack: In this, the attacker does not tamper with the request. The attacker taps the request and sends it to the server multiple times in a short duration, though it is a valid request, the server processes the request multiple times, which is not needed
Please read about Nonce.
In the first step, the user sends his credentials i.e username and password to the login service and if you have a web based application that also uses the same password it might be dangerous. If in case password in compromised, API and web everything is exposed, please use a different PIN for API access. Also, ensure decrypted token as specified by you, expires after a certain time.
Ensure the service (application server) tomcat. jboss never returns a server page in case of internal error, this gives the attacker extra information of the server where the app is deployed.
-- MODIFIED BASED ON SECOND POST --
Yes your correct if your using mutual SSL, but in case its a one way access you don't have the client certificates. It would be good if you just double ensured everything in the request, just like signed (signature) SOAP, one of the strong data transfer mechanism. But replay attack is a possibility with HTTPS, just handle that. Rest use tokens encryption is good. And why not ask the client to decrypt the token with the password and return the output of the decryption by this you can validate the output, if it is present in your database ? This approach the user does not send the password over the wire even if it is HTTPS ?

Categories