PAM "pam_unix.so" authentication sometimes fails - java

I'm having some trouble with PAM. I have a tomcat webapp that uses PAM to authenticate. During install we make a symbolic link in /etc/pam.d to the /etc/pam.d/sshd file. This has always worked.
Recently I added a way for users to authenticate each request (rather than using a JSESSIONID cookie). This was added because we need to batch load some data into a monitoring application periodically and using Basic Auth was easy.
If I curl my webservice repeatedly (like 10 times a second), then every once in a while PAM will fail. This happens around once every 500 times, though my client claims that it happens once every couple of times (note that they are running remotely, though i don't see why that matters).
I have replaced my sym-linked pam config with a minimal config of:
#%PAM-1.0
auth sufficient pam_unix.so audit
auth required pam_deny.so
I have also added this to my /etc/syslog.conf
*.debug /var/log/debug.log
The only applicable log messages can be found in the debug.log:
Mar 12 09:49:32 arques java: pam_unix(foo:auth): unable to obtain a password
Mar 12 09:49:32 arques java: pam_unix(foo:auth): auth could not identify password for [root]
How do I debug this further? I have tried:
Using different hosts. One which is a brand new install
I've turned off the nscd service

I'm having a similar problem with a Java application that uses PAM for authentication. For now, I'm guessing the problem is within the distributed Java PAM binding implementation on CentOS 6.4. I no longer have access to that system (but I'm still trying to solve this problem) so I cannot provide specifics such as JDK version, etc.
My solution ultimately was to harshly kludge PAM:
#%PAM-
auth sufficient pam_debug.so
To make this more explicit, you could use "pam_permit.so" instead.
That's it, basically. Any valid user would then be authenticated, with or without password. Ugh.
I'm continuing to research better answers.

Related

LDAP Entry Poisoning Fixed in jdk-8u191?

Fortify has reported an LDAP Entry Poisoning vulnerability in one of my Spring applications. You can get additional information on this vulnerability from the following links:
https://www.youtube.com/watch?v=Y8a5nB-vy78&feature=youtu.be&t=2111
https://www.blackhat.com/docs/us-16/materials/us-16-Munoz-A-Journey-From-JNDI-LDAP-Manipulation-To-RCE.pdf
https://www.blackhat.com/docs/us-16/materials/us-16-Munoz-A-Journey-From-JNDI-LDAP-Manipulation-To-RCE-wp.pdf
I decided to try and prove for myself if this was still a vulnerability. I did this by using Spring Tool Suite:
file -> new -> import spring getting started content
searched for ldap
and imported the Authenticating Ldap -> complete code set
https://spring.io/guides/gs/authenticating-ldap/
I then added the following lines to the included test-server.ldif file to the entry for bob as well as the entry for developers:
javaFactory: PayloadObject
objectClass: javaNamingReference
javaCodebase: http://127.0.0.1:9999/
javaClassName: PayloadObject
In order to run this, I needed to add the following line to application.properties:
spring.ldap.embedded.validation.enabled=false
I started up Wireshark and ran the Spring sample app, and sure enough, when I logged in with bob, I got a hit in Wireshark on port 9999.
When I asked a co-worker to test the same thing, he was unable to reproduce. After some research, we discovered that he had a newer jdk than I, and after I updated my jdk, I, too, was unable to reproduce the issue.
We narrowed it down to jdk-8u191 was the version that introduced "the fix", but I can't find anything that explains why or how it was fixed in the java release notes.
My question is - is LDAP Entry Poisoning now a false/positive if we're running jdk-8u191 or newer? Or is there some configuration option that can be set to override this "fix"?
8u191 closed a remote class loading vulnerability in LDAP, though research is ongoing. Whenever you are turning a stream of bytes into an Object in Java, you want to think about class loading (what 8u191 addressed), but also insecure deserialization.
When CVEs are addressed, they are not typically in the release notes.
As for whether or not the alert from Fortify is a false positive, I think it is more important to assess the risk relative to your application.
To leverage this vulnerability, for example, the attacker would at least need direct access to your LDAP instance (see pg 31), which likely indicates a larger security issue. 8u191 and after, the attacker would additionally need to find a class in your classpath that is vulnerable to insecure deserialization to reproduce what the BH talk demonstrates.

Java GSSAPI Credentials with Active Directory

Apologies in advance - I'm pretty new to Kerberos/GSSAPI, so I've probably got something really simple stuffed up.
I'm trying to run what is essentially the sample client code from the GSSAPI tutorials.
I have two VMs set up. One is named KDC-TESTING. It's a Domain Controller with Active Directory installed and a user named "testuser". It's running on the KDC.COM domain.
The second is running an IIS server named IIS-WEB that runs on the KDC.COM domain.
I also have my computer (windows 7). It's on a different domain, but it's currently using the domain controller's IP as its DNS. I'm trying to run the Basic GSSAPI client from eclipse on here.
When you go to iis-web.kdc.com (from either the domain controller vm or my computer), you're prompted for a username/password combo. You can log in using testuser (with its password, obviously).
When I run the client program, I get the following error:
org.ietf.jgss.GSSException, major code: 13, minor code: 0
major string: Invalid credentials
minor string: SubjectCredFinder: no JAAS Subject
It's thrown from this line:
GSSContext context = manager.createContext(clientName, krb5Mechanism, null, GSSContext.DEFAULT_LIFETIME);
Since it says the credentials are invalid, I added in the following (and tried creating the context with creds rather than null):
GSSCredential creds = manager.createCredential(clientName, GSSContext.DEFAULT_LIFETIME, krb5Mechanism, GSSCredential.INITIATE_ONLY);
That changed literally nothing (except for the stack trace).
Looking at this question and a bunch of docs/blogs, I think the problem is somewhat related to configuration, but I'm not sure what configuration needs to be done exactly.
I've got a krb5.conf file set up, and I'm running it with the command line arguments shown here.
I haven't done any Kerberos setup on my computer, but I've an SPN to testuser and maybe set up a keytab on the VMs (but I'm almost certain that that's not the cause).
EDIT/UPDATE:
I ran it from a new VM that was both on the KDC.COM domain and used KDC-TESTING.KDC.COM as its DNS and it seemed to work as expected (there was another error, this time with authenticating - progress! I think I know what's wrong with this one though).
I ran it as a JAR (as opposed to from inside eclipse) and, as expected, I was prompted in the command window for a username and password. Could this have been an issue (as in, is eclipse not able to take input, so it just crashes or something)?
I also hadn't been seeing any of the security debugging logs in eclipse (I'd been using -Djava.security.debug=all), but on the the VM it was all there (there was a lot of it).

Java application authentication using Active Directory

I am working on a third party Java application for which I need to authenticate its users using Active Directory.
This application is hosted on RHEL 6.5, and uses LDAP to authenticate with Windows Active Directory. The AD server has been set up, and is working fine with an earlier version of the application (which was configured to enable the integration).
For the newer version, the vendor has laid out some steps to modify/configure the application files to connect with the AD server, and which are expected to help us authenticate. After making required changes, we are only able to open the UI page, which does not accept the (correct) credentials, the page that helps us with application configuration is not accessible at all.
I am a newbie to this area, and as far as my understanding goes, I would just need to make the suggested changes, and not follow the steps presented in this document, as those are for authenticating the Linux users, and NOT the application's users. Could someone also please confirm the same.
Any help/guidance in this issue would be greatly appreciated.
Thanks very much!
Edit:
I am unable to provide details of the files as it is confidential property, but the changes have to be made in the server property files.
Kindly request more details if necessary, I will try my best to provide them as I can't disclose everything, citing confidentiality reasons.
Thank you very much.
Edit 2:
Have added more details with this edit, which are given below:
The application has one of its component as CAS, which is currently configured to use database as its authentication handler. When we enter the credentials - username: abcd, password: samplepswd, we are able to login successfully.
As the business requirement is that of authentication with Active Directory using LDAP, we have to modify the CAS properties file. As per instructions from the product vendor, we have changed the following properties to use ldap -
authenticationHandler.type=ldap
ldapSSLConfig.enabled=false
ldapContextSource.url=ldap://sample.ADserver.example.net:389
ldapContextSource.userDn=abcd
ldapContextSource.password=samplepswd
ldapAuthenticationHandler.filter=uid=%u
ldapAuthenticationHandler.searchBase=OU=DEF,OU=PQR,OU=XYZ,DC=ADserver,DC=example,DC=net
We also need to make changes in the casAuthConfig xml file for the following properties (as anonymous search is not supported):
1. anonymousReadOnly, value is set to false
2. java.naming.security.authentication, value is set to simple
There is provision to use ldap over SSL as well, but currently we are not using that.
However, if we do use SSL, additional changes have to be made to the following properties:
ldapSSLConfig.enabled=true
ldapSSLConfig.trustStorePath=/home/dir1/subdir1/subdir2/keystorename.keystore
ldapSSLConfig.trustStoreType=jceks
These are the only configuration changes done on our (client) side; and in fact the only changes done. Nothing has been added/modified on the server (AD server), except another user, but that has no impact on the existing setup.
After restarting cas to reflect the changes, we encounter the error of bad credentials, although the values entered are correct:
2015-09-16 12:12:30,558 INFO [com.emeter.cas.authentication.support.DelegatingAuthenticationHandler] - Authenticating credential using handler
com.emeter.cas.adaptors.ldappwd.BindLdapAuthenticationHandler
2015-09-16 12:12:30,558 DEBUG [com.emeter.cas.authentication.support.DelegatingAuthenticationHandler] - credentials.getUsername() = abcd
2015-09-16 12:12:30,672 INFO [com.emeter.cas.adaptors.ldappwd.BindLdapAuthenticationHandler] - Search for cn=abcd returned 0 results.
2015-09-16 12:12:30,672 INFO [org.jasig.cas.authentication.AuthenticationManagerImpl] - AuthenticationHandler:
com.emeter.cas.authentication.support.DelegatingAuthenticationHandler failed to authenticate the user which provided the following credentials:
[username: abcd]
2015-09-16 12:12:30,676 ERROR [org.jasig.cas.integration.restlet.TicketResource] - error.authentication.credentials.bad
org.jasig.cas.ticket.TicketCreationException: error.authentication.credentials.bad
at org.jasig.cas.CentralAuthenticationServiceImpl.createTicketGrantingTicket_aroundBody10(CentralAuthenticationServiceImpl.java:423)
Can anybody please help with this issue? Or possibly point in the right direction?
Any help would be greatly appreciated.
Thank you.

SSO confusion - incorporating SSL difficulties

I have a WebSphere on AIX server,
and a simple java client on windows XP (connects to server over http).
I would like to incorporate SSL for client autherization. Mainly, I have a smartcard reader.
The only problem is - the smartcard is used already once to access Windows and we would like to save the trouble for the client to re-enter PIN during client application startup.
I started reading a lot about SSO - which I was assured can help my problem. This led me to reading about WebSphere's support for SPENGO - in their redbooks. Problem is it involves a lot of support from the Active directory people - and they are not keen on helping - and also I fear they're envolvement can slow down the incorporation.
So now I am looking into OpenSSO, WAFFLE, JOSSO and other frameworks that may help me.
But wait - this all seems like a major overspec. All I wanted was to save my client a second prompt to the smartcard.
What I really want is a method - one of the following:
-A Windows XP and above setting that will enable me to retreive the certificate inside the smart card (along with some access to encryption/decryption capabilities to authenticate the certificate).
-Some sort of access to windows to allow me these options
-Perheps, Some sort of java pkcs#11 method that will enable me to get access to the same connection as Windows.
-Is such an ability vendor specific?
Is this even possible? The wikipedia Single sign-on entry http://en.wikipedia.org/wiki/Single_sign-on speaks of SSO with smartcards - but so far I haven't been able to find any way on how to do it. All I know is that my smartcard is prompts a second time if I try to use it with the regular pkcs#11 code.
To sum up:
1. Is there a windows/verndor specific/java to enable me to SSO using the smartcard.
2. If not or if not recommended, what other SSO solution should I use given that I don't want to depend on the Active directory people?
3. In the worst case, where SSO can only be efficiently acheived with Kerberose and ActiveDirectory - what implementation could be less demanding on the ActiveDirectory side?
Thank you.

Is there a way in Java or a command-line util to obtain a Kerberos ticket for a service using the native SSPI API?

I want to implement Single Sign On with Kerberos in Java and have successfully managed to create a ticket for the Service using the ticket from the Windows logon. Unfortunately, I can only create that ticket when the Registry Key "allowtgtsessionkey" is enabled. I am receiving an exception with the message "Identifier doesn't match expected value (906)" as soon as I disable it. The registry key is documented on http://java.sun.com/j2se/1.5.0/docs/guide/security/jgss/tutorials/Troubleshooting.html and http://support.microsoft.com/kb/308339.
Unfortunately I do not have access to the registry on the computers where my application will be used, so I am looking for a way to do this without having to modify it. When I do Single Sign On over SPNEGO in Internet Explorer or Mozilla Firefox, they create a Service ticket in my ticket cache, so there definitely has to be a way to do this without setting the registry key. Does anyone have an idea how to do this in Java?
Thanks for your help,
memminger
Update: I am giving up on this issue. The Windows registry key prevents the access to the Ticket (more exactly: the Subject) inside the Ticket cache. Java on Windows uses its own GSSAPI implementation, and I suppose that needs access to the Ticket to create a Service Ticket. The SSPI Windows API though has full access to the Ticket cache and can thus create Service tickets. This API is used by the web browsers, but it is not used by Java (according to http://java.sun.com/developer/technicalArticles/J2SE/security/#3). When I disable SSPI in Firefox after having accessed a web page once (so a service ticket has been created), I can still access the page, so maybe a command-line util would be sufficient that creates a service ticket using the SPPI API.
For us, this means now that we can either abandon Single Sign On (which is unacceptable for us) or that we do the authentification on the client side of our application (because we can only read out the username but not verify the ticket on the server), which is a major security risk. Another example of how stronger security constraints lead to bigger security holes because they become too complicated to use.
Forgive me if I am misunderstanding you problem, but...
The point of SSO type systems is that the client authenticates directly to the (separate) authentication server, and obtains a ticket from it. It then passes the ticket to the target server(s) it wants to use, each of which verify that the ticket is valid with the authentication server. If the ticket is validated, it can be assumed by the server that the client only obtained it by presenting the (trusted) Kerberos server with acceptable credentials.
Nowhere in the process, should any server authenticate on behalf of the client. In such a system, the only server that needs to know and validate the client's credentials is the authentication server - no other server need have access to this information. This way the client can authenticate for many servers with just one authentication exchange, and credentials are not put at risk by being stored on, or accessible to, multiple servers.
It sounds like your implementation is working just as it should - the authentication should occur on the client side of the application, and this is correct and not a security risk.
Have you tried setting sun.security.jgss.native in Java 6? Wouldn't SSPI be the "native" interface for windows?
You can access the native SSPI API via JNA. See the WindowsAuthProviderImpl in WAFFLE or WindowsNegotiateScheme from the Apache HC library for an example.
Native support for Windows SSPI was introduced into JDK 13 and later backported to JDK 11 too. You'll need to use at least Java 11.0.10. When the JDK's support for SSPI is used then there's no longer a need to fiddle with the allowtgtsessionkey registry key, nor any need to use JNA or Waffle.
You need to set
-Dsun.security.jgss.native=true
to make it work.
You can recognize if your JDK version for Windows has support for SSPI if it includes a file named sspi_bridge.dll in the bin directory.
Refs:
JDK-6722928

Categories