Software Newsletter      http://www.softwaremag.com/l.cfm?doc=1152-8/2008   Software Journal
   
Software Journal
  Search  
   
   
 
The Software 500
Application Development
Application Focus
Business Intelligence
Customer Relationship
Management
IT Infrastructure
Security
The Business of IT
TECH CENTER
   
  Software Journal  
 

 

Our Partners

http://www.softwaremag.com/SW500CD.cfm?yr=2008
 
eInquiry System
 
 
|   Login to SW500 Survey    |   SoftwareMag Login   |    Register   |
Security
Feature (May 2006)

Authentication and Authorization Are
App Dev Pain Points

by Rudolph Araujo and Mark Curphey

Critical security functions are often left for individual developers to deal with; secure app dev design and review needs to address them from day one.
 

Our experience, based on performing hundreds of application and code reviews, tells us that authentication and authorization—as well as user and session management, which are related—present the bulk of the security issues faced by developers of real-world applications.

We believe the fundamental cause of these problems is the fact that all too often these critical security functions are never considered during the design and other earlier phases in the application development lifecycle. Instead, they are left for individual developers to deal with. This lack of attention can result in practitioners making assumptions, and as a result inconsistencies and perhaps even vulnerabilities are introduced into the application. Moreover, the lack of basic developer security awareness, the need to provide a “quick and dirty” solution, and the absence of a detailed application threat model often results in implementations that use weak mechanisms for authentication and other security functions. Such mechanisms are easily broken, compromising the entire application.

Definitions1

Before we delve into the technical intricacies of some of these topics, it would help to ensure that we are all on the same page with regards to definitions for the terminology that will be used repeatedly throughout this article. This is especially necessary, since a number of these terms are often overloaded, used interchangeably, or out-and-out misused. Some even have different meanings in the physical world.

AUTHENTICATION—This is the process by which a computer, computer program, or user attempts to confirm that the computer, computer program, or user from whom the second party has received some communication is, or is not, the claimed first party.

IDENTIFICATION—Identification is the way in which a user tells a system (or claims) who he or she is (for example, by using a username). The identification component of an access control system is normally a relatively simple mechanism based on either Username or User ID. Authentication, on the other hand, is the process of proving those claims with strong evidence.

EVIDENCE – Evidence is the secret used by an entity in the system—a user or a process—to authenticate itself to the system. For instance, a password is a form of evidence. Under normal circumstances it is assumed that each entity has its own evidence, which must be presented in some form to satisfy the authentication burden.

PRINCIPAL—This represents the entity in the system. All authentication and authorization decisions are tied to the principal. A principal can therefore be an authenticated or an anonymous entity.

AUTHORIZATION—Authorization (or establishment) defines a user’s rights and permissions on a system. After a user (or process) is authenticated, authorization determines what that user can do on the system. While authorization is typically assumed to follow authentication, it is important to bear in mind that in a number of applications—especially web applications on the Internet—the anonymous or unauthenticated user also has certain rights and privileges associated with him or her: for instance, browsing the catalog and adding to the shopping cart.

Given these basic definitions, the rest of this article is divided into two major sections covering authentication and authorization. Our next article will provide more details on related user management and session management issues. For each, we enumerate best practices as well as common mistakes and mis-configurations. We also focus on how to identify some of these anti-patterns while reviewing an application.

Authentication

As mentioned above, authentication is not merely restricted to a user proving his/her identity to a computer—and indeed, current applications use a number of different authentication models. Unfortunately, however, even considering the large body of knowledge that exists with regards to strong authentication protocols, large numbers of applications both on the web and otherwise get it wrong!

One of the biggest mistakes comes when authentication and identification are confused. Perhaps the most illustrative example of this is the use of IP addresses as a strong authenticator. Consider, for example, an online, subscription-based news service. If University X now buys a subscription, the news provider restricts access to all IP addresses owned by that university. However, this could be an entire class B network and a mere 16,777,216 potential nodes. Hence, if even one user within the university runs a web proxy available to external users, the authentication system will be broken. Thus the authentication has moved well beyond the service that truly needs to protect its resources. In this example, each and every customer would need to ensure that no proxies are run, and that if they are run, that they perform strong authentication to restrict proxy to only legitimate users. Another illustration of this is the way in which a number of cell phone providers authenticate access to voice mailboxes based solely on a phone number provided by caller ID2.

Authentication for a web application, in practice, takes the following three forms (see Table 1):

HTTP-based authentication systems (such as HTTP Basic and Digest) are generally regarded as weak. The former practically transmits credentials in the clear. Moreover, in both cases the user is really authenticating to the server rather than to the application. Consequently, with these systems it is also practically impossible to build an elaborate user management scheme, because the user store is beyond the boundaries of the application.

Forms-based authentication is perhaps the most common mechanism in web applications. This authentication scheme requires developers for the most part to implement their own protocols and user management. Hence, it is critical that they adhere to some of the guidelines mentioned later in this document.

Perhaps the biggest risk associated with forms-based authentication schemes is the theft of credentials or session identifiers. All credentials in any form therefore should be transmitted over an encrypted tunnel (SSL/TLS using a minimum 128-bit encryption). Further, it is important to clearly separate public and restricted areas of the website. This prevents the inadvertent transmission of credentials and other sensitive data over a non-secure channel.

Database servers are another common part of a typical application infrastructure, and most databases provide some form of authentication. Unfortunately, authenticating to the database can have some of the same pitfalls as the HTTP-based authentication systems described above. In our experience, very often development teams use such highly privileged accounts as that of the main database administrator (dba/sa) to access the server. This implies that the process now has access to not only your application’s data but also all other data stored on the same server, including database server configuration information and settings. In fact, a number of database-related security issues such as SQL injection are merely bugs that exploit high-privileged environments. In general, when operating with a database server, we always recommend using operating system-based authentication as far as possible to avoid storing credentials in the code or in configuration files. Further, in either case a low-privileged account must be used, as well as separate connection strings and accounts for database reads and writes.

In general, for back-end authentications, hard coding of credentials in the code must always be avoided. This is because such credentials can be trivially discovered by an attacker utilizing tools such as proxies, disassemblers, and debuggers. This is especially true for thick-client applications that are deployed on untrusted end-user machines. These end users have all the time and resources they need to dissect an application and retrieve its secrets. Moreover, one such compromise could spell the doom of any licensing or client-side authentication scheme, because inevitably a “crack” will soon find its way onto the Internet. A common mistake we have seen applications make in this area is to rely purely on client-side authentication, as shown in the figure below. Very often applications will authenticate the user on the client and then employ shared credentials—or perhaps even no credentials—to connect to a remote server. Developers of such applications would do well to consider the impact of an attacker bypassing the client and connecting directly to the server in their threat model.

Choosing a Protocol

As with most other facets of security, application developers are advised to use tried and tested authentication protocols such as Kerberos5. Leveraging the underlying operating system-based authentication is also regarded as a best practice and was illustrated with the discussion over database authentication above.

Most current strong authentication protocols belong to a class known as challenge response. While details of this family of protocols are beyond the scope of this article, it is imperative to consider some of the key benefits they offer:

  • Credentials are never transmitted over the wire.
  • Credentials need not be stored in the clear in the user data store.
  • Most of these protocols support mutual authentication (i.e., the client authenticating itself to the server as well as the server authenticating itself to the client).

Increasingly, however, many organizations are demanding even more stringent authentication mechanisms. Over the last few years, multi-factor authentication has become immensely popular. These schemes have attempted to combine multiple unique facets, such as:

  • Something you know, as in a password or a PIN
  • Something you have, as in a token or a smart card
  • Something you are, as in a biometric quality
  • Somewhere you are, as in geographic coordinates

Perhaps the most common example of this is the smart card, which uses strong, asymmetric key cryptography and the concept of a PKI to enable authentication within an organization. Other examples include your ATM card, RSA SecurIDs, and USB security tokens.

In multi-tiered applications, developers must choose between two fundamentally different models: the trusted subsystem model, or the impersonation/delegation model. The trusted subsystem model relies on the web or application tier to authenticate the end user. Once this has been done, all connections to back-end resources are performed using a common set of credentials. On the other hand, with the impersonation/delegation model, user credentials flow through the system, and hence the web or application server is required to impersonate the logged-on user before attempting to access back-end resources. Each of these has advantages and disadvantages, as summarized in the Table 2.

Operating system support for both these models is prevalent across all modern systems: for instance, Microsoft Windows 2000 and above support delegation. This delegation, however, is unrestricted and provides access to all downstream servers or services. This in itself represents a security threat, and hence Microsoft Windows Server 2003 introduces the notion of constrained delegation6.

With constrained delegation, the administrator can configure the Microsoft Active Directory service to restrict the services and servers that your application can access with the impersonated identity. Constrained delegation, however, does require Kerberos authentication. If your application cannot use Kerberos authentication to authenticate its callers—that is, if your users are authenticating across a restrictive firewall—you can use protocol transition to switch from a different authentication mode, such as forms- or certificate-based authentication to Kerberos, and then use that to access downstream network resources through constrained delegation.

In thick-client applications, development teams must ensure that the authentication is performed on the server side, thus making it more difficult for an attacker. (See Fig. 1.)

With the advent of Microsoft Windows Vista, a new authentication mechanism known as InfoCard7 will make its debut. InfoCard is intended to provide a security-hardened and efficient mechanism for federated identity management. By creating a standard, it hopes to provide a consistent user experience as well as additional benefits such as single sign-on across multiple applications and systems as well as web applications.

Finally, not forgetting component authentication, the most important best practice to always bear in mind in this area is to use strong cryptography for the purpose. Most code authentication schemes, such as Authenticode8, strong naming8, AND JAR signing,10 use hash functions and digital signatures to guarantee authenticity and integrity. It is therefore important that the keys used for this purpose be of sufficient length and entropy as well as being maintained securely to prevent compromise. Best practices surrounding this and other cryptographic concerns were covered in the Winter 2006 article.

Authorization

Authorization, in our experience, is the biggest pain point for application development teams. Along with data validation, which will be discussed in a future article, this represents the category in which we find the most and the highest-risk issues in applications we review. Perhaps the most common issue is the presence of backdoors and the reliance on security through obscurity.

Oftentimes during development, the team will place an “admin cookie” in the code. The code, in turn, checks for this cookie and, if it is found, turns off all security checks (especially authentication) and often logs the user as an administrator. When we have found such issues, we can see that they have not been maliciously injected into the application by the developers. Most often they are placed there purely as shortcuts, so the developers do not have to go through elaborate authentication schemes during unit testing. Many times, however, those developers forget to remove the code before going into production, and as a result what was a relatively harmless “productivity optimization” becomes a nasty backdoor with disastrous consequences. A thorough code review must therefore check for such inadvertent security holes.

Similarly, when it comes to authorization a lot of development teams believe that the phrase “out of sight is out of mind” holds true. This is what we mean by the reliance on security through obscurity. For instance, a number of web applications perform authorization purely on the client side: for example, if a user does not have permission to perform a specific task, then the appropriate menus will not be displayed to him or her. However, the actual operation that performs the task is clearly not protected. Hence, if the attacker can determine the syntax and semantics for directly invoking the operation (either through bypassing the client or by re-enabling the appropriate menus using a proxy), the task can be performed in violation of the business rules. Another illustration of this is the case of applications assuming that specific URL paths will not be discovered—making that the only authorization control in place. What happens most often is that some attacker with plenty of time on his hands or the appropriate URL fuzzing tools will indeed find that path and thus cause a privilege escalation. Consider, for instance, what would happen if your favorite e-commerce site had a /cc_admin virtual directory that, while not advertised publicly, was accessible publicly!

In general, the most common best practice with regards to authorization is the “three-by-three” rule of thumb. This implies checking three attributes—the principal attempting to perform the operation, the resource the operation is being performed on, and the operation itself. In turn, these three attributes should be checked three times—once when the user interface is generated, a second time in the user interface logic on the client side itself, and a third time immediately before executing the operation. Performing the check in the user interface logic on the client side is recommended not necessarily from a security perspective, but to avoid unnecessary server round-trips when legitimate users make innocent mistakes. However, client-side checks should never be a replacement for server-side authorization controls.

It is important that authorization be considered as early in the application development lifecycle as possible. Typically this should be done once all the potential user classes and objects have been identified. Doing it upfront helps create standards for all the developers and assists in assembly of the test plans created by the software QA teams. Moreover, it also prevents developers from making assumptions along the lines of “I thought he/she did the authorization check.”

At Foundstone, we have had tremendous success with authorization modeling to augment regular UML style software modeling. In particular, we have used a tool called SecureUML,[ix] for which we have also developed a Microsoft Visio template. Other techniques, such as UMLSec,[x] have also been documented extensively in academic literature. The use of formal modeling ensures that all concepts are put down on paper and that no unwarranted or unknown assumptions are made by individual developers. And as with traditional modeling, it also helps expose contradictions and backdoors that may have been inadvertently designed into the system.

In formal authorization theory, three fundamental access control models are used in practice. Discretionary Access Control is operator-driven, meaning the owner of the resource determines the permissions on the resource. This is most commonly seen in commercial operating systems through permissions on files, sockets, and other such securable objects. Mandatory Access Control, on the other hand, uses a classification scheme common in government and defense installations to ensure the integrity and confidentiality of primarily data resources. A third hybrid model is Role Based Access Control (RBAC). The major advantage of this model is that it provides for flexible and scalable administration with minimal overheads. RBAC models the system based on real-life roles (e.g., in a banking application one might have roles such as Teller, Customer, Accountant, Account Executive, and Branch Manager). Real-life users are assigned specific roles based on the business. Permissioning on the resources is then done using these roles rather than the users directly. This allows for scenarios (the bank manager being transferred to a different branch, for instance) to be easily implemented, since the permissions are not tied to a specific branch manager but instead to the role of Branch Manager. Thus all that would need to be done in this case is to change the role mapping from the original branch manager to the new one. RBAC also has extensive language level support in JAVA/J2EE using the deploytool, as well as in .NET and COM+ through the System.Security.Permissions namespace and the ObjectContext object, respectively. In fact, in .NET 2.0 a Role Manager API[xi] has been provided, allowing for out-of-the-box support for role-based access control using a provider model. This also includes administration tools and database schemas.

Any authorization scheme is only as secure as it is implemented and deployed. It is therefore critical that developers do not expect the operating system, the system deployer, or the administrator to define access control. Defining file system access control lists (ACLs) is an excellent example of this and must be set by the application itself, potentially during the installation process. Most large database vendors support at least table-level access control. If needed, third-party database shims may be used to extend this farther, to column-level access. In keeping with the role-based approach discussed above, the resources should have ACLs defined using the operating system group and user accounts that the application roles map into.

Least Privilege and Race Condition

No discussion of authorization can be complete without mentioning the cardinal principle of least privilege. Essentially, this principle simply states that an application must run with the least privilege possible, so as to decrease the attack surface. For instance, consider a server application developed in C running as an administrative user. If an attacker is now able to exploit a buffer overflow in this application, he or she will obtain administrative privileges. However, if that server were only running as a low-privileged user, even though the buffer overflow exploit would still succeed, it would provide the attacker with a far less attractive target.

A common way of implementing least privilege is through privilege separation or compartmentalization—the use of impersonation when privileged operations need to be performed. On UNIX systems, for instance, this is commonly done using setuid and/or setgid. Windows similarly has the LogonUser DuplicateToken APIs, which perform similar functions.

When impersonation is used, developers must ensure that the privilege is used for an extremely short and finite duration and for a specific resource. If elevated privileges are needed in multiple parts of the application, then privileges must be raised and dropped separately rather than raising them for an extended period of time. The impact of exceptions when privileges are raised must also be kept in mind. Typically this is best handled using the finally clause to lower privileges, since it will be executed irrespective of whether an exception is raised or not.

Developers must avoid the temptation of using elevated privileges because it makes development easier. There are easy ways to avoid the need for elevated privileges. For instance, the /tmp directory (the All Users profile on Windows) is often world-writable; hence, if temporary files need to be created this is an excellent place to do so, rather than in the application directory (e.g. the Program Files folder) itself, which typically should be only root-writable. The use of a fine-grained permissioning system can also help in encouraging least privileged execution. Interestingly, a number of organizations we have surveyed have had success in this regard by requiring that all developers write code using a low-privileged account. This forces them to make the most secure choices and avoid elevating privileges unless it is absolutely necessary.

Another common issue to watch out for in regards to authorization is a race condition. One common manifestation of such a condition is what is described as the Time of Check – Time of Use (TOCTOU) problem. Developers must ensure that before an authorization decision is made, the application must be able to satisfy itself that the security token it is referencing is the one that is most current and valid, and that it indeed belongs to the user making the request. If there is a significant time lag between check for access and performing an operation, then a malicious attacker may have the opportunity to change the operation to be performed. Perhaps the most common instance of this is when an application uses symbolic links. An attacker can attempt to change the location to which the link points after the access check has been performed. Similarly, if the access check is performed when running in elevated privileges and is not re-done when privileges are lowered, access may be falsely granted to a resource.

Conclusion

In most applications, the mechanisms of authentication and authorization, and related mechanisms for user management and session management (covered in a future article), are the primary line of defense for security. Consequently, they also bear the brunt of most attacks. However, we hope that—just as the other articles in this series have shown—we have made it clear that building security into your applications is not impossible, or even difficult. All that is needed is adherence to best practices and focus from the early stages in an application’s development lifecycle. Where authentication and authorization are concerned, security cannot be added at the end. They represent the core of the application’s architecture and therefore must be part of the design from day one.

Rudolph Araujo is a Principal Software Security Consultant at Foundstone. Rudolph is responsible for creating and delivering the threat modeling and security code review service lines. He is also responsible for content creation and training delivery for Foundstone’s Building Secure Software, Writing Secure Code – ASP.NET and Writing Secure Code – C/C++ class. Araujo has strong computer science fundamentals and more than 10 years of software development experience in C/C++ and C# on both UNIX and Windows environments. He holds a master’s degree from Carnegie Mellon University with a focus on information security. He is also a Microsoft Visual Developer - Security MVP.

Mark Curphey is the founder of the Open Web Application Security Project (OWASP), and is the Vice President of Consulting at Foundstone, now a McAfee company. OWASP, created to help organizations understand and improve the security of their Web applications, publishes a list of Top 10 Web application security vulnerabilities each January. Curphey is the former director of software security for Charles Schwab and has a master’s degree in cryptography. He is also a Microsoft Visual Developer - Security MVP.

1 All definitions are based on those available on http://www.wikipedia.org

2 http://www.freedom-to-tinker.com/?p=709

3 http://web.mit.edu/kerberos/

4 http://msdn.microsoft.com/library/default.asp?url=/library/
en-us/dnpag2/html/paght000024.asp

5 http://msdn.microsoft.com/windowsvista/building/
infocard/default.aspx

6 http://msdn.microsoft.com/workshop/security/
authcode/signing.asp

7 http://msdn.microsoft.com/library/en-us/cptools/html/
cpgrfstrongnameutilitysnexe.asp

8 http://java.sun.com/docs/books/tutorial/deployment/jar/

9 http://www.foundstone.com/index.htm?subnav=resources/
navigation.htm&subcontent=/resources/proddesc/secureuml.htm

10 http://www4.in.tum.de/~umlsec/

11 http://msdn.microsoft.com/library/en-us/dnpag2/
html/paght000013.asp

 
 
 
Related Links
  Table 1: Three Authentication Types

 
  Table 2: Two Trust Models Explained

 
  Buyers Guide:
Secure Application Development Tools & Services


 
  Back to Home Page  
Advertisement
Sign Up for Digital Software Magazine

     
Home |  About Us |  Software 500 |  Editor's Desk |  Subscribe |  Advertise |  Contact Us | 

Copyright © 1999-2010 Software Magazine and King Content Co.
Site Design by Enervision Media
Site Development/Administration by Kunal Panchal