A7 Missing Function Level Access Control

A7 Missing Function Level Access Control

Most web applications verify function level access rights before making that functionality visible in the UI. However, applications need to perform the same access control checks on the server when each function is accessed. If requests are not verified, attackers will be able to forge requests in order to access functionality without proper authorization.

A7.1 Failure to Restrict URL Access:

Enabling URL access control takes some careful planning. Among the most important considerations are:

  • Ensure the access control matrix is part of the business, architecture, and design of the application
  • Ensure that all URLs and business functions are protected by an effective access control mechanism that verifies the user’s role and entitlements prior to any processing taking place. Make sure this is done during every step of the way, not just once towards the beginning of any multi-step process
  • Pay close attention to include/library files. Where feasible, they should be kept outside of the web root. They should verify that they are not being directly accessed, e.g. by checking for a constant that can only be created by the library’s caller
  • Do not assume that users will be unaware of special or hidden URLs or APIs. Always ensure that administrative and high privilege actions are protected
  • Block access to all file types that your application should never serve. Ideally, this filter would follow the "accept known good" approach and only allow file types that you intend to serve, e.g., .html, .pdf, .php. This would then block any attempts to access log files, xml files, etc. that you never intend to serve directly.
  • Keep up to date with virus protection and patches to components such as XML processors, word processors, image processors, etc., which handle user supplied data.

A7.2 Implement ESAPI Access Controller

Based on: http://owasp-esapi-java.googlecode.com/svn/trunk_doc/latest/org/owasp/esapi/AccessController.html

The AccessController interface defines a set of methods that can be used in a wide variety of applications to enforce access control. In most applications, access control must be performed in multiple different locations across the various application layers. This class provides access control for URLs, business functions, data, services, and files.

The implementation of this interface will need to access the current User object (from Authenticator.getCurrentUser()) to determine roles or permissions. In addition, the implementation will also need information about the resources that are being accessed. Using the user information and the resource information, the implementation should return an access control decision.

Implementers are encouraged to implement the ESAPI access control rules, like assertAuthorizedForFunction() using existing access control mechanisms, such as methods like isUserInRole() or hasPrivilege(). While powerful, methods like isUserInRole() can be confusing for developers, as users may be in multiple roles or possess multiple overlapping privileges. Direct use of these finer grained access control methods encourages the use of complex boolean tests throughout the code, which can easily lead to developer mistakes.

The point of the ESAPI access control interface is to centralize access control logic behind easy to use calls like assertAuthorized() so that access control is easy to use and easy to verify. Here is an example of a very straightforward to implement, understand, and verify ESAPI access control check:

try {  ESAPI.accessController().assertAuthorized("businessFunction", runtimeData); // execute BUSINESS_FUNCTION
} catch (AccessControlException ace) {... attack in progress }

Note that in the user interface layer, access control checks can be used to control whether particular controls are rendered or not. These checks are supposed to fail when an unauthorized user is logged in, and do not represent attacks. Remember that regardless of how the user interface appears, an attacker can attempt to invoke any business function or access any data in your application. Therefore, access control checks in the user interface should be repeated in both the business logic and data layers.

<% if ( ESAPI.accessController().isAuthorized( "businessFunction", runtimeData ) )
ADMIN" <%="" "="" macrohasbody="false" wikihasprecedingnewline="false" wikihastrailingnewline="false">
ADMIN" <%="" "="" macrohasbody="false" wikihasprecedingnewline="false" wikihastrailingnewline="false">
       { %> <a href="/doAdminFunction">ADMIN</a> <% } else
NORMAL" <%="" "="" macrohasbody="false" wikihasprecedingnewline="false" wikihastrailingnewline="false">
NORMAL" <%="" "="" macrohasbody="false" wikihasprecedingnewline="false" wikihastrailingnewline="false">
       { %> <a href="/doNormalFunction">NORMAL</a><% } %>

A7.3 Guide to Authorization

Based on https://www.owasp.org/index.php/Guide_to_Authorization

A7.3.1 Principle of least privilege

  • Development, test, and staging environments must be set up to function with the lowest possible privilege so that production will also work with lowest possible privileges.
  • Ensure that system level accounts (those that run the environment) have privileges limited to the greatest degree possible. Web and application servers should never execute as “Administrator”, “root”, “sa”, “sysman”, “Supervisor”, or any other privileged account.
  • User accounts should possess just enough privileges within the application to perform their assigned tasks. These user accounts should be created unprivileged and be given permissions incrementally until they have the full capabilities required. They should not be created with high privileges and then arbitrarily limited.
  • Business user accounts should not be administrator accounts and vice versa. Separate accounts should be used to perform these different sets of tasks even if the same user needs to be able to perform tasks in both realms.
  • Web applications should access the database through one or more limited accounts that do not have schema-modification privileges unless required. If the web application requires the ability to modify the database schema, then the design should be analyzed to determine if and why functionality must be implemented in such a potentially hazardous manner.
  • Database access should be performed through parameterized stored procedures (or similar) to allow all table access to be revoked (i.e. select, drop, update, insert, etc). This should be done using a low privilege database account. This account should not hold any SQL roles above “user” (or similar).
  • Code access security should be evaluated and implemented if possible. If a component only needs the ability to perform DNS queries, it should only be granted the code access permissions to permit this. That way if the code attempts to read from the file system or make arbitrary network connections, this will not be allowed and an error will be raised.
  • Minimize the use of custom authorization code
  • Use built-in platform or framework authorization facilities.

A7.3.2 Centralized authorization routines

A7.3.3 Authorization Matrix

Either use the built in authorization facilities of the framework, or place the call to a centralized authorization check at the beginning of sensitive resource views or actions.

A7.3.4 Controlling access to protected resources

  • Use logical tier separation and patterns such as Model View Controller instead of directly accessing protected resources from the web tier.
  • Ensure that Model code checks to ensure that the requesting user should have access to the protected resource.
  • Ensure that the code requesting the resource has adequate error checking and does not assume that access will always be granted. Failure cases should be accounted for.
  • Ideally generate sensitive content on the fly and send directly to the browser rather than saving to the web server’s file system.
  • If protecting static sensitive content, implement authorization checks to prevent anonymous access.
  • If you have to save to disk (not recommended), use random filenames (such as a GUID) and clean up temporary files regularly.
  • Do not store sensitive static content in web-accessible directory paths. Rather, store this content in non-web accessible directories and proxy access to this content through a handler that will implement proper authorization, logging, and other security functions.. NOTE: Whenever accessing the file system from web-facing code be sure to guard against potential injection attacks.
  • Always prefer to write less code in applications, particularly when frameworks provide presumably high quality and well-tested alternatives.
  • If custom code is required to perform authorization functions, consider fail-safe authentication and exception handling – ensure that if an exception is thrown, the user is logged out or at least prevented from accessing the protected resource or function.
  • Ensure that coverage approaches 100% by default.

A7.3.5 Protecting access to static resources

A7.3.6 Reauthorization for high value activities or after idle out

A7.3.7 Be cautious of custom authorization controls

A7.3.8 Never implement client-side authorization tokens

Many web application developers wish to avoid server-side session storage. Instead, they rely on client-side state maintenance mechanisms such as cookies, hidden form fields, or request/response headers. Often this is misguided when applied to access control and secrets because any information transmitted from the client is open to manipulation unless properly secured using cryptographic techniques.

When your application is satisfied that a user is authenticated, associate the session ID with the authentication tokens, flags or state. For example, once the user is logged in, a flag with their authorization levels is set in the session object.

if ( authenticated ) {
request.getSession(true).setValue("AUTHLEVEL") = X_USER;}

Do not trust any client-side authentication or authorization tokens in headers, cookies, hidden form fields, or in URL arguments unless they have been cryptographically secured via signing or encryption.

  • If your application uses an SSO agent, such as IBM’s Tivoli Access Manager, Netegrity’s SiteMinder, or RSA’s ClearTrust, ensure your application validates the agent tokens rather than simply accepting them, and ensure these tokens are not visible to the end user in any form (header, cookie, hidden fields, etc). If the tokens are visible to the end user, ensure that all the properties of a cryptographically secure session handler are taken into account.

A7.3.9 Never implement client-side authorization tokens

Many web application developers wish to avoid server-side session storage. Instead, they rely on client-side state maintenance mechanisms such as cookies, hidden form fields, or request/response headers. Often this is misguided when applied to access control and secrets because any information transmitted from the client is open to manipulation unless properly secured using cryptographic techniques.

Learn more: