7.12 Security

In this section, we address the various security aspects of using Flash Remoting with Java. Application security is a broad topic in Java and encompasses many aspects of Java application development. There are user authentication and authorization systems for managing individual user access to protected application features. There are the Container-Managed Security features of a J2EE application server that manage method-level access to EJBs and user authentication security constraints in the servlet container. There are also the core Java security features that manage system resource, class, and method access within the JVM (Java Virtual Machine). There are the security features provided by specific technologies, such as web services. Finally, there is the fuzzy task of trying to guess how malicious users might try to attack the system and plugging the holes before they are exploited.

7.12.1 User Authentication and Authorization

Authentication is the process of identifying a user or entity accessing a system. This is usually implemented with a login process that requires a user to provide a username and password. Authorization is the process of determining the privileges of an authenticated user. Authorization may be implemented with custom application logic or using configuration in a J2EE application server to restrict access to resources based on the user's role.

7.12.1.1 Container-Managed Security

When used with JRun, Flash Remoting clients can provide user credentials using NetConnection.setCredentials( ), as shown here (note that the call to NetServices.createGatewayConnection( ) returns a NetConnection object):

var gatewayConnection = NetServices.createGatewayConnection( );
gatewayConnection.setCredentials("username", "password");

The user is authenticated by JRun when the Remoting gateway handles service method calls. JRun uses the user role to authorize access to EJBs and other container-managed resources.

When not running in JRun, applications using Container-Managed Security may have users log in through an HTML interface or have Flash communicate directly with the security service of the application server exposed through the standard j_security_check form action.

The following example shows a function, cmLogin( ), that submits an HTTP POST request to the application server's authentication service. The j_security_check portion of the URL, "http://localhost:8400/remotingbook/j_security_check", and the request parameters, j_username and j_password, are dictated by the Container-Managed Security portions of the Servlet 2.3 specification. We are essentially using Flash to mimic submitting an HTML form tied into the form-based login of the container as specified and standardized by the Servlet 2.3 specification:

// Function to handle container-managed login
function cmLogin (username, password) {
  // Create the object to load the url
  var loader = new LoadVars( );
  loader.j_username = username;
  loader.j_password = password;

  // Create the target to handle the result
  var target = new LoadVars( );
  target.onLoad = function (result) {
    trace("cmLogin.onLoad: " + result);
  };

  // Log in against the container's j_security_check.
  loader.sendAndLoad("http://localhost:8400/remotingbook/j_security_check",
                     target);
}

For more information on using standard form-based login with Container-Managed Security, see http://www.onjava.com/pub/a/onjava/2001/08/06/webform.html or the books Java Servlet Programming and JavaServer Pages (both from O'Reilly).

Once a user is logged in, the container makes a java.security.Principal object and role available for performing authorization checks. This information is available through the two methods HttpServletRequest.getUserPrincipal( ) and HttpServletRequest.isUserInRole( ). Section 7.9 explains techniques for gaining access to the user request so that Remoting services can access the container-managed authentication and authorization information.

With an authenticated user, the servlet container will use the user's information when authorizing use of other container-managed resources, such as EJBs and security constraints configured in the application's web.xml file. To restrict access to the Remoting gateway to only logged-in users, add a security constraint to your application's web.xml file as shown in the following example. Replace rolename with the name of a role that you have defined in your application and wish to have access to Remoting services.

<security-constraint>
  <web-resource-collection>
    <url-pattern>/gateway</url-pattern>
    <auth-constraint>
      <role-name>rolename</role-name>
    </auth-constraint>
  </web-resource-collection>
</security-constraint>
7.12.1.2 Home-grown systems

Home-grown authentication and authorization systems range widely in implementation and complexity. Most rely on storing information in the user session. Section 7.9 and Section 7.10 earlier in this chapter explain techniques for accessing the user session from Remoting services that can be used to support custom authentication and authorization.

For tasks such as limiting access to the Remoting gateway based on user information, a servlet filter that can deny access based on your own custom criteria and is mapped to the gateway URL is an appropriate solution.

7.12.1.3 Service authentication

Authentication in service-oriented architectures is a topic of much discussion, especially as it relates to SOAP-based web services. Many developers believe that services should handle authentication and authorization for every service method call. Applied to Flash Remoting, this approach requires that the Flash client provide the user credentials for every service method call. The service method authenticates the user according to the provided credentials every time a Flash client invokes it.

While authenticating the user every time may seem like overkill, it makes it easier to write standalone services that are not dependent on the application server or other application code to authenticate users. If a service needs to know about the user in order to run, it looks up the user using her credentials and continues.

7.12.2 Restricting Service Access

Flash Remoting is essentially a servlet that uses introspection to invoke methods on a class in the application server. The class and method are both named by the Flash client. A Flash client can invoke any method through the Flash Remoting gateway on any class in the application server that has a no-argument constructor.

This arrangement gives the client a great deal of power over what classes are instantiated on the server side. A malicious user could write a Flash client to manipulate the server state, access internal information about the server and application, or use up all the server memory by using classes in the application server or application. While all classes with no-argument constructors are vulnerable to this exploit, the ones of greatest concern are classes with easily accessible documentation. The application server classes and standard Java classes fit this profile. A malicious user can easily find out what classes are available in any application server or Java distribution by reading the documentation available online.

A simple exploit of this vulnerability is shown in the following example. In this example, the Flash client connects to java.util.ArrayList as a Remoting service from a Flash client through Flash Remoting and invokes ArrayList.addAll( ) in an infinite loop. This is basically a denial of service attack, which will fill up the available memory of the application server. Before long, it will crash the JVM running the application server:

// Use java.util.ArrayList as a JavaBean service.
var service = gatewayConnection.getService("java.util.ArrayList", this);

// Build a nice big list of strings.
var list = new Array( );
for (var i = 0; i < 100; i++) {
  list.push("Let's eat memory");
}

// Add the list forever.
this.onEnterFrame = function ( ) {
  for (var i = 0; i < 100; i++) {
    service.addAll(list);
  }
};

Other, more sophisticated exploits may use application server classes as services to change the state of the running server or access protected information. The following sections outline defensive measures you can take against certain types of attacks.

7.12.2.1 Use Java security

Flash Remoting does not provide a mechanism to restrict Flash client access to specific services. Macromedia recommends restricting access to services by enabling the Java security manager for your application server and editing the Java security policy to allow only the Remoting gateway to access your service classes.

The Java security manager is responsible for enforcing the security policy for an application. A security policy is a collection of permissions that are defined in a security policy file or in code. See Sun's security documentation at http://java.sun.com/j2se/1.4/docs/guide/security/index.html or Java Security by Scott Oaks (O'Reilly) for complete coverage of configuring security in Java.

Refer to your application server's documentation for information on enabling the Java security manager for your application and for the location of the security policy file it uses. Some application servers install with the Java security manager already enabled, in which case you probably need to give the Flash gateway access to your service classes to use Flash Remoting at all. For example, in an installation of IBM WebSphere with the security manager enabled, grant clients permission to access the package that contains the service class by adding a line to the default permissions granted to all domains in the websphere_root/AppServer/java/jre/lib/security/java.policy file. For example, the following line lets users access the Flash Remoting sample classes in the my.services package:

permission java.lang.RuntimePermission "accessClassInPackage.my.services"

A properly configured security policy will prevent the Remoting gateway from accessing the classes that it does not need to access in the application server, core Java libraries, and your application.

Unfortunately, using the Java security manager to limit service access has its limitations. Most application servers do not install with the security manager enabled, because it degrades performance and introduces configuration hassles for developers. The security manager degrades performance because it has to check permissions for almost everything that happens in the JVM. The extent of the performance degradation depends on the application server. It is usually from 1 to 10%.

Configuring a security policy can be a tricky task. Simply enabling the security manager and finding the right location for the security policy file may require digging into the depths of your application server documentation. Editing a policy file requires a good understanding of the behavior of the Java security manager and the range of security threats to your application and application server. Testing the security policy configuration and ensuring that it does not prevent other aspects of your application from running correctly also add complexity to your development process.

The final limitation to using the Java security manager to limit service access is that you cannot write a security policy that prevents the gateway from using the core Java libraries as services, because the gateway needs them to operate correctly. A security policy file cannot distinguish between classes used in the gateway Java code and classes invoked by the gateway as services. So, the ArrayList exploit discussed earlier is still available.

7.12.2.2 FlashGatekeeper

In the process of writing the security section of this chapter, I became increasing frustrated with the available options for restricting service access through the Remoting gateway. The security manager solution recommended by Macromedia is inadequate. It is hard to implement and does not address all of the issues.

Java developers using Flash Remoting need a simple solution for limiting service access to the services they have created. The solution should forbid all service access except those explicitly indicated by the developer. Flash Remoting for J2EE should provide such a solution but it does not. So, I created one and I describe it here.

The solution is a Servlet 2.3 filter implementation called FlashGatekeeper. FlashGatekeeper is documented and available as an open source project at http://carbonfive.sourceforge.net/flashgatekeeper. FlashGatekeeper uses classes that come with the Flash Remoting flashgateway.jar file to inspect the AMF message sent by the Flash client. It extracts information about the services that the Flash client is trying to invoke and determines if the services are allowed based on the FlashGatekeeper configuration.

If a Flash client tries to invoke a service that is not allowed by FlashGatekeeper, FlashGatekeeper writes details about the Flash Remoting request to the application server's log files and returns a standard 403 Forbidden HTTP header. If the service is allowed, FlashGatekeeper allows the request to continue on to the Flash Remoting gateway.

FlashGatekeeper installs as a JAR file in your application's WEB-INF/lib directory. Configure FlashGatekeeper in your application's WEB-INF/web.xml file as a servlet filter mapped to the URL of the Flash Remoting gateway servlet. If the Remoting gateway is mapped to /gateway, configure the FlashGatekeeper filter as follows:

<filter>
  <filter-name>GatekeeperFilter</filter-name>
  <filter-class>com.carbonfive.flashgateway.security.GatekeeperFilter
    </filter-class>
  <init-param>
    <param-name>config-file</param-name>
    <param-value>flashgatekeeper.xml</param-value>
  </init-param>
</filter>

<filter-mapping>
  <filter-name>GatekeeperFilter</filter-name>
    <url-pattern>/gateway</url-pattern>
</filter-mapping>

FlashGatekeeper looks for its configuration file in the classpath of your web application. In this example, you should put flashgatekeeper.xml in WEB-INF/classes or in another directory in your web application's classpath. The FlashGatekeeper configuration file is an XML description of permitted services and service methods. The configuration allows for identifying several services by using a package name instead of a class or using a JNDI context instead of an object in JNDI.

A sample flashgatekeeper.xml configuration file follows:

<config>
  <service>
    <name>com.oreilly.frdg.java.service</name>
    <method>
      <name>*</name>
    </method>
  </service>
  <service>
    <name>com.oreilly.frdg.java.FlashService</name>
    <method>
      <name>serviceMethod</name>
    </method>
  </service>
  <service>
    <name>remotingbook</name>
    <method>
      <name>*</name>
    </method>
  </service>
  <service>
    <name>java:comp/env/ejb</name>
    <method>
      <name>*</name>
    </method>
  </service>
</config>

This configuration file allows access to only services in or below the package com.oreilly.frdg.java.service, the service method implementation com.oreilly.frdg.java.service.FlashService.serviceMethod( ), servlet services in the remotingbook web application, and any EJB services in JNDI under java:comp/env/ejb.

In addition to restricting access to services by service name and service method, FlashGatekeeper supports restricting service access by user role, as determined by Container-Managed Security. For detailed information on FlashGatekeeper configuration and features, refer to the FlashGatekeeper web site.



    Part III: Advanced Flash Remoting
     
    ASPTreeView.com
     
    Evaluation has ЩјіКіМИёѕµЙexpired.
    Info...