ColdFusion Security Framework


Besides the operating system and Web server security services, administrators also have ColdFusion's security framework available to them. The migration to the Java platform means a change in ColdFusion's security infrastructure. ColdFusion now leverages the JAAS (Java Authentication and Authorization Service).

NOTE

ColdFusion MX introduced a new security framework that completely replaced the Advanced Security system of previous versions. As a result, the following tags and functions are obsolete and will not work in ColdFusion MX: <cfauthenticate>, <cfimpersonate>, AuthenticatedContext(), AuthenticatedUser(), IsAuthenticated(), IsAuthorized(), and IsProtected().However, ColdFusion MX 7 will allow you to create user-defined functions (UDFs) with the same name as these obsolete security functions.


ColdFusion offers security in the following areas:

  • Development. ColdFusion provides password protection for the administrator, and Remote Development Services (RDS) access via Macromedia Dreamweaver, HomeSite+, or ColdFusion Studio 5.

  • CFML. The ColdFusion Markup Language provides several features to augment application security and deployment.

  • Resource. ColdFusion controls access to a subset of tags and functions, data sources, files and directories, and host IP addresses.

  • User. ColdFusion provides user authentication, allowing you to secure application functionality based on a user's role (or group membership).

This portion of the chapter focuses on development and user security. CFML security enhancements are discussed in Chapter 7, and resource security (the server sandbox) is covered in Chapter 9, "Creating Server Sandboxes."

Development Security

ColdFusion's security implementation begins with the ColdFusion Administrator. The Security section of the Administrator allows you to configure the following: the ColdFusion Administrator password, the RDS password, and Resource/Sandbox security. By default, ColdFusion protects Administrator and RDS access with the passwords you enter during installation. The ColdFusion Administrator Password page (Figure 8.24) allows you to disable the ColdFusion Administrator password, or enter and confirm a new one.

Figure 8.24. Use the ColdFusion Administrator Password page to change the Administrator password. To completely disable the password, clear the check box.


Figure 8.25 shows the RDS Password page, which is used to control access to ColdFusion from visual tools (Dreamweaver, HomeSite+, and ColdFusion Studio 5). Disabling RDS security means relying on the Web server and individual database servers for file and data source security.

Figure 8.25. Use the RDS Password page to control the password for Dreamweaver, HomeSite+, or ColdFusion Studio access, or to completely disable the password.


CAUTION

Disabling either the Administrator or RDS password can open devastating holes in your application. Disable the Administrator password only if you are using Web server ACLs for access control to the CFIDE directory and its children. Although Macromedia recommends completely disabling RDS on production systems, you should always enable the RDS password on all systems. For steps to disable RDS, see the "Disabling RDS on Production Servers" section of Chapter 10, "Security in Shared and Hosted Environments."


User Security

User security gives you granular control over your application. This control goes beyond that of the operating system and Web server. The operating system controls local and share access to files and directoriesin other words, NTFS permissions. The Web server's ACLs grant access to files and directories containing code, based upon an authenticated user's credentials. However, neither the Web server nor the operating system allows you to natively extend the system's security framework beyond the page level to the elements within your code (HTML, CFML, images, Web services, and so on). ColdFusion's user security provides the authentication and authorization features that extend access control to the element level, allowing you to programmatically decide what functionality displays in a page.

About Authentication

You should already be familiar with authentication and authorization. Authentication is the process of validating a user's identity. The typical paradigm is a user name/login ID and password stored in a user table of a back-end relational database (RDBMS). A user submits a user name and password via the proverbial login form, and its action page fires a SQL query that matches the user's input with the entries in a user table. Some enterprise solutions replace the RDBMS with an LDAP (Lightweight Directory Access Protocol) user directory such as Microsoft's Active Directory, the Sun ONE/iPlanet Directory Server, or Novell's NDS. Some high-security sites even utilize LDAP and X.509 client certificates, leveraging the Web server's SSL capabilities. ColdFusion provides tags and functions for easy integration with all these solutions.

ColdFusion recognizes two methods of authorization: Web server authentication and application (programmatic) authentication.

  • Web server authentication. Most Web servers support basic HTTP authentication, requiring a valid user name and password to access directories containing application files. When a user requests a page in a secured directory, the Web server presents a login form. If the user's login is successful, the Web server grants access to the directory and caches the authenticated user ID and password to employ on the user's subsequent page requests. We have already described how to configure directory-based authentication methods in IIS, Apache and Sun ONE.

  • Application authentication. Application authentication relies on application code and logic to perform roles-based authentication. In this method, it's the application that displays the login form and authenticates the user against the application's own user directory (usually a database or LDAP). Upon a successful login, the application checks the user's credentials and grants access to the appropriate ColdFusion resources.

About Authorization

In ColdFusion security, authorization ensures that the authenticated user has the appropriate credentials to access resources. Rolesgroup memberships defined in a user directorydictate which users have access to what resources. This is undoubtedly similar to some of the models with which you are already familiar. Consider the personnel structure of a typical Web department:

  • Network administrators

  • Systems administrators

  • Database administrators

  • Web developers

Each individual in the department falls into one of these roles. Each role has access to particular sections of the network infrastructure, database, Web server, and so forth. Indeed, each role has specific responsibilities and duties. Similarly, applications define roles and assign them to users. These roles control what a user can do or can access within the application. Applications then acquire the authenticated user's ID and roles from the user directory at login, storing them for the duration of the user's session.

In ColdFusion, the <cflogin> and <cfloginuser> tags provide the authentication functionality, and the GetAuthUser() and IsUserInRole() functions perform authorization.

Security Tags and Functions

As previously mentioned, ColdFusion includes tags and functions with which to implement security and access control. Table 8.4 describes the new ColdFusion security tags and functions.

Table 8.4. ColdFusion Security Tags and Functions

TAG\FUNCTION

DESCRIPTION

<cflogin>

Provides a container for user authentication code. Used with the <cfloginuser> tag to validate a user login against an LDAP, database, or other user repository.

<cfloginuser>

Identifies the authenticated user to ColdFusion by specifying the user's ID, password, and roles. Requires the name, password, and roles attributes. Specify a comma-delimited list to the roles attribute. ColdFusion evaluates whitespace in this attribute, so be careful not to add spaces after commas.

<cflogout>

Logs the current authenticated user out of ColdFusion by completely removing the user's authenticated ID (session) and roles. When this tag is not used, ColdFusion automatically logs users out when their sessions time out.

<cffunction>

Used only in ColdFusion Components (CFCs). The roles attribute restricts function execution to authenticated users in the specified roles.

<cfntauthenticate>

Authenticates a user name against the Windows domain in which the ColdFusion server is running. This tag can optionally retrieve the authenticated user's group memberships as well. This tag is new in ColdFusion MX 7.

GetAuthUser()

Returns the authenticated user's ID. By default it returns the username value specified in <cfloginuser>; if this is blank, it returns the value of CGI.Remote_User.

IsUserInRole()

Returns true if the authenticated user is a member of the specified roles. Use a comma-delimited list to check multiple role assignments.


Authenticating with <cflogin>

Code all of your authentication logic between <cflogin> tagsincluding database user name/password lookups, Windows authentication, LDAP logins, and so forth. The <cflogin> tag creates a container for storing user security informationthe CFLOGIN scope. This scope contains two variables: CFLOGIN.name and CFLOGIN.password. These two variables are populated with a user's login ID and password when any of the following occurs:

  • A form is submitted containing input fields with the special j_username and j_password names. For example:

     <input type="text" name="j_username"> <input type="password" name="j_password"> 

  • A Macromedia Flash Remoting gatewayConnection object is sent containing the setCredentials() method.

    TIP

    For an example of how to authenticate via Flash Remoting, see Macromedia TechNote 18684, "How to pass login credentials to cflogin via Flash Remoting" at http://www.macromedia.com/go/tn_18684.


  • A request contains an Authorization Header with a user name and password sent via HTTP Basic authentication.

  • A request contains an Authorization Header with a hashed user name and password sent via Digest or NTLM authentication. In this case, CFLOGIN.name contains the username sent by the Web server, but CFLOGIN.password is set to an empty string.

CAUTION

User name and password are sent in cleartext using a simple login form. Flash Remoting sends the user name/password over the binary-encoded AMF (Action Message Format) protocol. HTTP Basic authentication sends the user name and password in a Base64-encoded string with each request. Consider using SSL (HTTPS) to secure the user name and password when authenticating with these methods.


The <cflogin> tag accepts three optional attributes:

  • IdleTimeout. Specifies a maximum time interval for inactivity (the period between page requests) before logging out the user. The default value is 1800 seconds (30 minutes). This attribute is ignored if the loginStorage attribute is set to Session in the <cfapplication> tag or Application.cfc.

  • ApplicationToken. An application-specific identifier used to restrict the CFLOGIN scope to the current application. This defaults to the current application namespecified in the <cfapplication> tag or with the THIS.name variable in Application.cfcand prevents cross-application logins.

    NOTE

    Normally you won't need to specify ApplicationToken; however, ColdFusion allows unnamed applications for J2EE compatibility. ColdFusion uses the ApplicationToken value to help keep the user's login valid for only the current directory and its subdirectories. To secure code in other directories, the application name must be identical to the ApplicationToken value.


  • CookieDomain. Specifies the domain for which the login cookies are set. This prevents cross-site cookie attacks and is useful in clustered environments.

If authentication is successful, specify the authenticated user's user ID, password, and roles to the <cfloginuser> tag to log the user into the ColdFusion application. The GetAuthUser() function returns the user ID specified in <cfloginuser>.The IsUserInRole() function checks the specified role against the list of roles specified in <cfloginuser>.

TIP

If Web server security is used instead of ColdFusion security (CFLOGIN), GetAuthUser() returns the value of CGI.Remote_User, which is set by the Web server. If using both Web server security and CFLOGIN, pass the web server's authenticated user ID (for instance, CGI.Remote_User or CGI.Auth_User) to the <cfloginuser> name attribute to keep Web server security and ColdFusion security in synch. The IsUserInRoles() function requires <cfloginuser>.


Storing Login Information

Login credentials are stored either in a cookie or in the Session scope, as determined by the LoginStorage value as either an Application.cfc initialization variable or in the <cfapplication> attribute. By default, <cflogin> sets a nonpersistent cookie in the user's browser, called cfauthorization_applicationName. The cookie value is a Base64-encoded string containing the user ID, password, and application name. This in-memory cookie is not written to disk (for example, the cookies.txt file) and is destroyed when the browser closes.

Because ColdFusion sends this cookie with every request, users must allow in-memory cookies in their browsers. If the browser disables cookies, then the effect of the <cfloginuser> tag exists only for the current page request. In this scenario, ColdFusion allows you to code the <cfloginuser> outside of the <cflogin> tag in every template you want to secure, in order to persist the login information across page requests.

When storing login information in the Session scope, ColdFusion stores the Base64-encoded user ID, password, and application name in the SESSION.cfauthorization variable. ColdFusion stores this variable in its internal memory space and uses the browser's session cookies (CFID and CFTOKEN, or JSESSIONID) for user identification. This is more secure than using cookies for login storage because ColdFusion does not pass SESSION.cfauthorization with every page request. The user's login and session share the same timeout valueand ColdFusion ignores the IdleTimeout <cflogin> attribute.

To use the Session scope to store login information, ensure the following:

  • Session Management is enabled in the ColdFusion Administrator

  • Session Management is enabled in the Application.cfc or <cfapplication>

  • LoginStorage=Session is specified in either the Application.cfc or <cfapplication>

TIP

With SetDomainCookies enabled in Application.cfc or <cfapplication>, the SESSION.cfauthorization login variable is available to all members in a server cluster.


Best Practice: ColdFusion Sessions and CFLOGIN

Session scope variables are held in ColdFusion memory space. Storing the CFLOGIN authorization variable (SESSION.cfauthenticate) in the Session scope (LoginStorage=Session) will persist the value for the duration of the user's session. If the user closes the browser without logging out with CFLOGOUT, the authorization value will still persist in ColdFusion memory until the Session scope is cleared when the session times out or the server is restarted. If another user logs in with the same Session ID (CFID and CFTOKEN or JSESSIONID) as the authenticated user, that user can impersonate the previously authenticated user.

ColdFusion identifies browser sessions by cookies and URL parameters. A ColdFusion Session ID comprises the CFID, CFTOKEN, and Application name (applicationname_CFID_CFTOKEN). When J2EE Sessions are enabled, the Session ID is the JSESSIONID value. A ColdFusion session can be impersonated by passing existing Session ID values on the URL or in cookies.

The following are best-practice steps to prevent session impersonation:

  • Enable J2EE session management and use JSESSIONID:

    • JSESSIONID is a random-generated string created as a nonpersistent cookie.

    • Use GetPageContext().GetSession().InValidate() to clear J2EE Session data, including the login information (SESSION.cfauthenticate).

  • For ColdFusion session management:

    • Use a UUID for CFTOKEN. Enable UUID for CFTOKEN in the ColdFusion Administrator Settings page.

    • Ensure CFID and CFTOKEN are created as nonpersistent values. See Macromedia TechNote 17915 at http://www.macromedia.com/go/tn_17915.

    • Do not allow Session variables to pass on the URL. These values are not browser specific like cookies.

    • When logging out the user, ensure that <cflogout> is called as well as StructClear(Session). StructClear(Session) clears all session variables except the SESSIONID and SESSION.cfauthenticate values.

    • Use the OnSessionStart method in the Application.cfc to clear any existing SESSIONID values (from URL or cookie).

    • Call <cflogout> in the OnSessionEnd method to ensure the logged in user is logged out when the session ends.

Logging Out

There are several ways to log out a user and remove their login information from ColdFusion. The primary method is to use the <cflogout> tag. ColdFusion MX did a poor job of destroying session information after a user logged out. Table 8.5 lists the circumstances in which ColdFusion logs out the current user and destroys the <cfloginuser> authentication credentials.

Table 8.5. ColdFusion User Logout

DESCRIPTION

LoginStorage=Cookie

LoginStorage=Session

Application fires <cflogout>

X

X

The <cflogin> IdleTimeout value is reached

X

N/A

The user closes all browser windows

X

N/A

The ColdFusion session ends

N/A

X


CAUTION

<cflogout> does not clear the login information if you authenticate users via Web server security or the HTTP Authorization header. These security paradigms continue to send authentication information to ColdFusion until all browser windows are closed. Therefore, until all browser windows are closed, the CFLOGIN scope may persist beyond user logout, providing a window of opportunity for another user to impersonate the first user.


Executing <cflogout> when using LoginStorage=Session removes the SESSION.cfauthorization variable from the Session scope, but does not end the current user's session. Therefore, if you want to log the user out and completely clear their session, you must code logic that calls <cflogout> and StructClear(Session):

 <cfif IsDefined('URL.Logout') and URL.Logout>   <cflogout>   <cfset StructClear(Session)> </cfif> 

TIP

Calling StructClear(Session) will not generate a new session id but it will completely empty the SESSION structure.


Basic ColdFusion Login Example

The following code demonstrates a single-page login mechanism. Three templates are involved: Application.cfm, loginForm.cfm, and index.cfm. The loginForm.cfm template contains a simple login formuser name and password fieldsthat passes the special j_username and j_password to the <cfloginuser> tag in the Application.cfm. The user must authenticate with the login form in order to access the index.cfm. The Application.cfm contains all the authentication and authorization logic in the body of <cflogin>. Listings 8.1 through 8.3 display this basic login code example (using "admin" and "password" for the username and password, respectively).

Listing 8.1. Application.cfm

[View full width]

 <cfsilent> <!---####  File name: Application.cfm  Description: Demonstrates coldfusion user security with <cflogin>, <cfloginuser>, and  <cflogout> Tags.  Assumptions: None  Author name and e-mail: Sarge (ssargent@macromedia.com)  Date Created: July 24, 2002  Change Log: Updated February 20, 2005 ####---> <cfapplication name="OWS" sessionmanagement="yes" sessiontimeout="#createTimeSpan(0,0,0 ,30)#" loginstorage="cookie"> <!---#### Display a nice title in the browser title bar ####---> <cfhtmlhead text="<TITLE>ColdFusion: User Security Test</title>"> <!---#### Set a REQUEST variable to check the login status. ####---> <cfparam name="REQUEST.loggedin" default="true" type="boolean"> <!---#### If the logout URL variable is passed, log off the current user, clear the  session, and set the login status to false, then return the user to the login screen. ####---> <cfif IsDefined('URL.logout') and URL.logout>  <cflogout>  <cfset StructClear(Session)>  <cfset REQUEST.loggedin = "false">  <cfinclude template="loginform.cfm"><cfabort> </cfif> <!---#### Call <cflogin> to create the CFLOGIN scope/container. Idle timeout is set to 30  minutes or 1800 seconds. ####---> <cflogin idletimeout="1800">   <!---#### CFLOGIN.name and CFLOGIN.password automatically assume the j_username and  j_password values from the login form. If you use    some other field naming conventions, you will have to manually set CFLOGIN.name and  CFLOGIN.password equal to the corresponding    values. ####--->   <cfif IsDefined("CFLOGIN.name") and Len(Trim(CFLOGIN.name)) and Len(Trim(CFLOGIN.password))>     <!---#### Authenticate the user. For this example, the only valid user is "admin,"  whose password is "password." CompareNoCase will     return a zero (0) if the two strings are identical. ####--->     <cfif not CompareNoCase('admin', Trim(CFLOGIN.name)) and not CompareNoCase(Trim (CFLOGIN.password), "password")>       <!---#### Pass the authenticated user's name, password, and role to <cfloginuser>,  and set login status to true ####--->       <cfloginuser name="#CFLOGIN.name#" password="#CFLOGIN.password#" roles="admin">       <cfset REQUEST.loggedin = "true">     <cfelse>       <!---#### if the login fails, set bad login notice, set login status to false, and  return to the login form. ####--->       <cfset REQUEST.badlogin = "true">       <cfset REQUEST.loggedin = "false">       <cfinclude template="loginform.cfm"><cfabort>     </cfif>   <cfelse>     <!---#### If no login is provided, set login status to false and return to the login  form. ####--->     <cfset REQUEST.loggedin = "false">     <cfinclude template="loginform.cfm"><cfabort>   </cfif> </cflogin> </cfsilent> 

The Application.cfm checks to see if a user is logged in, and redirects the request to the login page (loginform.cfm) if needed.

Listing 8.2. loginForm.cfm

[View full width]

 <cfsetting enablecfoutputonly="yes"> <!---####  File name: loginForm.cfm  Description: Login form for the ColdFusion user security example.  Demonstrates how to use the special j_username and j_password field names for the  <cflogin> tag.  Assumptions: None  Author name and e-mail: Sarge (ssargent@macromedia.com)  Date Created: July 24, 2002  Change Log: Updated February 20, 2005 ####---> <cfsetting enablecfoutputonly="no"> <!doctype html public "-//w3c//dtd html 4.01 transitional//en"> <html> <body> <p>Please enter your login information:</p> <!---#### If the user submits a bad login, display a friendly message ####---> <cfif IsDefined('REQUEST.badlogin')><span style="color: red">Your login information was  invalid!</span></cfif> <!---#### Use cfform to provide client-side javascript validation on the user name form  field. ####---> <cfform action="index.cfm" method="post"> <table border="0">   <tr>     <td>User Name:</td>     <td><cfinput type="text" name="j_username" message="You must enter a user name!"  required="yes"></td>   </tr>   <tr>     <td>Password:</td>     <td><cfinput type="password" name="j_password" message="You must enter a password!"  required="yes"></td>   </tr>   <tr>     <td>&nbsp;</td>     <td><input type="reset"> | <input type="submit" name="logon" value="Login"></td>   </tr> </table> </cfform> </body> </html> 

The loginForm.cfm template contains the actual form that submits the user name and password. These are processed by the Application.cfm when the form is submitted. The code in Application.cfm will allow processing to continue with index.cfm if authentication is successful; otherwise, the login form will redisplay.

Listing 8.3. index.cfm

[View full width]

 <cfsetting enablecfoutputonly="yes"> <!---####  File Name: index.cfm  Description: Index page secured by <cflogin> in the Application.cfm. This  page also shows how to use the ColdFusion security functions:  GetAuthUser() and IsUserInRole.  Assumptions: None  Author name and e-mail: Sarge (ssargent@macromedia.com)  Date Created: July 24, 2002  Change Log: Updated February 20, 2005 ####---> <cfsetting enablecfoutputonly="no"> <!doctype html public "-//w3c//dtd html 4.01 transitional//en"> <html> <body>   <!---#### Use the GetAuthUser function to display the authenticated id ####--->   <p><b>Welcome, <span style="color: green"><cfoutput>#GetAuthUser()#</span> </cfoutput>!< /b></p>   <!---#### Use the IsUserInRole function to add conditional logic based on the user's  group membership (role). ####---> <cfif IsUserInRole("admin")>   <p>Based on your login ID, you are permitted to access this section of the site.</p> Please proceed to the <a href="index.cfm" title="This link is for demonstration purposes  only">Administrator's section</a>.   <!---#### Display the log out link. ####--->   <p><a href="index.cfm?logout=yes">Log Out</on></p> </cfif> </body> </html> 



Advanced Macromedia ColdFusion MX 7 Application Development
Advanced Macromedia ColdFusion MX 7 Application Development
ISBN: 0321292693
EAN: 2147483647
Year: 2006
Pages: 240
Authors: Ben Forta, et al

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net