How to make ldap evaluate clear text password vs DES stored password - hash

I use openldap slapd 2.4.40 and postgresql9.2.23 as back-sql on CentoS 6.9
user and password for LDAP uid and userPassword are stored in postgresql by DES encoding.
Original clear text is JacicFk5
DES encoded/encrypted text is IfjFxsltK/MPE which stored in DB.
I can see the user information as the result of ldapseach by stored password.
ldapsearch -x -b "dc=example,dc=com" -D uid="HDZZZ0R0N,ou=people,dc=example,dc=com" -w IfjFxsltK/MPE '(&(uid= HDZZZ0R0N)(objectClass=*))'
# extended LDIF
#
# LDAPv3
# base <dc=example,dc=com> with scope subtree
# filter: (&(uid= HDZZZ0R0N)(objectClass=*))
# requesting: ALL
#
# user01, people, example.com
dn: uid= HDZZZ0R0N,ou=people,dc=example,dc=com
objectClass: inetOrgPerson
cn:: W+aOkl3lia/nlKPnianjg6Hjg7Pjg4bjg4rjg7PjgrnvvIgzNu+8iVNURw==
sn:: W+aOkl3lia/nlKPnianjg6Hjg7Pjg4bjg4rjg7PjgrnvvIgzNu+8iVNURw==
uid: HDZZZ0R0N
userPassword:: SWZqRnhzbHRLL01QRQ==
However, I can’t do ldapsearch by original clear text password
ldapsearch -x -b "dc=example,dc=com" -D uid="HDZZZ0R0N,ou=people,dc=example,dc=com" -w JacicFk5 '(&(uid= HDZZZ0R0N)(objectClass=*))'
ldap_bind: Invalid credentials (49)
Does anyone tell me how to make ldapsearch to resolve given password by clear text and stored password by DES encoding?
I’d like to know is how to make plaintext JacicFk5 from ldapseach command-line to hash IfjFxsltK/MPE and make it match against IfjFxsltK/MPE in DB as userPassowrd.
Is there suitable directive for ldap.conf or slapd.conf?
I've checked followings .
echo "SWZqRnhzbHRLL01QRQ==" |perl -MMIME::Base64 -ne 'print decode_base64($_) . "\n"'
it returns IfjFxsltK/MPE
perl -e 'print("userPassword: {crypt}".crypt("JacicFk5","If")."\n");'
it returns userPassword: {crypt}IfjFxsltK/MPE
One more info.
my ldapseach can solve password text for users stored in AD server via ownclod.

What you want/need to have is a LDAP simple authentication. Please first note that it is unsecure to store passwords in plaintext!
First you need to test what auth mechanisms you have supported/allowed.
An example:
tukanos#localhost:~# ldapsearch -H ldap:// -x -LLL -s base -b "" supportedSASLMechanisms
dn:
supportedSASLMechanisms: DIGEST-MD5
supportedSASLMechanisms: CRAM-MD5
supportedSASLMechanisms: NTLM
Now you want to change the onfiguration via ldapmodify. You prepare a LDIF file (LDIF stands for LDAP Data Interchangable Format) with configuration.
Prepare your configuration file you can name it olcSaslSecProps.ldif:
dn: cn=config
replace: olcSaslSecProps
olcSaslSecProps: noanonymous,minssf=0,passcred
What the properties mean:
noanonymous ... no anonymous connection allowed
minssf=0 ... that defines your effective encryption strength (0 ... no encryption)
passcred ... that would allow password to work as for credentials
To quote the OpenLDAP security considerations
Security Strength Factors
The server uses Security Strength Factors (SSF) to indicate the
relative strength of protection. A SSF of zero (0) indicates no
protections are in place. A SSF of one (1) indicates integrity
protection are in place. A SSF greater than one (>1) roughly
correlates to the effective encryption key length. For example, DES is
56, 3DES is 112, and AES 128, 192, or 256.
A number of administrative controls rely on SSFs associated with TLS
and SASL protection in place on an LDAP session.
security controls disallow operations when appropriate protections are
not in place. For example:
security ssf=1 update_ssf=112
requires integrity protection for all operations and encryption
protection, 3DES equivalent, for update operations (e.g. add, delete,
modify, etc.). See slapd.conf(5) for details.
Now to apply the LDIF file:
ldapmodify -Y EXTERNAL -H ldapi:// -f ./olcSaslSecProps.ldif
Now to restart the slapd daemon:
systemctl restart slapd
If you check now your configuration you should get LOGIN and PLAIN:
ldapsearch -H ldap:// -x -LLL -s base -b "" supportedSASLMechanisms
dn:
supportedSASLMechanisms: PLAIN
supportedSASLMechanisms: LOGIN
Now your search should work with plain test password:
ldapsearch -x -b "dc=example,dc=com" -D uid="HDZZZ0R0N,ou=people,dc=example,dc=com" -w JacicFk5 '(&(uid= HDZZZ0R0N)(objectClass=*))'

Related

want to run command from outside Postgresql and want to store password in encrypted format?

I want to write a script that will check whether replication is on or not, so I wrote the command in a script:- PGPASSWORD='********' psql -U user_name -p 54032 -c "select * from pg_stat_replication" -d postgres
but I want to encrypt the password for security purposes so I did MD5 encryption and put the hash of it.
PGPASSWORD='a67a4e657061eac2036a88ec523dbbbb' psql -U user_name -p 54032 -c "select * from pg_stat_replication" -d postgres
It's not working Please help me.
There is no way to avoid having a clear text password somewhere, either on the command line or in the environment or in a password file.
If you want to authenticate without a clear text password anywhere, use certificate authentication with a client certificate.

Postgres: MD5 Password / Plain password

I'm trying to understand how role passwords are supposed to operate in Postgres.
https://www.postgresql.org/docs/current/static/sql-createrole.html says for ENCRYPTED / UNENCRYPTED
If the presented password string is already in MD5-encrypted format, then it is stored encrypted as-is,
So my unencrypted password is: MyPassword .
The MD5 hash of "MyPassword" is 48503dfd58720bd5ff35c102065a52d7
If I do
-- See https://www.postgresql.org/docs/9.6/static/sql-alterrole.html
ALTER ROLE "MeOhMy"
LOGIN
PASSWORD '48503dfd58720bd5ff35c102065a52d7'
;
And then attempt to use "MyPassword" when doing
sudo -u postgres psql meohmy -h 127.0.0.1 -d meohmy_development
I, of course, first get prompted for my sudo password and then I get prompted by Postgres "Password for meohmy"
If I enter MyPassword I get
FATAL: password authentication failed for user "ralph#dos32.com"
If I enter, instead, 48503dfd58720bd5ff35c102065a52d7 then I can sign in.
What am I not understanding?
To create an md5 password for PostgreSQL, the formula is:
"md5" + md5(password + username)
Here are 3 ways you can create one, where the username is "admin" and the password is "password123"...
Linux:
# echo -n "md5"; echo -n "password123admin" | md5sum | awk '{print $1}'
md53f84a3c26198d9b94054ca7a3839366d
NOTE: The -n is critical to avoid including the newline character in your hash!
MacOS:
➜ echo -n "md5"; md5 -qs "password123admin"
md53f84a3c26198d9b94054ca7a3839366d
Python 2:
>>> import hashlib
>>> print("md5" + hashlib.md5("password123" + "admin").hexdigest())
md53f84a3c26198d9b94054ca7a3839366d
Python 3:
as above, but use binary strings
print("md5" + hashlib.md5(b"password123" + b"admin").hexdigest())
Postgresql hashed passwords have md5 prefix:
md548503dfd58720bd5ff35c102065a52d7
Using Postgres11 on GCP Cloud SQL. Gitlab version gitlab-ee 13.3.4 Omnibus install
# gitlab-ctl pg-password-md5 gitlab_user
Enter password:
Confirm password:
and
# echo -n <password for gitlab_user>gitlab_user | md5sum
are equivalent.
Note: My db user is gitlab_user
The answer provided by #zerkms is partially correct. It led me to the right answer.
The answer provided in Generating postgresql user password is the answer that works for me.

Unicode Base64 values in a LDAP Filter

I'm trying to find Active Directory users who are:
memberOf::Q049RG9tw6RuZW4tQWRtaW5zLENOPVVzZXJzLERDPXh4eCxEQz1pbnRlcm4=
(this base64 stands for CN=Domänen-Admins,CN=Users,DC=xxx,DC=intern)
Searching for it directly (via API or ldapsearch) yields no result (since it's a unicode DN):
ldapsearch -h ... -D Administrator#xxx.intern -x -w '...' -b dc=xxx,dc=intern '(memberof=CN=Domänen-Benutzer,CN=Users,DC=xxx,DC=intern)'
Following filters didn't work either:
(memberof=Q049RG9tw6RuZW4tQWRtaW5zLENOPVVzZXJzLERDPXh4eCxEQz1pbnRlcm4=)
(memberof=:Q049RG9tw6RuZW4tQWRtaW5zLENOPVVzZXJzLERDPXh4eCxEQz1pbnRlcm4=)
(memberof=::Q049RG9tw6RuZW4tQWRtaW5zLENOPVVzZXJzLERDPXh4eCxEQz1pbnRlcm4=)
I can't find any documentation except for RFC specifying base64 encoding in LDIF files.
UPDATE the above ldapsearch commands are for convenience only, it doesn't work with LDAP API either - using:
ldap.search_s('dc=xxx,dc=intern', ldap.SCOPE_SUBTREE, filter, ['cn'])
with filters:
filter='(memberof=CN=Domänen-Benutzer,CN=Users,DC=xxx,DC=intern)'.encode('utf-8') # raw UTF
filter='(memberof=CN=Domänen-Benutzer,CN=Users,DC=xxx,DC=intern)'.encode('cp1252') # raw 1252
filter=b'(memberof=CN=Dom\\e4nen-Benutzer,CN=Users,DC=xxx,DC=intern)' # hex
filter=b'(memberof=CN=Dom\\xe4nen-Benutzer,CN=Users,DC=xxx,DC=intern)' # python repr
I've also confirmed with Wireshark that the filter is indeed transmitted in UTF8
The attribute type cn has a Directory String syntax according to the standard. Directory Strings are encoded using UTF-8. Saying that searching via API yields no results incorrect. You are just using the incorrect encoding. The ldapsearch tool (assuming you are using OpenLDAP) may not support searching with accented characters.
The ldapsearch utility shipped with the UnboundID Data Store handles this pretty well. Here is the LDIF that I used for testing:
dn:: Q049RG9tw4PCpG5lbi1BZG1pbnMsZGM9ZXhhbXBsZSxkYz1jb20=
objectclass: organizationalPerson
sn: person
dn: cn=mygroup,dc=example,dc=com
objectclass: groupofnames
member:: Q049RG9tw4PCpG5lbi1BZG1pbnMsZGM9ZXhhbXBsZSxkYz1jb20=
Here is my command line test:
$ ldapsearch -b "dc=example,dc=com" "member=CN=Domänen-Admins,dc=example,dc=com"
dn: cn=mygroup,dc=example,dc=com
objectClass: top
objectClass: groupofnames
cn: mygroup
member:: Q049RG9tw4PCpG5lbi1BZG1pbnMsZGM9ZXhhbXBsZSxkYz1jb20=
Also, you may want to read the Directory String syntax from RFC 4517.
UPDATE
I managed to make this working with Active Directory (Windows Server 2012 R2, DataCenter edition) and using the ldapsearch utility shipped with the UnboundID Data Store. This is what I see:
$ ldapsearch --trustAll -Z -h <hostname> -p 636 -D "cn=administrator,cn=users,dc=dom-ad2,dc=local" -w <password> -b "cn=test,dc=dom-ad2,dc=local" "member=CN=Domänen-Benutzer,CN=test,DC=dom-ad2,DC=local"
dn: CN=mygroup,CN=test,DC=dom-ad2,DC=local
objectClass: top
objectClass: group
cn: mygroup
member:: Q049RG9tw4PCpG5lbi1CZW51dHplcixDTj10ZXN0LERDPWRvbS1hZDIsREM9bG9jYWw=
member: CN=Administrator,CN=Users,DC=dom-ad2,DC=local
distinguishedName: CN=mygroup,CN=test,DC=dom-ad2,DC=local
instanceType: 4
whenCreated: 20160514104531.0Z
You can also use the LDAPSearch example class from the UnboundID LDAP SDK (jar download link) to accomplish this. Here is the equivalent command-line I used with the LDAP SDK:
$ java -cp unboundid-ldapsdk-3.1.1.jar com.unboundid.ldap.sdk.examples.LDAPSearch --trustAll -Z -h <host> -p 636 -D "cn=administrator,cn=users,dc=dom-ad2,dc=local" -w <password> -b "cn=test,dc=dom-ad2,dc=local" "member=CN=Domänen-Benutzer,CN=test,DC=dom-ad2,DC=local"
It turned out that it's only impossible to fetch members for built-in AD groups (i.e. (isCriticalSystemObject=TRUE)). memberOf queries for user-created groups work just fine, independently from encoding used. No hex encoding was necessary.
Why are you trying to use the base64 encoded value? You must base64 decode the value before using it in a LDAP filter. It either needs to be the string representation name of the value or a hex escaped version of the string value when used in a LDAP filter.
Edit: After translating the group names a bit from your question it became more apparent to me what your issue actually is. The default "Domain Users" group is actually a primary group for a user. It will not show up in the memberOf list (hence the empty results on a search). To check if a user is a member of "Domain Users" you must inspect the primaryGroupId value for a user. In 99% of all cases this will always be the default "Domain Users" group.

What is a non-invasive OS-independent test to verify the PostgreSQL system user password is NULL?

This seems like a deceptively easy question to answer, but may not be.
Let's look at a different (easier) case. How can we verify that the system user password is 'SOMEPASS', assuming that the system user is 'postgres'.
su - postgres; env PGPASSWORD=SOMEPASS psql -h localhost -c 'select' > /dev/null
if [ $? -ne 0 ]; then
echo "Invalid password."
fi
The -h on psql forces the connection to use TCP instead of a domain socket, which forces a password-based login. Otherwise the default pg_hba.conf is configured to allow passwordless connections from the system user over domain socket.
What is an analogous version of the test above but which can verify that the system user password is NULL? The test should return 0 if the system user has a NULL password, and 1 if not.
Additionally, since I am hoping to convert this into generic code for use in puppet across Windows, Solaris, and Linux OS's, the solution should (can not?) make use of helper command-line utilities like sed, awk, perl, etc.
To turn any psql query into a return value in the shell you have a couple of options:
Have psql emit a single boolean and test that with grep -q;
Have psql emit zero rows or non-zero rows; or
Have your query fail with an ERROR in one case, and test psql's return value
Of these I tend to prefer the first, and that's pretty easy with your case:
if psql -At -c "select CASE WHEN rolpassword IS NULL THEN 'FAIL' ELSE 'OK' END from pg_authid WHERE rolname = 'postgres';" | grep -q FAIL; then
...

How to execute PostgreSQL script-file from command line without userinput / password

During the installation of my app, I want to create a PostgreSQL-Database and some tables and functions.
For that purpose I use PSQL.EXE that ships with PostgreSQL. I have 2 scripts. The first one creates the database and a corresponding user that has rights to execute scripts on that database. I want to execute the second script as this just created user. Unfortunately I can't find a way to pass the password for that user as a command line argument. Omitting the password leads to a stop of execution and a prompt for the user to enter the password, which I would like to avoid - since this is executed during installtion of my app.
Is there any way to pass the password as argument or is there any other command line tool I could use?
To explain the environment a bit further. I use WiX 3.5 setup as a "MSI-Builder".
You can either use a pgpass file as dbenhur answerd, or you can set the environment variable PGPASSWORD before calling psql:
SET PGPASSWORD=my_very_secret_password
psql somedb someuser
All supported environment variables are documented in the manual: http://www.postgresql.org/docs/current/static/libpq-envars.html
You can't supply password via cmdline arg (and don't want to as that's poor security practice).
You can provide a .pgpass file to support automatic script authentication. Here's the docs.
Better still, if you have access to create the db role then you already have all the access you need without having to carefully log in with a password. Have the second script operate under the same user as the first but include the following line to switch user:
set role my_new_user;
Where my_new_user is the name of the role you want to run it as.
If you only divided the scripts because of the different logins then with this they can go in the same file and just switch role mid way through.
Note:
On the off chance that you are not creating the DB and new role as a super user this may be a little more complex. If this is the case you will need to create the new role with:
create role my_new_role ... ADMIN my_role;
Where my_new_role is the role you're creating and my_role is your current user. Then when you're finished simply:
revoke my_new_role from my_role;
For completion, you can also use URI (doc link)
List dbs
psql "postgresql://username:password#localhost/postgres" -l
I also crafted this command to have only names (please tell me if you know a better way):
psql "postgresql://username:password#localhost/postgres" -l | awk -F '|' '{print $1}'| sed -e '/^\s*$/ d' -e '1,3d'|sed '$d'|awk '{print $1}'
You can also use unix socket to connect:
# ss -x -a |grep postgres|awk '{print $5}'
/var/run/postgresql/.s.PGSQL.5432
Note that the parent directory of the socket is used:
# sudo -u postgres psql -d "postgresql:///postgres?host=/var/run/postgresql/" -l
You can only do this if you have this line in your pg_hba.conf:
local all postgres ident
"ident" uses unix user for authent
dump a db
Here I added a different port number
pg_dump -Fc "postgresql://username:password#localhost:9001/${db}" > "backup_${db}.pgdump"
With dumpall you need a super user or role (with CREATE ROLE ... SUPERUSER). And it must have access to all DB. By default postgres can.
but in my case I couldn't use pg_dumpall with postgres because his password was removed by devs.
So I used:
sudo -u postgres pg_dumpall -d "postgresql:///?host=/var/run/postgresql/" > all.dump
tested version
# cat /opt/postgresql/PG_VERSION
9.6
hth