Covering J2EE Security and WebLogic Topics

VeriSign sells its PKI/SSL business to Symantec

Quick. What’s the first thing you think of when you hear the name “VeriSign?” Right, SSL and digital certificates.

VeriSign sold off its Authentication Services business to Symantec and is apparently now focusing on its network infrastructure and domain registrar businesses. For me, it’s weird to think of VeriSign without the PKI aspect. It’s also incongruent to have a PKI-related name like “VeriSign” mean anything but PKI now. Good thing they’re already an established company, I guess.

Frankly, I don’t know why I felt compelled to write about this other than it seems so humorous to me. The best part, though, is that selling to Symantec “delivers on [the] request” of its customers to have their “offerings integrated into a larger services suite.” Puh-leeze. I’m thinking it was Symantec’s cool $1.3B that REALLY delivered.

Learning how to write secure web apps

If you write web applications you owe it to yourself, your company, and your users to have some knowledge of the exploitation techniques that will be used against it. Knowing the techniques helps you write more secure code.

The obvious way to learn about such things is to read books or security web sites. The more interesting (OK, fun!) way of doing it is to actually perform the exploits against against a purposefully insecure web application that’s built to be hacked.

OWASP has had such an application for years. WebGoat is an insecure J2EE application that provides lessons on how to exploit the weaknesses. I tried this awhile ago and it’s really eye-opening from a non-hacking developer’s perspective.

Google has just created a similar application called Jarlsberg. Jarlsberg runs on Google’s AppEngine and is written in Python. However, language choice doesn’t matter much when it comes to security vulnerabilities in web applications. Like WebGoat, Jarlsberg teaches you how to perform the exploits in a series of hands-on lessons.

I haven’t tried Jarlsberg yet but it’s on my list of things to do.

Happy hacking!

Good primer on web security

Christian Heilmann wrote a nice post on web security topics. He gives an overview of the following attacks:

He also provides some practical tips for being safer on the web (as a user) and things you can do on your server and in your applications to be more secure. Neither his tips nor the article itself are about WebLogic but certainly most of the information is  relevant to any server and a good reminder in any case.

WebLogic 11g Released

Oracle Fusion Middleware 11g was released today which includes an updated WebLogic Server. For WebLogic Server there’s not a whole lot of news in the security department. Here’s what’s new:

  • A new Oracle Internet Directory Authentication Provider
  • A new Oracle Virtual Directory Authentication Provider
  • Support for WS-SecureConversation 1.3 on JAX-WS
  • Support for MTOM with WS-Security on JAX-WS

What’s interesting from the greater Fusion Middleware perspective, though, is the new Oracle Platform Security Service (OPSS) which provides common security functionality across the Fusion product line. It seems like Oracle took the WebLogic/AquaLogic Enterprise Security idea and ran with it big time. Looks like a major boon for all-Oracle shops…

Another WebLogic Security Blog

A colleague pointed out another blog that covers WebLogic security that you might find useful. Looks like Josh Bregman is off to a good start on his Oracle Fusion Middleware Security blog. Check it out.

Maven and the Tyranny of a WebLogic Installation

Can you stand another post on Maven and WebLogic? I can’t but I thought I’d document this anyway… ;-)

I decided to revisit the problem outlined in Maven and WebLogicMBeanMaker in WebLogic 9/10 wherein you need to have an installation of WebLogic on the machine where you build your security provider. To refresh your memory if you read that post, the problem is that weblogic.jar uses relative paths to find other jars and thus defeats Maven’s dependency mechanism.

I came up with a solution that precludes having to have WebLogic installed but it still doesn’t use artifacts in the repository. Rather, it’s a hack but at least it’s a portable hack.

The solution is to have a directory that contains the required WebLogic jars in the required hierarchy. Here’s the directory structure and subset of files you need from the WLS 9.x installation:

./common/lib/apache_xbean.jar
./server/lib/ant/ant.jar
./server/lib/cssapi.jar
./server/lib/cssimpl.jar
./server/lib/mbeantypes
./server/lib/mbeantypes/wlManagementImplSource.jar
./server/lib/mbeantypes/wlManagementMBean.jar
./server/lib/mbeantypes/wlSecurityProviders.jar
./server/lib/mbeantypes/xacmlSecurityProviders.jar
./server/lib/schema/weblogic-domain-binding.jar
./server/lib/weblogic.jar
./server/lib/xbean.jar

I made a directory to contain the directories and files above and then used that high level directory in the pom like this:

<dependency>
  <groupId>weblogic</groupId>
  <artifactId>weblogic<artifactId>
  <version>9.2.0</version>
  <scope>system</scope>
  <systemPath>C:/WLS920/server/lib/weblogic.jar</systemPath></dependency>

<dependency>
  <groupId>weblogic</groupId>
  <artifactId>wlManagementMBean</artifactId>
  <version>9.2.0<version>
  <scope>system</scope>
<systemPath>C:/WLS920/server/lib/mbeantypes/wlManagementMBean.jar</systemPath>
</dependency>

<dependency>
  <groupId>weblogic</groupId>
  <artifactId>xmlbeans</artifactId>
  <version>1.0</version>
  <scope>system</scope>
  <systemPath>C:/WLS920/server/lib/xbean.jar</systemPath>
</dependency>

As long as your WebLogicMBeanMaker tasks use “maven.compile.classpath” in the classpath then it should work like a champ.

Being freed from the tyranny of a WebLogic installation is a relief and lends itself to painless builds on a continuous integration server, for example.

Obviously, this solution is for WLS 9 (is anyone still using that?) but providers built this way also work in WLS 10.

Certificate to User Mapping in WebLogic

A reader of my Fifteen Minute Guide to Mutual Authentication post commented that perhaps the burden of doing mutual authentication (two-way SSL) isn’t worth the effort since you still have to map certificates to users. I’ll admit, that does seem like a bummer.

However, since most companies already have a list of users in LDAP or a database it’s probably not a big deal most of the time. WebLogic has several authentication providers that you can use to tap into your existing user store. Still, I think it’s a great question worth exploring so let’s consider what’s involved.

Strong Authentication

Having the user provide a certificate to the server is a form of strong authentication. No password traverses the network and the user must possess the certificate file. It’s extremely difficult to spoof a user due to the cryptography involved. The user is most definitely authenticated when the two-way SSL link is successfully created. In other words, they are who they say they are assuming you trust the Certificate Authority (CA) who signed their certificate.

Strong authentication alone is the primary benefit of using mutual authentication, of course. The user is who they say they are. We now need to turn our attention to authorization so that we can determine whether or not they can access the system.

Implicit Groups

If you don’t want to maintain cert-to-user mappings you can leverage WebLogic’s implicit groups. See the link for more info but you could use the “users” group to authorize users without maintaining a user list. The “users” group represents any authenticated user. When using mutual authentication, any user identified by their certificate will automatically be in this group. If you can get away with one role in your application then the “users” group may work for you. However, be sure to read about CAs below.

Certificate Authority Scope

The huge drawback to using the implicit “users” group in this way is that any certificate signed by the CAs you trust will be acceptable to your application. If you’re using the default JDK truststore “cacerts” you’ll wind up trusting the signed certificates of all the major and a ton of minor CAs from around the world.

The fix, of course, is if you control the CA. For example, if your company has a CA, you can configure your truststore to only have that CA’s certificate. Then, you only accept users from your company (and partners if they get certs signed by your company’s CA).

In this scenario you will still allow anyone signed by the company’s CA to have access to your app. Whether that’s acceptable or not is a business decision. If you go this route make doubly sure that you ONLY trust your company’s CA.

Deprovisioning Users

When you don’t have a list of users how do you deny them access when they quit?

Revoking the certificate is the obvious answer. Checking certificate revocation requires a custom security provider and is outside the scope of this article. However, the implication is that your public key infrastructure must be mature enough to have OCSP or CRLs for you to check revocation in the first place.

Conclusion

To summarize, it is possible to use mutual authentication without maintaining a list of users. However, you need to exercise extreme care when doing so. Also, authorization flexibility is reduced to just one possible role since there’s only one group to which to map.1


Footnote:

1. Technically, you can do the mapping to multiple roles if certain preconditions exist and you’re willing to do some extra work. As an example scenario, let’s say you use your own CA. Your CA uses OU fields in the DN which you might be able to leverage for role mapping. You’d have to write your own authentication provider to add groups to the subject based upon the OU information and then you can map the roles to the groups as usual in your application’s deployment descriptors.

Friendlier Navigation Syntax in WLST

In WLST (WebLogic Scripting Tool), how many times have you wished you didn’t have to type the parentheses or quotes when navigating MBeans? For me, I wished for that every time. ;-)

Fortunately, WLST designer Satya Ghattu lets us in on a little secret. Simply enter easeSyntax() while in online mode and you can drop the parentheses and quotes when navigating. Using Satya’s examples:

cd(“/Servers/testServer”)

turns into the friendlier

cd /Servers/testServer

Thanks for the tip, Satya!

WebLogic 10 Active Directory Authentication Provider Bug

Reader Cobbie Behrend emailed with a bug he noticed in the Active Directory authentication provider in WebLogic 10. He writes:

“The class that handles AD authentication has a small bug in it that causes authentication to fail [at a later time] after someone logs in incorrectly. During authentication the AD provider binds twice using the same LDAP connection, once with the username password being authenticated, and once with the credentials supplied when you configure the LDAP provider. If authentication fails, the second binding doesn’t happen, and the unauthenticated LDAP connection is returned to the internal LDAP connection pool. This poses a problem when later trying to authenticate and the unauthenticated LDAP connection is retrieved from the pool (you get a stack trace from netscape LDAP classes telling you that the connection has not been bound).

Below is the nested stack trace that you get from WebLogic. The really confusing part when you try to figure this one out is that the point of failure changes, as it all depends on when the bogus connection is being used… also if you are using the same AD user for WebLogic configuration of LDAP, and for testing your application (typical bad development behavior), you don’t notice that the connection is bogus when you turn security logging on. So below the failure is at getDNForUser, but I’ve also seen it happen getting the group members of a group (when testing using a different user).”

netscape.ldap.LDAPException: error result (1); 00000000: LdapErr: DSID-0C090627, comment: In order to perform this operation a successful bind must be completed on the connection., data 0, vece
at netscape.ldap.LDAPConnection.checkMsg(Unknown Source)
at netscape.ldap.LDAPConnection.checkSearchMsg(Unknown Source)
at netscape.ldap.LDAPConnection.search(Unknown Source)
at weblogic.security.providers.authentication.LDAPAtnDelegate.getDNForUser(LDAPAtnDelegate.java:3310)
at weblogic.security.providers.authentication.LDAPAtnDelegate.authenticate(LDAPAtnDelegate.java:3180)
at weblogic.security.providers.authentication.LDAPAtnLoginModuleImpl.login(LDAPAtnLoginModuleImpl.java:200)
at com.bea.common.security.internal.service.LoginModuleWrapper$1.run(LoginModuleWrapper.java:110)
at java.security.AccessController.doPrivileged(Native Method)
at com.bea.common.security.internal.service.LoginModuleWrapper.login(LoginModuleWrapper.java:106)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at javax.security.auth.login.LoginContext.invoke(LoginContext.java:769)
at javax.security.auth.login.LoginContext.access$000(LoginContext.java:186)
at javax.security.auth.login.LoginContext$4.run(LoginContext.java:683)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.login.LoginContext.invokePriv(LoginContext.java:680)
at javax.security.auth.login.LoginContext.login(LoginContext.java:579)
at com.bea.common.security.internal.service.JAASLoginServiceImpl.login(JAASLoginServiceImpl.java:93)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at com.bea.common.security.internal.utils.Delegator$ProxyInvocationHandler.invoke(Delegator.java:57)
at $Proxy11.login(Unknown Source)
at weblogic.security.service.internal.WLSJAASLoginServiceImpl$ServiceImpl.login(Unknown Source)
at com.bea.common.security.internal.service.JAASAuthenticationServiceImpl.authenticate(JAASAuthenticationServiceImpl.java:82)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at com.bea.common.security.internal.utils.Delegator$ProxyInvocationHandler.invoke(Delegator.java:57)
at $Proxy32.authenticate(Unknown Source)
at weblogic.security.service.PrincipalAuthenticator.authenticate(Unknown Source)
at weblogic.servlet.security.internal.SecurityModule.checkAuthenticate(SecurityModule.java:256)
at weblogic.servlet.security.internal.SecurityModule.checkAuthenticate(SecurityModule.java:205)
at weblogic.servlet.security.internal.FormSecurityModule.processJSecurityCheck(FormSecurityModule.java:245)
at weblogic.servlet.security.internal.FormSecurityModule.checkUserPerm(FormSecurityModule.java:200)
at weblogic.servlet.security.internal.FormSecurityModule.checkAccess(FormSecurityModule.java:91)
at weblogic.servlet.security.internal.ServletSecurityManager.checkAccess(ServletSecurityManager.java:82)
at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2076)
at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2046)
at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1366)
at weblogic.work.ExecuteThread.execute(ExecuteThread.java:200)
at weblogic.work.ExecuteThread.run(ExecuteThread.java:172)

Cobbie points out that you don’t even see the stack trace above unless you enable authentication debugging. He says, “In the console you must set environment -> servers -> AdminServer -> Logging -> Advanced -> Severity Level to debug. To turn on security logging you have to change environment -> servers -> AdminServer -> Debug -> WebLogic -> security -> atn -> DebugSecurityAtn to enabled.”

Cobbie contacted Oracle and received a patch but it doesn’t seem to be a “normal” one in that it was not given a unique name like most patches. Instead, Oracle sent him a new cssWlSecurityProviders.jar file via email.

Cobbie notes:

“The patch works, but only if you have “Use Retrieved User Name as Principal” set to false. If a user sets “Use Retrieved User Name as Principal” property to true the connection should be returned to the pool for the retrieved user (something that was also fixed by this patch).

This works great if a correct password is passed in. However if incorrect credentials are passed in and you have “Use Retrieved User Name as Principal” set to true, you have the same issue as before. The unauthenticated connection gets added to the LDAP connection pool, and future attempts to use it fail.

It appears that there still is no check to confirm that the connection is authenticated before the connection is returned to the pool (or from the pool).”

Hopefully, this post will spare others the troubleshooting effort when they encounter this subtle bug.

Thanks Cobbie!

The WebLogic Administration Port

Is your WebLogic console available to anyone on the Internet? A quick Google search might be eye-opening:

http://www.google.com/search?q=%22Administration+Console%22+%22Sign+in%22+WebLogic+inurl:%22console%22&hl=en&filter=0

If you try this search you’ll see approximately two pages of exposed consoles. A colleague I showed this to pondered: “How many still use weblogic/weblogic?” Good question. Scary, too.

Simon Vans-Colina wrote “Competitive Intelligence Gathering with Google” wherein he discusses two ways of gleaning which server a site is using. He demonstrated how to search for stacktraces which give very obvious clues as well as the console searching technique shown above.

It’s also important to realize that the results from the search above only found the unfortunate sites whose links were published in some way for Google to find them. Regardless of the search results, someone could go directly to your site and slap a “/console” on the end of your domain to see what happens.

These problems aren’t new and they’re not limited to WebLogic, of course. Any server software that exposes a web-based administration application is fair game. Blogging apps, CMS’s, you name it — they all expose an admin app. If you’re lucky, your application will provide some way to restrict access to the administrative functionality. This post is about securing WebLogic’s console.

You have two choices if you don’t want your server caught with its pants down:

  1. Disable the console application
  2. Use the administration port

Disabling the console application is a bit extreme. If you do that you can only administer your server with weblogic.Admin, WLST, or a custom JMX client. That all seems a bit too inconvenient so the second option is the way to go and will be described below.

Enabling the administration port prevents the masses from accessing your console while giving you access to the same. It’s the best of both worlds. With the administration port enabled:

  • The console is only accessible over a non-standard port (which should not be available from outside your firewall)
  • You have to use SSL
  • You get a dedicated administration listen thread
  • Administrative requests over any port other than the admin port are rejected

So, by using the admin port you protect your console and get several other nice side-effects. The admin port will not be on port 80 or 443 and will thus not be available outside your firewall. Technically, you could open the admin port on the firewall but then you’re back in the same boat. Also, anybody who tries to do an administrative request over any other port will find their request rejected.

Another feature is that your interaction with the console has to be over SSL which protects your data as it transits the wire. And really, who doesn’t love SSL? (Aside: When is the last time you heard of data compromise via an SSL attack? Pretty rare, indeed.)

Finally, using the admin port gets you a dedicated listen thread. What’s the big deal? Let’s say that you have 40 listen threads and the admin port is not enabled. A bug or poor resource utilization causes all 40 threads to be blocked or otherwise unavailable. If you want to get into the console and see what’s going on or fix the problem you’d be out of luck because there’s no thread available to do your work. That’s not good.

The outlook is sunnier when you’ve enabled the admin port, though. Now you have 40 normal listen threads and a dedicated admin thread. If all 40 normal threads are hung you still have a responsive thread for doing your investigation. Of course, you can also look at the separate thread benefit from the opposite perspective: An admin poking around on the console won’t consume a thread intended for satisfying user requests.

Now you’re clamoring for the admin port, right? ;-) Let’s set it up.

A prerequisite is that you need to set up SSL normally which is well-documented by BEA. After that, access the console and do the following:

  1. Click on the first node under Domain Structure (it’s your domain name)
  2. Click Lock & Edit
  3. Select the Enable Administration port checkbox
  4. Specify the administration port
  5. Click Save
  6. Click Activate Changes

No restart is required and you’re automatically switched to using the admin port. By the way, the same page allows you to disable the console or change its context path.

Now that you’re using the admin port, if you attempt to access the console over the standard listen ports you’ll be greeted with

Console/Management requests can only be made through an administration channel

Unfortunately, this is also a fingerprint of WebLogic but at least your console is hidden behind your firewall. You can mitigate this fingerprinting to a degree by changing the context path for the console. For example, I changed mine to SecurityThroughObscurity and I would thus access the console via

https://localhost:7777/SecurityThroughObscurity

assuming 7777 is my admin port. Now, going to http://localhost/console will provide the inquisitive user with a nice 404–Not Found page.

The choice of “SecurityThroughObscurity” was obviously tongue-in-cheek but it does highlight the fact that changing the context path is not securing anything but it is making it harder to find. Every little bit helps, I guess.

There are some things of which you need to be aware if you’re running a cluster. See Administration Port and Administrative Channel for more information.

P.S. Don’t forget to change BOTH your username and password. People are on to weblogic/weblogic, I’m afraid… ;-)

« Previous Entries  

Bookmark this page on del.icio.us