I have a rest api which talks to Postgres, right now in the properties file of the api we are hardcoding the DB password.
so we thought when a user role is created in postgres we can use Md5 hash value(or any other encrypted value which should be decrypted by postgres) for the password...and we can use that value(hased value) in api property file instead of hardcoded one.
My question is can we use that Md5 hash value in api dev property file and when the password is sent over network and tries to connect to postgres Will it (postgres) decrypt to actual password and allows the user to connect to DB without authentication failed?????
TL;DR: you can't store the hashed password in a properties file and use it to authenticate unless the client application can recognise that it's pre-hashed and avoid the second hashing pass.
If the client library does recognise pre-hashed passwords (libpq doesn't), the hashed password can be used as a proxy for the real password. You don't need to know the real password if you know the hash. this means it's also no more secure to store the hashed password in the properties file than it is to store the original password.
The password is salted and hashed again before being sent on the wire so you can't sniff what you see on the wire and use that to authenticate.
Looking at the source code, sendAuthRequest in src/backend/libpq/auth.c:
/* Add the salt for encrypted passwords. */
if (areq == AUTH_REQ_MD5)
pq_sendbytes(&buf, port->md5Salt, 4);
port is struct Port in src/include/libpq/libpq-be.h, which has:
char md5Salt[4]; /* Password salt */
This is set by ConnCreate in src/backend/postmaster/postmaster.c:
/*
* Precompute password salt values to use for this connection. It's
* slightly annoying to do this long in advance of knowing whether we'll
* need 'em or not, but we must do the random() calls before we fork, not
* after. Else the postmaster's random sequence won't get advanced, and
* all backends would end up using the same salt...
*/
RandomSalt(port->md5Salt);
Now, passwords are verified in md5_crypt_verify in src/backend/libpq/crypt.c. There we see that passwords already stored as md5 are hashed again with the session salt:
if (isMD5(shadow_pass))
{
/* stored password already encrypted, only do salt */
if (!pg_md5_encrypt(shadow_pass + strlen("md5"),
port->md5Salt,
sizeof(port->md5Salt), crypt_pwd))
{
pfree(crypt_pwd);
return STATUS_ERROR;
}
}
Thus the hashed password sent on the wire is protected against replay attacks by the session salt.
Whether the client app can recognise a pre-hashed password and the format it expects them to be in depends on the client library.
According to pg_password_sendauth in src/interfaces/libpq/fe-auth.c the libpq front-end doesn't seem to check for pre-hashed password input. Other clients may vary.
Just to be clear - md5 hashing is not encryption.
19.3.2. Password authentication
The password-based authentication methods are md5 and password. These
methods operate similarly except for the way that the password is sent
across the connection, namely MD5-hashed and clear-text respectively.
If you are at all concerned about password "sniffing" attacks then md5
is preferred. Plain password should always be avoided if possible.
However, md5 cannot be used with the db_user_namespace feature. If the
connection is protected by SSL encryption then password can be used
safely (though SSL certificate authentication might be a better choice
if one is depending on using SSL).
PostgreSQL database passwords are separate from operating system user
passwords. The password for each database user is stored in the
pg_authid system catalog. Passwords can be managed with the SQL
commands CREATE USER and ALTER USER, e.g., CREATE USER foo WITH
PASSWORD 'secret'. If no password has been set up for a user, the
stored password is null and password authentication will always fail
for that user.
If you configure your Postgres client authentication file (pg_hba.conf) for md5 password-based authentication, you don't need to explicitly use md5() function to keep database password in your property file.
For encrypting purposes - you can configure database connection to work over SSL. Please check Secure TCP/IP Connections with SSL.
Related
I have a PostgreSQL instance running on Cloud SQL in GCP. I am connecting to it via a psql client from another machine. The connection is working fine.
However I want to know what happens when you run the following command.
Cloud SQL already uses SCRAM-SHA-256 as a password encryption mechanism by default. I have verified it. So I don't know what this command is doing.
CREATE ROLE temprole NOSUPERUSER INHERIT NOCREATEROLE NOCREATEDB LOGIN
NOREPLICATION NOBYPASSRLS PASSWORD
'SCRAM-SHA-256$4096:H45+UIZiJUcEXrB9SHlv5Q==$I0mc87UotsrnezRKv9Ijqn/zjWMGPVdy1zHPARAGfVs=:nSjwT9LGDmAsMo+GqbmC2X/9LMgowTQBjUQsl45gZzA=';
Is the string inside ' ' set as password? If not, then what is it?
Secondly, how do I login as the temprole user? Do I need to set the password for it again?
PostgreSQL does not store the clear text password, but a hash of it. The password_encryption parameter determines how the clear text password gets hashed. Now when you create or alter a role, you can not only set the clear text password (which the server will hash), but you also can set the already hashed password, like your example shows. The advantage is that you don't have to transfer the clear text password to the PostgreSQL server. (psql's command \password does it that way.)
To log into the server, you need to know the clear text password. Whoever created the hash in the statement you show will know that password, so you will have to ask there.
The system recognizes that string as already being a valid format for a scram verifier (AKA "encrypted" password) and so just stores it for future password verification work. If it had not recognized it as being a valid format, then it would have treated it as a plain password, digesting it into a verifier before storing it. It is infeasible to go from the verifier back to the password--that is one of the criteria that went into the design of the system. Whoever generated that string should know what password it represents. If they don't know (or won't tell you) then you will need to either guess and get lucky, or reset the password before you can log in as that user.
(And by the way, that password was extremely easy to guess, so if it this is a real situation you had better go change it immediately)
The CredentialRepresentation used in the Keycloak 'reset-password' REST API contains fields for hashing algorithm, hashed password, hashing iterations etc.
This implicates that I can pass through a hashed password and all its hashing specifications, instead of passing the plain-text password to the service. This is exactly what I'd like to do, because passing a plain-text password doesn't feel right.
When I try to call the service without the plain-text value however, I get a 400 error with the error message that the plain-text value is missing. Is there any way to pass just the hashed password?
Passing in a plaintext password (via HTTPS of course) allows keycloak to hash it using the hash algorithm policy of the realm.
If you want to pass in the hashed password value, iterations and algorithm then you also need to provide the hashing SPI that implements PasswordHashProviderFactory and PasswordHashProvider. And I don't think this is available via the reset-password API, but would work with the Update User API (I haven't tested this).
Rather than specifying a new password manually a better security practice is to use the PUT /admin/realms/{realm}/users/{id}/execute-actions-email admin call with "UPDATE_PASSWORD" as the required action. This causes Keycloak to send an email to the user that gives a link to set a new password directly.
I need to salt a hashed(SHA-256) password using Apache Shiro. I used the following method, but it uses plainText password as a parameter. But I need to get an alredy hashed password from the frontend and salt it and store in the server side. Otherwise if I use the following method I will have to pass the plain password all the way through frontend, which is not secure. So please suggest me a way to overcome this problem.
String hashedPassword = new Sha256Hash(plainTextPassword, salt);
You cannot salt the password after it has been hashed. Salting works by combining the salt with the plain text password, and hashing the entire thing. This is why Shiro's Sha256Hash requires you to give it the plain text password.
It is common to pass the plain text password from the front end to the service layer as long as this communication is secure (e.g. HTTPS for web UIs). The only thing you should not do is store the plain text password in a database (which a correctly configured Shiro will not do) because your database may be compromised.
When passing the plain text password from the front end to your service, it will only exist in memory for a short time before being garbage collected. To obtain the password someone would have to either break your SSL connection (in which case you are screwed anyway) or compromise your server and dump the memory (in which case you are screwed anyway).
I'm storing the user's credentials in a database with the encoded password: sha1(pw + salt) and the salt.
When I'm trying to login the user from a client app I do the same thing only with a different salt value, so I send the sha1(pw + another_salt) and another_salt for authorization.
The question is that what further modification should be done to the received encoded password to be able to check against the stored value.
If you send something from client it doesn't matter if it's hashed password or just string. And if it's content generated by client (i.e. you generate salt on client, not on server) - attacker could as well just send your string. So if it's not secured connection, then you add additional work which doesn't help.
To allow checking passwords on server with another salt, you need to store original password in clear text.
That's the whole point of storing hashes instead of passwords in database is to not allow guessing them from hash only. And if you salt them additionally, then you need to use the same salt (it's public, as it's stored in database in clear text, but it's now part of original password). What you ask is something like this:
Haw to login on user (whose password is "secure password" + "hard" => sha1("secure passwordhard")) sending something + "soft" (and then test with sha1(something + "soft")) instead.
If you really need this app to work, just send user's password in cleartext from client app, but over secured connection.
I have MD5 hashes of passwords in a database that I want to use against HTTP AUTH DIGEST. But in reading the docs, it looks like the digest hash contains a hash of the username,realm and plaintext password. Is there any way to use the MD5 hash of the password in this situation?
No. If the hash they need is generated like so:
MD5(username + realm + password)
You are out of luck.
If they are hashing the password like so:
MD5(MD5(password) + username + realm)
You'd be able to do that with just the hashed password. But it doesn't sound like that's what's going on.
No, you have to store in the tables the HA1 hash of Digest and use that for other types of auth (forms and Basic). See here: Storing password in tables and Digest authentication
No, this is not possible. The whole point of digest authentication is to avoid replay attacks, i.e. were somebody has only a hashed version (of some authentication data) rather than the real data.
Not only is it a hash of username, real, and plaintext password, but also a nonce, which will change every time. So you really need the plaintext password.
No. In digest authentication, the password is hashed with a challenge, there is no way to make it work with another hash.
Basic auth over HTTPS is more secure and it should work with your hashed password.