Spring Security

Before getting started we need to understand the basics of security.

What is security from an web application point of view?  Web security mainly comprises the following areas:  websites, web applications and web services.  Authentication is the verification of the credentials of the connection attempt. This process consists of sending the credentials from the remote access client to the remote access server in either a cleartext or encrypted form using an authentication protocol.  Authorization is the verification that the connection attempt is allowed. Authorization occurs after successful authentication.

What type of security threats are the above mentioned in web securities?  The vulnerabilities are varied amongst a collage of attacks and approaches, such as:

  1. Cross-site scripting
  2. SQL injection
  3. Denial of service attacks
  4. Buffer overload
  5. Code injection
  6. Memory corruption
  7. Cross Site Request Forgery (CSRF)

These are the most common attacks and things a developer should be prepared to understand and prevent in their code.

Another area of security provides access or no access to users based on the authority.  The user may have partial access to the application whereas another user may have complete access.

So we can assume that applications are secured by access control and also by preventing harmful code to exploit vulnerabilities.

There are many facets to security in general and can be viewed from various seats.  Our main focus since this is based on Spring Security is web application security.  In order to be fully security aware, the security person should analyze the security of the possible threats from various forms such as, network access, firewalls, software, and also human (social) interaction.

Now with a better understanding of what security is and what types of vulnerabilities exist, we can now dive into discussing Spring Security. As of this writing, we are using the Spring Security 4.0.0.M2 version and is what we will focus on.  In order to download and use the package that includes the security piece, you can easily do so by using Maven.

Within your pom.xml file you can use the following dependency to download jars needed for the security dependency:

<dependencies>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>4.0.0.M2.RELEASE</version>
</dependency>
</dependencies>

If you have worked with Spring, you are probably familiar with Maven.  If not, Maven is a tool used kind of like Ant, but it does all the work for you.  The only tricky part is the setup, which is fairly simple and straightforward and will not be discussed here.  You should familiarize yourself with it as it is commonly used on most projects.  By including the above dependency, pom.xml file, in your project, the application will pull down the latest version of the jars for you and will not be included until you build it.  So by defining the group id maven looks at it maven site for prerequisites and then determines the version you need and then it is pulled into the project.  So your pom.xml file will have other dependencies to pull down any other jars needed to build the project into a war.  Pretty cool huh?

Common Features Of Spring Security

  • Comprehensive and extensible support for both Authentication and Authorization
  • Protection against attacks like session fixation, clickjacking, cross site request forgery, etc
  • Servlet API integration
  • Optional integration with Spring Web MVC

Why use Spring Security?  Spring Security is a great way to implement security and enjoy the broad range of features that is offered by the packages.  As mentioned above the user can use various forms of attacks and vulnerabilities to exploit a web application.  Spring is package to handle those issues and most be specifically configured to prevent such vulnerabilities.  It is possible to view exploits for classroom affects to see the value in having security to prevent such acts.  There are other non Spring approaches to security but do not provide the added help to deal with vulnerabilities, so it is recommended to use Spring Security.

Java Configuration

Prior to Spring Security 3.2 the developer was required to use xml to configure Java Security.  There are similarities between version 3.1 and 3.2 within the Security Namespace Configuration.  The first step is to create a springSecurityFilterChain, which allows the application to process all requests filtering each request.

The following is an example of a basic easy approach to use:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.*;
import org.springframework.security.config.annotation.authentication.builders.*;
import org.springframework.security.config.annotation.web.configuration.*;

@Configuration
@EnableWebSecurity
publicclassSecurityConfigextendsWebSecurityConfigurerAdapter{

@Autowired

    publicvoid configureGlobal(AuthenticationManagerBuilder auth)throwsException {
          auth
            .inMemoryAuthentication()
                .withUser(“user”).password(“password”).roles(“USER”);
    }
}

The next thing to do is register  springSecurityFilterChain, and Spring has a base class to handle this.  AbstractSecurityWebApplicationInitializer is a base class that can handle the registration of the filter chain.

This approach only works if you are using Spring MVC.  The following code would be used to complete that task:

import org.springframework.security.web.context.*;

publicclassSecurityWebApplicationInitializer
      extends AbstractSecurityWebApplicationInitializer{}

Spring does offer an alternative if you are not using Spring MVC and must add the following constructor to the above class:

publicSecurityWebApplicationInitializer(){
      super(SecurityConfig.class);
}

Now that we have the basic wiring setup for URL processing, which provides all URLs be preprocessed by our filter chain. 

Next we need to ensure SecurityConfig is loaded by SecurityWebApplicationInitializer, by overriding getRootConfigClasses.

publicclassMvcWebApplicationInitializer
extends AbstractAnnotationConfigDispatcherServletInitializer{

@Override
protectedClass<?>[] getRootConfigClasses(){
       returnnewClass[]{
          SecurityConfig.class};
       } // … other overrides …
}

If we want to use form based authentication, we would setup the following code:

protectedvoid configure(HttpSecurity http)throwsException{
    http .authorizeRequests()
            .anyRequest().authenticated()
            .and().formLogin()
            .and().httpBasic();
}

The code example above is an implementation without having to use xml, but for some who are familiar with the xml approach may be more familiar with the following code:

<httpuse-expressions=”true”>
    <intercept-urlpattern=”/**”access=”authenticated”/>
    <form-login/>
    <http-basic/>
</http>

HTTP Basic authentication is the weakest for of authentication and is not usually used unless you have a simple application that security may not be that important.  An interesting point to spell out is Spring Security will implement a version of a login using the above actions.  No additional coding is required and a login form will be rendered to the user.  This is typical overriding with your own login page.

In order to create your own login, you can use something like this:

protectedvoid configure(HttpSecurity http)throwsException {

     http .authorizeRequests()
        .anyRequest()
        .authenticated()
        .and()
        .formLogin()
        .loginPage(“/login”)
        .permitAll();       
}

The login page would use something similar to this:

<c:urlvalue=”/login”var=”loginUrl”/>
<formaction=”${loginUrl}”method=”post”>
  <c:iftest=”${param.error != null}”>
     <p> Invalid username and password. </p>
  </c:if>

  <c:iftest=”${param.logout != null}”>
     <p> You have been logged out. </p>
  </c:if>
     <p><labelfor=”username”>Username</label>
        <inputtype=”text”id=”username”name=”username”/>
     </p>
     <p><labelfor=”password”>Password</label>
        <inputtype=”password”id=”password”name=”password”/>
     </p>
    <inputtype=”hidden”name=”${_csrf.parameterName}”              value=”${_csrf.token}”/>
    <buttontype=”submit”class=”btn”>Log in</button>
</form>

Using the following example, we can see you can customize actions accordingly:

protectedvoid configure(HttpSecurity http)throwsException{

    http .authorizeRequests() 
    .antMatchers(“/resources/**”, “/signup”, “/about”).permitAll()     
    .antMatchers(“/admin/**”).hasRole(“ADMIN”)
    .antMatchers(“/db/**”).access(“hasRole(‘ROLE_ADMIN’)
       and hasRole(‘ROLE_DBA’)”).anyRequest().authenticated()
    .and()

     // …

    .formLogin();
}

The code above is self explanatory but in case it is not clear to the reader we can elaborate the obvious.  As you can see the following urls /resources, /signup, and /about are allowing all users access and the ** in resources ensures anything with the url /resources and any other urls not defined.  This is good to use when many urls inclusions exist.  The /admin and /db urls are requiring authentication.

An in memory approach would look like this:

@Autowiredpublicvoid configureGlobal(AuthenticationManagerBuilder auth)throwsException{
    auth .inMemoryAuthentication()
            .withUser(“user”).password(“password”).roles(“USER”)
         .and().withUser(“admin”).password(“password”).roles(“USER”,”ADMIN”);
}

Hard coded values should not be used when ever possible.  This type of code requires code changes to update credentials and if you wanted to have multiple admin logins then you would have to create a chain of login and passwords in the code. 

If you want to use a JDBC approach:

@Autowired
privateDataSource dataSource;

@Autowiredpublicvoid configureGlobal(AuthenticationManagerBuilder auth)throwsException{

    auth .jdbcAuthentication()
            .dataSource(dataSource)
            .withDefaultSchema()
            .withUser(“user”).password(“password”).roles(“USER”).and()
            .withUser(“admin”).password(“password”).roles(“USER”,   “ADMIN”);

Here is an LDAP approach:

@Autowired
privateDataSource dataSource;

@Autowired
publicvoid configureGlobal(AuthenticationManagerBuilder auth)throwsException{
    auth .ldapAuthentication()
            .userDnPatterns(“uid={0},ou=people”)
            .groupSearchBase(“ou=groups”);
}

If there is a good reason to do so, you can also define multiple configurations to accomplish different authentications.

There are many ways to provide access restrictions to certain parts of the application.  Here is an example of a way to provide such constraints:

publicinterfaceBookService{
  @Secured(“IS_AUTHENTICATED_ANONYMOUSLY”)
  public Booking readBooking(Schedule schedule);
  @Secured(“IS_AUTHENTICATED_ANONYMOUSLY”)
  publicBooking[] findBookings();
  @Secured(“ROLE_DISPATCHER”)
  publicBooking post(Booking booking,Schedule schedule);
}

In order to use the above snippet you must define the following:

@Configuration@EnableGlobalMethodSecurity(securedEnabled =true)

publicclassMethodSecurityConfig{

   // …

}

Define the filter in web.xml:

<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy
</filter-class>
</filter>
<filter-mapping>
  <filter-name>springSecurityFilterChain</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

The above code illustrates how all url patterns will be processed by the springSecurityFilterChain.  The /* indicates all requests get processed or you could have another pattern if the filter should only apply in certain cases.

What is authentication?

Authentication is the ability to discriminate based on a way to ensure the person who’s login is verified by user name and password.  This only ensure the person who logs in properly knew the username/password, but does not guarantee it is the actual person who is authorized.  User context information is returned as used to have access to roles and other information about the user.  More then one form of authentication can be used to help to ensure the authorized person is using the system.  We can now use an access control mechanism across all application resources.

Here is a commandline example:

import org.springframework.security.authentication.*;
import org.springframework.security.core.*;
import org.springframework.security.core.authority.SimpleGrantedAuthority;import org.springframework.security.core.context.SecurityContextHolder;publicclassAuthenticationExample{

  privatestaticAuthenticationManager am =newSampleAuthenticationManager();

publicstaticvoid main(String[] args)throwsException{
    BufferedReader in =newBufferedReader(newInputStreamReader(System.in));
while(true){
      System.out.println(“Please enter your username:”);
      String name = in.readLine();
System.out.println(“Please enter your password:”);
      String password = in.readLine();try{Authentication request =newUsernamePasswordAuthenticationToken(name, password);
        Authentication result = am.authenticate(request);SecurityContextHolder.getContext().setAuthentication(result);break;
      }
      catch(AuthenticationException e){
        System.out.println(“Authentication failed: “+ e.getMessage());
      }
    }

    System.out.println(“Successfully authenticated. Security context contains: “+SecurityContextHolder.getContext().getAuthentication());
  }
}

classSampleAuthenticationManagerimplementsAuthenticationManager{
  staticfinalList<GrantedAuthority> AUTHORITIES =newArrayList<GrantedAuthority>();static{
    AUTHORITIES.add(newSimpleGrantedAuthority(“ROLE_USER”));
  }

  publicAuthentication authenticate(Authentication auth)throwsAuthenticationException{
    if(auth.getName().equals(auth.getCredentials())){
      returnnewUsernamePasswordAuthenticationToken(auth.getName(), auth.getCredentials(), AUTHORITIES);
    }thrownewBadCredentialsException(“Bad Credentials”);
  }
}

We have to this point of discussed username and passwords, and we have not discussed securing the data or making our data more secure.  A system that stores passwords should use password encoding and never should be in plain text.  Do not use a plain hash function and sha or md5 should be used.  A hash is used to change the value of a password and is then stored versus the plain text.  Hashing makes it harder for someone viewing the data to determine the actual password.  Hashing algorithms are basically a shortened version of the actual string and is often used for encryption algorithms.  A better approach to securing data would be to call an enterprise application, which performs this action.

Web Application Security

As the heading suggests we are focused on web application security which make use of HTTP and Servlet API. 

The easiest way to provide security via your application is to setup and use servlet filters.  Filters are very useful for many purposes but the main thing to remember is filters provide a robust approach to a systematic approach to handle all http requests and to be able to provide some functional control globally without having to do it in each class.  This provides the ability to create a SecurityFilter that is called each time a request is made on the server.  You can easily imagine that would be useful for security and other purposes.  Filters are added to the web.xml file and are mapped to a servlet already defined to handle requests. 

To use DelegatingFilterProxy, you will need to add something like this in the web.xml file:


<filter>
<filter-name>myFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>myFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</filter>

Now that you have setup the use of DelegatingFilterProxy you can create an instance using the following:


<bean id="filterChainProxy"class="org.springframework.security.web.FilterChainProxy">
<constructor-arg>
<list><sec:filter-chainpattern="/restful/**"filters="
           securityContextPersistenceFilterWithASCFalse,
           basicAuthenticationFilter,
           exceptionTranslationFilter,
           filterSecurityInterceptor"/>
<sec:filter-chainpattern="/**"filters="
           securityContextPersistenceFilterWithASCTrue,
           formLoginFilter,
           exceptionTranslationFilter,
           filterSecurityInterceptor"/>
</list>
</constructor-arg>
</bean>

Request Mapping & HttpFirewall

FilterChainProxy is responsible for deciding which requests get processed and FilterSecurityInterceptor decides which security constraints apply.  The servlet specification requires that the HttpServetRequest is accessible by specific getter method functions.  These are the contextPath, servletPath, pathInfo, and queryString.  Spring Securiity is only concerned with paths, so the contextPath is ignored.  The servlet specification does not clearly define where parameters are stored in the servletPath or pathInfo, so it varies from servlet container.  Security defined at the service layer is much better for handling security and should be used.
 

Filter Security Interceptor

FilterSecurityInterceptor is responsible for handling the security for HTTP resources.  The interceptor will require an AuthenticationManager and AccessDecisionManager be used to handle the control. 

Here is an example of a bean using the interceptor:

<beanid=”filterSecurityInterceptor”class=”org.springframework.security.web.access.intercept.FilterSecurityInterceptor”>
  <propertyname=”authenticationManager”ref=”authenticationManager”/>
  <propertyname=”accessDecisionManager”ref=”accessDecisionManager”/>
<propertyname=”securityMetadataSource”>
    <security:filter-security-metadata-source>
<security:intercept-urlpattern=”/secure/super/**”access=”ROLE_WE_DONT_HAVE”/><security:intercept-urlpattern=”/secure/**”access=”ROLE_SUPERVISOR,ROLE_TELLER”/></security:filter-security-metadata-source>
  </property>
</bean>
 

ExceptionTranslationFilter

As the name suggests,  this filter is used to handle any exceptions thrown with the FilterSecurityInterceptor and does not handle any security. 

Here are examples of beans that can be defined:

<beanid=”exceptionTranslationFilter”class=”org.springframework.security.web.access.ExceptionTranslationFilter”>
 <propertyname=”authenticationEntryPoint”ref=”authenticationEntryPoint”/>
 <propertyname=”accessDeniedHandler”ref=”accessDeniedHandler”/>
</bean>

<beanid=”authenticationEntryPoint”class=”org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint”>
<propertyname=”loginFormUrl”value=”/login.jsp”/>
</bean>

<beanid=”accessDeniedHandler”class=”org.springframework.security.web.access.AccessDeniedHandlerImpl”>
<propertyname=”errorPage”value=”/accessDenied.htm”/>
</bean>
 

AuthenticationEntryPoint

The AuthenticationEntryPoint will be called if the user requests a secure HTTP resource but they are not authenticated. An appropriate AuthenticationException or AccessDeniedException will be thrown by a security interceptor further down the call stack, triggering the commence method on the entry point. This does the job of presenting the appropriate response to the user so that authentication can begin. The one we’ve used here is LoginUrlAuthenticationEntryPoint, which redirects the request to a different URL (typically a login page). The actual implementation used will depend on the authentication mechanism you want to be used in your application.
 

AccessDeniedHandler

AccessDeniedHandler is called after a user has been authenticated but does not have permissions to a resource of which they have tried to access.  By default, an AccessDeniedHandlerImpl is used, which just sends a 403 (Forbidden) response to the client.
 

SecurityContextPersistenceFilter

As we saw previously, this filter has two main tasks. It is responsible for storage of the SecurityContext contents between HTTP requests and for clearing the SecurityContextHolder when a request is completed. Clearing the ThreadLocal in which the context is stored is essential, as it might otherwise be possible for a thread to be replaced into the servlet container’s thread pool, with the security context for a particular user still attached. This thread might then be used at a later stage, performing operations with the wrong credentials.

Here is a simple implementation of the class:

<beanid=”securityContextPersistenceFilter”class=”org.springframework.security.web.context.SecurityContextPersistenceFilter”/>
 

SecurityContextRepository

The following interface is used for loading and storing securityContext:

publicinterfaceSecurityContextRepository{
  SecurityContext loadContext(HttpRequestResponseHolder requestResponseHolder);
void saveContext(SecurityContext context,HttpServletRequest request,HttpServletResponse response);
}

Here is an example of a bean implementation:

<beanid=”securityContextPersistenceFilter”class=”org.springframework.security.web.context.SecurityContextPersistenceFilter”>
  <propertyname=’securityContextRepository’>
    <beanclass=’org.springframework.security.web.context.HttpSessionSecurityContextRepository’>
<propertyname=’allowSessionCreation’value=’false’/>
    </bean>
  </property>
</bean>
 

UsernamePasswordAuthenticationFilter

The login form simply contains j_username and j_password input fields, and posts to the URL that is monitored by the filter (by default this is /j_spring_security_check). The basic filter configuration looks something like this:

<beanid="authenticationFilter"class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
<propertyname="authenticationManager"ref="authenticationManager"/>
</bean>

 

Application Flow on Authentication

The AuthenticationManager is responsible for handling authentication and will pass control to the AuthenticationSuccessHandler and AuthenticationFailureHandler accordingly.  So if a user were to login and if they are authenticated successfully, then they would be passed to the AuthenticationSuccessHandler , otherwise they would be passed to the AuthenticationFailureHandler for a failed attempt.
 

Servlet 3+ Integration

Spring integrates with the Servlet 3 specification by interfacing with the authenticate and login member functions.  The HttpServletRequest.authenticate will proceed to the application if successful authentication and will send the request back to the HttpServletRequest.login if it fails.   HttpServletRequest.logout is used to log the current user out of the application.  At this point, the HttpSession will be invalidated and typically a redirect to a welcome page or logout page.
 

AsyncContext.start(Runnable)

The AsyncContext.start(Runnable) method that ensures your credentials will be propagated to the new Thread. Using Spring Security’s concurrency support, Spring Security overrides the AsyncContext.start(Runnable) to ensure that the current SecurityContext is used when processing the Runnable. For example, the following would output the current user’s Authentication:

 
finalAsyncContext async = httpServletRequest.startAsync();
async.start(newRunnable(){publicvoid run(){
Authentication authentication =SecurityContextHolder.getContext().getAuthentication();
try{
           finalHttpServletResponse asyncResponse =(HttpServletResponse) async.getResponse();
            asyncResponse.setStatus(HttpServletResponse.SC_OK);
            asyncResponse.getWriter().write(String.valueOf(authentication));
            async.complete();
}catch(Exception e){
  thrownewRuntimeException(e);
}
}
});

 

Basic and Digest Authentication

Basic authentication is often used with web applications today especially with sites that are not done as an enterprise approach.  In most web applications quickly being done using simple web application generators are perfect for the small company and when limited exposure.  Basic authentication uses plain text to transport passwords and should not be used in most cases.  If it has to be used then you can ensure at a minimum to use SSL (HTTPS). 
 

BasicAuthenticationFilter

BasicAuthenticationFilter is responsible for processing basic authentication credentials presented in HTTP headers. This can be used for authenticating calls made by Spring remoting protocols (such as Hessian and Burlap), as well as normal browser user agents (such as Firefox and Internet Explorer). The standard governing HTTP Basic Authentication is defined by RFC 1945, Section 11, and BasicAuthenticationFilter conforms with this RFC. Basic Authentication is an attractive approach to authentication, because it is very widely deployed in user agents and implementation is extremely simple (it’s just a Base64 encoding of the username:password, specified in an HTTP header).
 

DigestAuthenticationFilter

DigestAuthenticationFilter is capable of processing digest authentication credentials presented in HTTP headers. Digest Authentication attempts to solve many of the weaknesses of Basic authentication, specifically by ensuring credentials are never sent in clear text across the wire. Many user agents support Digest Authentication, including FireFox and Internet Explorer. The standard governing HTTP Digest Authentication is defined by RFC 2617, which updates an earlier version of the Digest Authentication standard prescribed by RFC 2069. Most user agents implement RFC 2617. Spring Security’s DigestAuthenticationFilter is compatible with the “auth” quality of protection (qop) prescribed by RFC 2617, which also provides backward compatibility with RFC 2069. Digest Authentication is a more attractive option if you need to use unencrypted HTTP (i.e. no TLS/HTTPS) and wish to maximise security of the authentication process. Indeed Digest Authentication is a mandatory requirement for the WebDAV protocol, as noted by RFC 2518 Section 17.1.
 

 Cross Site Request Forgery (CSRF)

What is a cross site request forgery threat? 

Assume that your bank’s website provides a form that allows transferring money from the currently logged in user to another bank account. For example, the HTTP request might look like:

POST /transfer HTTP/1.1Host: bank.example.com
Cookie: JSESSIONID=randomid;Domain=bank.example.com;Secure;HttpOnlyContent-Type: application/x-www-form-urlencoded

amount=100.00&routingNumber=1234&account=9876
 
 

Now pretend you authenticate to your bank’s website and then, without logging out, visit an evil website. The evil website contains an HTML page with the following form:


<formaction="https://bank.example.com/transfer"method="post">     <inputtype="hidden"name="amount"value="100.00"/>
<inputtype="hidden"name="routingNumber"value="evilsRoutingNumber"/>
<inputtype="hidden"name="account"value="evilsAccountNumber"/><inputtype="submit"value="Win Money!"/>

</form>

We all like to win money, so you click on the submit button. In the process, you have unintentionally transferred $100 to a malicious user. This happens because, while the evil website cannot see your cookies, the cookies associated with your bank are still sent along with the request.

Worst yet, this whole process could have been automated using JavaScript. This means you didn’t even need to click on the button. So how do we protect ourselves from such attacks?

One solution is to use the Synchronizer Token Pattern. This solution is to ensure that each request requires, in addition to our session cookie, a randomly generated token as an HTTP parameter. When a request is submitted, the server must look up the expected value for the parameter and compare it against the actual value in the request. If the values do not match, the request should fail.

We can relax the expectations to only require the token for each HTTP request that updates state. This can be safely done since the same origin policy ensures the evil site cannot read the response. Additionally, we do not want to include the random token in HTTP GET as this can cause the tokens to be leaked.

Let’s take a look at how our example would change. Assume the randomly generated token is present in an HTTP parameter named _csrf. For example, the request to transfer money would look like this:

POST /transfer HTTP/1.1Host: bank.example.com
Cookie: JSESSIONID=randomid;Domain=bank.example.com;Secure;HttpOnlyContent-Type: application/x-www-form-urlencoded

amount=100.00&routingNumber=1234&account=9876&_csrf=<secure-random>

CSRF Caveats

Timeouts can occur and the token that is stored is no longer available in the session object.  In this case, a 403 would occur as access should be denied to that resource.  Using JavaScript the user can be notified that the session is about to expire and allow the user to extend the session without a timeout occurring. 

Logging in the token should be stored in the session object, so it can be used to determine that the user is actually making the request and not some random hacker.  Cookies should not store the token or it is possible for the hijacker to use the cookie to mask the user authenticity. 

Logging out the token is useful to prevent the user from being logged out of the application also.  So the threat can also be used to prevent a user from performing their work or continual interruption of work.

HiddenHttpMethodFilter

The HiddenHttpMethodFilter should be placed the Spring Security filter. In general this is true, but it could have additional implications when protecting against CSRF attacks.

Note that the HiddenHttpMethodFilter only overrides the HTTP method on a POST, so this is actually unlikely to cause any real problems. However, it is still best practice to ensure it is placed Spring Security’s filters.

Security Http Response Headers

Spring Security easily allows users to inject security headers to protect their applications.

Default Security Headers:

Cache Control

The no-cache directive in a response indicates that the response must not be used to serve a subsequent request i.e. the cache must not display a response that has this directive set in the header but must let the server serve the request. The no-cache directive can include some field names; in which case the response can be shown from the cache except for the field names specified which should be served from the server. The no-store directive applies to the entire message and indicates that the cache must not store any part of the response or any request that asked for it.

Content Type Options

The only defined value, “nosniff”, prevents Internet Explorer and Google Chrome from MIME-sniffing a response away from the declared content-type. This also applies to Google Chrome, when downloading extensions. This reduces exposure to drive-by download attacks and sites serving user uploaded content that, by clever naming, could be treated by MSIE as executable or dynamic HTML files.

HTTP Strict Transport Security

HTTP Strict-Transport-Security (HSTS) enforces secure (HTTP over SSL/TLS) connections to the server. This reduces impact of bugs in web applications leaking session data through cookies and external links and defends against Man-in-the-middle attacks. HSTS also disables the ability for user’s to ignore SSL negotiation warnings.

X-Frame-Options

Provides Clickjacking protection. Values: deny – no rendering within a frame, sameorigin – no rendering if origin mismatch, allow-from: DOMAIN – allow rendering if framed by frame loaded from DOMAIN

X-XXS-Options

This header enables the Cross-site scripting (XSS) filter built into most recent web browsers. It’s usually enabled by default anyway, so the role of this header is to re-enable the filter for this particular website if it was disabled by the user. This header is supported in IE 8+, and in Chrome (not sure which versions). The anti-XSS filter was added in Chrome 4. Its unknown if that version honored this header.

Example of usage:

<http><!– … –>
<headers>
        <cache-control/>
        <content-type-options/>
        <hsts/>
        <frame-options/>
        <xss-protection/>
</headers>
</http>

Custom Headers

The main reason to use custom headers is if a new threat were to arise and the standard is in the works.  Then you can create a customer header to handle such cases.

Session Management

HTTP session related functonality is handled by a combination of the SessionManagementFilter and the SessionAuthenticationStrategy interface, which the filter delegates to. Typical usage includes session-fixation protection attack prevention, detection of session timeouts and restrictions on how many sessions an authenticated user may have open concurrently.

Anonymous Authentication

It is normally a good idea to have a denial by default and allow and disallow user access across the application.  In the case of anonymous login, the user will have access to allowed pages and resources while maintaining security across protected pages.  There would be no difference between an anonymous user and an unauthenticated user. 

Here is a bean example for the anonymous user:

<beanid=”anonymousAuthFilter”class=”org.springframework.security.web.authentication.AnonymousAuthenticationFilter”>
<propertyname=”key”value=”foobar”/>
<propertyname=”userAttribute”value=”anonymousUser,ROLE_ANONYMOUS”/>
</bean>

<beanid=”anonymousAuthenticationProvider”class=”org.springframework.security.authentication.AnonymousAuthenticationProvider”>
  <propertyname=”key”value=”foobar”/>
</bean>

<beanid=”filterSecurityInterceptor”class=”org.springframework.security.web.access.intercept.FilterSecurityInterceptor”>
  <propertyname=”authenticationManager”ref=”authenticationManager”/>
  <propertyname=”accessDecisionManager”ref=”httpRequestAccessDecisionManager”/>
  <propertyname=”securityMetadata”>
    <security:filter-security-metadata-source><security:intercept-urlpattern=’/index.jsp’access=’ROLE_ANONYMOUS,ROLE_USER’/><security:intercept-urlpattern=’/hello.htm’access=’ROLE_ANONYMOUS,ROLE_USER’/><security:intercept-urlpattern=’/logoff.jsp’access=’ROLE_ANONYMOUS,ROLE_USER’/><security:intercept-urlpattern=’/login.jsp’access=’ROLE_ANONYMOUS,ROLE_USER’/><security:intercept-urlpattern=’/**’access=’ROLE_USER’/>
    </security:filter-security-metadata-source>
  </property>
</bean>

Authorization Architecture

All the authorization approaches use a GrantAuthority Object.  By returning a string representation of the object it is easy for it to be read by the AccessDecisionManager.  If it cannot be done then getAuthority() must return null.  If that happens then the AccessDecisionManager will have to support that feature.  Spring provides one approach to GrantAuthority which is GrantAuthorityImpl.  The authentication object will be populated with the information provided by the GrantAuthority.

AccessDecisionManager

The AccessDecisionManager is called by the AbstractSecurityInterceptor and is responsible for making final access control decisions.

The 3 functions included in the AccessDecisionManager are:

void decide(Authentication authentication,Object secureObject,Collection<ConfigAttribute> attrs)throwsAccessDeniedException;

boolean supports(ConfigAttribute attribute);

boolean supports(Class clazz);

The supports configAttribute is used during startup to determine the configuration being passed in will work properly with the AccessDecisionManager. 

The supports class determines whether the configured AccessDecisionManager will support the required secure object.

The decide method is used to determine authorization decisions. 

Hierarchical Roles

In most application it is common to have common roles assigned that distinguish control and access to the user, such as admin and users.  Admin having access to all areas of the application where users only have access to the most common areas.  There are various way one could implement roles assignment so to grant access.  For example, the role admin could be added to the role users so that admin had access to both admin and user access and then only grant authority to users amongst all objects or you could have admin, users assigned access to the objects needed full access to both roles. 

An example of a bean:

<beanid=”roleVoter”class=”org.springframework.security.access.vote.RoleHierarchyVoter”><constructor-argref=”roleHierarchy”/>
</bean>
<beanid=”roleHierarchy”class=”org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl”>
    <propertyname=”hierarchy”>
        <value> ROLE_ADMIN > ROLE_STAFF ROLE_STAFF > ROLE_USER ROLE_USER > ROLE_GUEST </value>
    </property>
</bean>

As you can see in the above example the ROLE_ADMIN has access to 4 roles where ROLE_USER only has 2.

Secure Object Implementations

AOP Alliance Security Interceptor

Method security in enforced using a MethodSecurityInterceptor, which secures MethodInvocations. Depending on the configuration approach, an interceptor may be specific to a single bean or shared between multiple beans.

Bean example:

<bean id=”bankManagerSecurity”
class=”org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor”>
<property name=”authenticationManager” ref=”authenticationManager”/>
<property name=”accessDecisionManager” ref=”accessDecisionManager”/>
<property name=”afterInvocationManager” ref=”afterInvocationManager”/>
<property name=”securityMetadataSource”>
<value>
com.mycompany.BankManager.delete*=ROLE_SUPERVISOR
com.mycompany.BankManager.getBalance=ROLE_TELLER,ROLE_SUPERVISOR
</value>
</property>
</bean>

Aspect J Security Interceptor

The AspectJ interceptor is named AspectJSecurityInterceptor. Unlike the AOP Alliance security interceptor, which relies on the Spring application context to weave in the security interceptor via proxying, the AspectJSecurityInterceptor is weaved in via the AspectJ compiler.

Bean Example:

<bean id=”bankManagerSecurity”
class=”org.springframework.security.access.intercept.aspectj.AspectJSecurityInterceptor”>
<property name=”authenticationManager” ref=”authenticationManager”/>
<property name=”accessDecisionManager” ref=”accessDecisionManager”/>
<property name=”afterInvocationManager” ref=”afterInvocationManager”/>
<property name=”securityMetadataSource”>
<value>
com.mycompany.BankManager.delete*=ROLE_SUPERVISOR
com.mycompany.BankManager.getBalance=ROLE_TELLER,ROLE_SUPERVISOR
</value>
</property>
</bean>       

Expression Based Access Control

Uses a Boolean based logic to allow complex conditions for access control. 

ExpressionDescription

hasRole([role])

Returns true if the current principal has the specified role. This is a synonym for hasAuthority([authority])

hasAnyRole([role1,role2])

Returns true if the current principal has any of the supplied roles (given as a comma-separated list of strings) This is a synonym for hasAnyAuthority([authority1,authority2])

hasAuthority([authority])

Returns true if the current principal has the specified authority. This is a synonym for hasRole([role])

hasAnyAuthority([authority1,authority2])

Returns true if the current principal has any of the supplied roles (given as a comma-separated list of strings) hasAnyRole([role1,role2])``hasAnyRole([role1,role2])

principal

Allows direct access to the principal object representing the current user

authentication

Allows direct access to the current Authentication object obtained from the SecurityContext

permitAll

Always evaluates to true

denyAll

Always evaluates to false

isAnonymous()

Returns true if the current principal is an anonymous user

isRememberMe()

Returns true if the current principal is a remember-me user

isAuthenticated()

Returns true if the user is not anonymous

isFullyAuthenticated()

Returns true if the user is not an anonymous or a remember-me user

hasPermission(Object target, Object permission)

Returns true if the user has access to the provided target for the given permission. For example, hasPermission(domainObject, 'read')

hasPermission(Object targetId, String targetType, Object permission)

Returns true if the user has access to the provided target for the given permission. For example, hasPermission(1, 'com.example.domain.Message', 'read')

An example based on role and ipaddress:

 

<http use-expressions=”true”>
<intercept-url pattern=”/admin*”
access=”hasRole(‘admin’) and hasIpAddress(‘192.168.1.0/24’)”/>

</http>

Method Security Expressions

There are four annotations which support expression attributes to allow pre and post-invocation authorization checks and also to support filtering of submitted collection arguments or return values. They are @PreAuthorize, @PreFilter, @PostAuthorize and @PostFilter.

@PreAuthorize(“hasRole(‘ROLE_USER’)”)
publicvoid create(Contact contact);

@PreFilter(“#c.name == authentication.name”)
publicvoid doSomething(@P(“c”)Contact contact);

@PostAuthorize(“hasRole(‘ROLE_USER’)”)

@PostFilter(“hasPermission(filterObject, ‘read’) or hasPermission(filterObject, ‘admin’)”)
publicList<Contact> getAll();

In conclusion, we reviewed a lot of topic areas covered in Spring Security.  We covered a vary of aspects of security such as securing access to various areas of the application and also threat based security.  Web applications have been focused on access based security and is almost always provided in enterprise applications.  From a threat point of view, we often don’t take as much time to worry about this side of the security concern and it will become in the near future a larger focus for applications, especially those out on the cloud or open to the internet.




This entry was posted in Spring and tagged , , , . Bookmark the permalink.