Securing Applications

Security can be compromised in many ways, unauthorized users may access your applications data, someone may intercept a message being transmitted between two users, or crackers may expose vulnerabilities in your network or application server, giving them access to run commands on your O/S.

There are three security related subjects

Authentication is the process by which a system verifies the identity of a user, in most cases a user ID and a password is requested, however more sophisticated mechanisms can be used certificates, biometric data, smart cards, physical tokens, etc. If using a password it can be stored in a flat file, database or even LDAP.

Authorization is the process of verifying that a user has sufficient privileges to access an application resource, JBoss uses the common mechanism of roles to archive this, by assigning roles to a user then giving access to resources to the role, the user will be able to access the resource, this is commonly known as role-based authorization.

JBoss Security SX Framework

JBoss uses the JBoss security SX framework, which builds on top of the Java Authentication and Authorization Service (JAAS) which secures all the Java EE technologies running in the application.

A incoming component request is routed to a JBoss SX component called a security domain, an abstraction used to secure all requests made to a component, the security domain performs any necessary checks and notifies the component whether the user can proceed or not. The security domain knows how to use one or more login modules to load security data from a data source. Security domains are configured at the server level and can be used by any component within the server. Security domains are bound into JNDI (see Tomcat JNDI for information on JNDI) when the server starts, JNDI context maps a component to a security domain. This information in in the server/xxx/conf/login-config.xml file.

example of a security domain (login-conf.xml) <application-policy name="jmx-console">
  <authentication>
    <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule" flag="required">
      <module-option name="usersProperties">props/jmx-console-users.properties</module-option>
      <module-option name="rolesProperties">props/jmx-console-roles.properties</module-option>
    </login-module>
  </authentication>
</application-policy>

The above example is the jmx-console login authorization, it starts off defining the security domain name "jmx-console", this name is the one bound into JNDI which would be java:/jaas/jmx-console, all bound security domains start with java:/jaas namespace. One note is that JBoss only bounds the security domain into JNDI after you deploy an application that references the security domain. The login-module points to a login module (Java class), you can point it to more than one if you need to, the module will load security information from a file in this case but can use a database or LDAP. The module-options obviously is used by the login-module to obtain the file names, so check what options your particular module will use.

JBoss SX provides a feature called dynamic login configuration that allows you to define security in your application archive rather than in the server's login-config.xml file. To enable this feature, you have to create and deploy a MBean for the service to the server's server/xxx/deploy directory. This file can be named anything you like as long as it has the suffix -service.xml, this enables the appropriate JBoss deployer to pick it up and deploy it as a MBean service.

Example MBean dynamic login config <server>
  <mbean code="org.jboss.security.auth.login.DynamicLoginConfig" name="jboss:service=DynamicLoginConfig">
    <attribute name="AuthConfig">dynamic-login-config.xml</attribute>
    <depends option-attribute-name="LoginConfigService">jboss.security:service=XMLLoginConfig</depends>
    <depends option-attribute-name="SecurityManagerService">jboss.security:service=JaasSecurityManager</depends>
  </mbean>
</server>

Logging Additional Security

By default security logging is minimal, to increase this update the server/xxx/conf/jboss-log4j.xml

increase security logging <category name="org.jboss.security">
  <priority value="TRACE" class="org.jboss.logging.XLevel"/>
</category>
<category name="org.jboss.web.tomcat.security">
  <priority value="TRACE" class="org.jboss.logging.XLevel"/>
</category>
<category name="org.apache.catalina">
  <priority value="DEBUG"/>
</category>

Note: don't forget to comment out the threshold parameter in the appender that you want the logging messages to appear in.

Secure Communications

When sending data over the wire (network), you should be aware of three aspects of secure communication

To ensure confidentiality the sender often encrypts the message and the recipient decrypts the message, encrypted communication protocols ensure data integrity (use SSL and TLS protocols) and source integrity can be protected by using a reliable third party that assigns certificates to different people and organizations.

There are two types of encryption

symmetric

This is like a user having a secret message that he/she puts into a box and secures it with a padlock, if your friend has the same key to the padlock you can both open and close it knowing no else can.

Symmetric works in the same manor by using a secret key, a message is encrypted with a secret key and decrypted with the same key, as long as the key is not comprised the two parties can communicate securely.

asymmetric Public key encryption (asymmetric encryption) uses a pair of mathematically associated keys, after a message is encrypted with one, it can only be decrypted with the other. The keys are called public and private, the public you can give to anyone and the private you keep yourself, only the private key can decrypt messages encrypted by the public key. What this means is that you can freely distribute the public to anyone, the only drawback is that this mechanism is slower.

To ensure that the encrypted message you receive from the sender is actually the sender you think you are communicating with, you use a public key certificate which is a digital certificate that consists of some information about the certificate holders identity and a public key. To verify that the public key belongs to the user whose identity is on the certificate, a CA (Certificate Authority) signs the certificate. There are a number of public CA's that charge for public key certificates, VeriSign, Thawte and Entrust.

To get a signed certificate, you first generate a self-signed certificate and use it to create a Certificate Signing Request (CSR). The CSR and a few hundred bucks is then sent to the CA who validates your identity and then sends back a signed certificate. You can also create your own self-signed certificates which is a good idea when using them internally.

To create your own certificates the JVM comes with a tool called keytool, this tool can be used for the following

Generate a keystore and self-signed certificate keytool -genkey -alias "selfsigned" -keyalg RSA -keystore keystore.pfv -storepass "password123" -validity 360
Generate a keystore and Export the CSR file to get signed then Import the signed-cert from the CA keytool -genkey -alias mydomain -keyalg RSA -keystore keystore.pfv
keytool -certreq -alias mydomain -keystore keystore.pfv -file getMeSigned.csr
keytool -import -trustcacerts -alias mydomain -keystore keystore.pfv -file signedCertificate.crt
Export the certficate from the keystore to distribute it keytool -export -alias mydomain -keystore keystore.pfv -file mydomain.crt
Print keystore information keytool -list -v -keystore keystore.pfv
keytool -list -v -keystore keystore.pfv -alias mydomain

The JVM comes with a keystore that has many public key certificates, this type of keystore is a truststore, if you need to import any certificates in to the truststore use the below command

importing into the trust store keytool -import -alias myserver -file server.csr -keystore C:\jdk1.6.0_12\jre\lib\secruity\cacerts
specify on the commandline java -Djavax.net.ssl.trustStore=<file>
     -Djavax.net.ssl.trustStorePassword=<pass>

When using secure communications the server has to have a certificate, but the client does not. You can authenticate the client if required to do so although this is uncommon (normally use login/password authentication to identify the client) , this is called mutual authentication.

Authentication Strategy

Who wants to verify the other party's identity

Who needs public key?
Server Authentication Client Server
Mutual Authentication Client and Server Client and Server

Configuring an SSL-aware security domain

It is very simple to setup SSL through the HTTP connector, you cannot setup an SSL-aware security domain in the login-config.xml file, you must define an MBean instance of Jaas SecurityDomain that points to a truststore.

Create a file (see below example) that ends with -service.xml and place it in the server/xxx/deploy directory

Example SSL-aware security domain defined MBean <server>
  <mbean code="org.jboss.security.plugins.JaasSecurityDomain" name="jboss.security:service=MySecurityDomain">
    <constructor>
      <arg type="java.lang.String" value="my-security-domain"/>
    </constructor>
    <attribute name="KeyStoreURL">${jboss.server.home.dir}/conf/server.truststore</attribute>
    <attribute name="KeyStorePass">servercert</attribute>
    <depends>jboss.security:service=JassSecurityManager</depends>
  </mbean>
</server>

Note: this will now bind to JNDI as java:/jaas/my-security-domain

If you want your security domain to do authentication and authorization as well, you still need to define a security domain in your login-config.xml file

login-config.xml <application-policy name="my-security-domain">
  ...
</application-policy>

Configuring Login Modules

A JBoss SX login module knows how to access a security data source in order to load a users password and role information. Login modules are configured with security domains, each security domain can have one or more login modules, they are configured in the login-config.xml file.

Login Module Description
BaseCertLoginModule Authenticates client certificates, must be stacked with another login module that does authorization
CertRolesLoginModule An extension of BaseCertLoginModule that authenticates against client certificates and authorizes against properties files
ClientLoginModules Used by standalone clients that want to log into a secure server
DatabaseCertLoginModule An extension of BaseCertLoginModule that authenticates against client certificates and authorizes against a database
DatabaseServerLoginModule Loads user/role information from a database
IndentityLoginModule a testing login module that causes all users to authenticate with the same credentials
LdapExtLoginModule Loads user/roles information from a LDAP server (supports hierarchical role structure)
ldapLoginModule Loads user/roles information from a LDAP server (only works with flat role structures)
RunASLoginModule Can be stacked with another login module to define the run-as status that they use while they're authenticating, useful if you need to call a secured EJB that's responsible for authenticating users.
SimpleServerLoginModule A testing login module that allows any role with a null password to authenticate
SRPCacheLoginModule Used to authenticate users using the Secure Remote Password (SRP) protocol
SRPLoginModule Used by standalone clients that want to authenticate using the SRP protocol
UsersRolesLoginModule Loads user/roles information from property files

I have supplied a couple of examples of the most commonly used ones, but you can use any of the login modules, don't forget to lookup the options that are available for each module.

UserRolesLoginModule

<application-policy name="my-security-domain">
  <authentication>
    <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule" flag="required">
      <module-option name="usersProperties">my-users.properties</module-option>
      <module-option name="rolesProperties">my-roles.properties</module-option>
    </login-module>
  </authentication>
</application-policy>

# my-user.properies file
pvalle=password
willhay=password1
normanwisdom=password2

# my-role.properies file
pvalle=admin,movies
willhay=movies
normanwisdom=movies

DatabaseServerLoginModule <application-policy name="database-domain">
  <authentication>
    <login-module code="org.jboss.security.auth.spi.DatabaseServerLoginModule" flag="required">
      <module-option name="dsJndiName">java:/OracleDS</module-option>
      <module-option name="principalsQuery">select passwd from users where userid=?</module-option>
      <module-option name="rolesQuery">select roleid, 'Roles' from roles where userid=?</module-option>
    </login-module>
  </authentication>
</application-policy>