OWASP Top Ten Project 2013 No 7 – Missing Function Level Access Control

Missing Function Level Access Control

Pipeline Access

Requests to an Intershop system are usually handled by the following components in the following order:

  1. Web Server
  2. Web Adapter
  3. Application Server Servlet
  4. Application Server Pipeline

Not all component must be involved with every request, e.g. the Web Adapter responds with a cached paged, making the Application Server Servlet and Pipeline execution obsolete.
But as a last consequence functionality of the web application is mapped/implemented by pipelines, thus the access to those must be controlled.

Call Mode “private”

Each start node of an Intershop Commerce Management Pipeline has a call mode setting that can be changed using Intershop Studio. This call mode setting can be private or public:

  • private – If the call mode is set to private, the Pipeline cannot be executed directly over HTTP. It is only callable from another Pipeline by using a call node or a jump node. Alternatively, the Pipeline can be executed by an Intershop job.
  • public – The Pipeline execution is not limited. Besides the ways described above, it can also be called over HTTP. If a pipeline has multiple start nodes, the call mode has to be set for each start node individually.

By setting the call mode it is not possible to configure specific access control for different users.

Centralized Pipeline Access Control

The CorePrefix pipeline is a prefix Pipeline which is provided as a default. The Pipeline checks if a user has the required permission to run a called Pipeline. This is, basically, a two-step process:

  • First, the CorePrefix Pipeline determines the permissions that are required to execute the called Pipeline at the specified Start Node in the given site context.
  • Then, it checks whether the current user’s permissions match the previously determined permissions. If so, the called pipeline will be executed; if not, the execution is denied and an error page will be displayed.

For each pipeline, access control lists define the permissions a user needs to execute this pipeline in general, or a specific start node of this pipeline. Every cartridge or site that has pipelines provides a pipelines-acl.properties file, located in

  • $IS_HOME/share/system/cartridges/<cartridge_name>/release/pipelines for cartridge pipelines, or
  • $IS_HOME/share/system/sites/<site_name>/<active_dir>/pipelines for pipelines directly bound to a specific site.

The pipelines-acl.properties file(s) includes the access control list (ACL) for every pipeline of the cartridge or site whose access should be restricted.
These access control lists are loaded into the pipeline cache upon server startup or pipeline reload.

General Pipeline Security

Since pipeline execution can be triggered from external sources via an URL, special care is necessary to secure pipelines, making sure that a pipeline responds only to requests from authorized clients.

Public, Private and Include Start Nodes

The configuration parameters for a start node include the call mode parameter. The call mode determines whether a pipeline can be triggered from an external source using HTTP requests, or from an internal source only using call or jump nodes. The call mode parameter for start nodes can take the following values:

  • Public for access from an external source such as the storefront, using (for example) HTTP requests.
<a href=“#URL(Action(‚ViewHomePage-Start‘))#“>…</a>
  • Such a public request allows only to call a public start node.
  • Include for access via remote include calls (Web Adapter includes, <WAINCLUDE>).
<isinclude url=“#URL(Action(‚PipelineXyz-Start‘)#”>
  • An included request allows to call a public or an include start node.
  • Private for access from an internal source such as another pipeline, using call or jump nodes.
<ispipeline pipeline=”ProcessPagelet-TemplateCallback” params=”#ParamMap#”>
  • An internal request allows to call a public, an include or a private start node.

For example, many viewing pipelines are triggered by external sources via HTTP requests, hence need to have a public start node. On the other hand, processing pipelines are typically called from viewing pipelines. Therefore, processing pipelines typically have private start nodes.

Prefix Pipelines

Prefix pipelines are generic pipelines which perform certain checks before the pipeline that has actually been requested is executed. Prefix pipelines therefore provide a powerful mechanism to prevent unauthorized access to public pipelines.

Intershop 7 supports so-called site prefix pipelines. The site preference value SitePrefixPipeline specifies the name of a pipeline which is automatically called before any public pipeline in the site is executed. The default value is set to the CorePrefix pipeline. See the figure below for details on this pipeline.

The pipelet processor checks the SitePrefixPipeline preference value only once, the first time a pipeline in the site is executed. The SitePrefixPipeline preference value is re-read only if the pipelines of the site or all pipelines in the system are reloaded.

If a pipeline is executed and the site’s SitePrefixPipeline preference value contains a prefix pipeline name, the prefix pipeline is looked up in the normal manner and is then executed. This also means that a prefix pipeline can be overloaded in the usual way.
Different versions of the prefix pipeline can be defined using the start nodes:

  • process
  • view, or
  • backoffice

These different versions are executed depending on the type of the pipeline (ProcessView, or Backoffice) triggering the prefix pipeline.

For example, if the original pipeline being executed is of type Process, a start node process is searched for in the prefix pipeline. If the system cannot find one, the pipelet processor looks for a default start node named Start. The name of the originally called pipeline and the start node name are put into the prefix pipeline dictionary using the CurrentPipelineName and CurrentStartNodeName keys.

The pipeline type is stored in the pipeline’s XML descriptor file. By default, the pipeline types are stored in lower case letters (e.g., <type>process</type>. Since the pipeline lookup mechanism is case sensitive, the respective prefix pipeline start nodes must be lower case as well.

The pipeline type is stored in the pipeline’s XML descriptor file. By default, the pipeline types are stored in lower case letters (e.g., <type>process</type>. Since the pipeline lookup mechanism is case sensitive, the respective prefix pipeline start nodes must be lower case as well.

The originally called pipeline is not executed after the site prefix pipeline if the following happens:

  • The site prefix pipeline ends with an interaction.
  • The site prefix pipeline ends with an exception, in which case the error handler of the site prefix pipeline is looked up and executed

If the site prefix pipeline ends with a named end node, the originally called public pipeline is executed. The SitePrefixEndNodeName value of the site prefix pipeline is passed to the dictionary. The values of the site prefix pipeline dictionary are available to the original pipeline as well.

CorePrefix Pipeline

The CorePrefix pipeline is a prefix pipeline which is provided as a default. The pipeline checks if a user has the required permission to run a called pipeline. This is, basically, a two-step process:

  • First, the CorePrefix pipeline determines the permissions that are required to execute the called pipeline at the specified start node in the given site context.
  • Then, it checks whether the current user’s permissions match the previously determined permissions. If so, the called pipeline will be executed; if not, the execution is denied and an error page will be displayed.

The permissions themselves are configured in the pipelines-acl.properties file, located in the pipeline directory of every cartridge, and pre-loaded during the pipeline cache initialization.

Pipeline Access Control Lists

If a pipeline requires a permission of the requester to execute the pipeline in general, or a specific start node of this pipeline, the pipeline’s cartridge contains a pipelines-acl.properties file. The pipelines-acl.properties file includes the access control list (ACL) for every pipeline of the cartridge or site whose access should be restricted. These access control lists are loaded into the pipeline cache upon server startup or pipeline reload.
The pipelines-acl.properties located in

  • <IS_HOME>\share\system\cartridges\<cartridge_name>\release\pipelines
    for cartridge pipelines, or
  • <IS_HOME>\share\system\sites\<site_name>\1\pipelines
    for pipelines directly bound to a specific site.

ACL Lookup Process

As pipelines are always executed within a site context, the common pipeline lookup and overload mechanism must apply to the ACL lookup as well. The following steps are performed:

  1. all available sites in the system are determined
  2. the site specific ACLs are read from the pipeline-acl.properties located in the site’s pipeline directory and stored into the site pipeline cache
  3. the cartridges that are currently loaded in the given site are determined
    The order within the list of cartridges bound to a site is relevant. The system sequentially searches for cartridge resources in a top-down manner, starting with the first cartridge in the list.
  4. For each cartridge in the list, the pipeline ACLs are loaded sequentially.
    Since a cartridge can be loaded in several sites, the cache prevents from loading the ACLs of the same cartridge again and again.
  5. Each loaded entry of the cartridge’s ACL file is checked against the site pipeline cache.
    Only those entries that have not already been added to the cache are added. Thus, ACLs can be overloaded like pipelines by adding the access control list to a cartridge which is on top of the lookup list or to the ACL list of the site.

The access control list lookup also considers cartridges and sites that do not define any pipelines. In this case, the cartridge’s or site’s pipeline directory only contains the file pipelines-acl.properties. This allows developers to overload the ACLs of pipelines by their project specific cartridges or sites.

ACL Syntax

The pipelines-acl.properties files must match a specific syntax. As all properties files, they are made of key-value pairs. The pipelines-acl.properties files define the required permission for each pipeline-start node combination.
The following lines illustrate the ACL syntax:

<-- permission list for a given context for a specific start node of a pipeline -->
<PipelineName>-<StartNodeName>=<Context>:<PermissionID>
<-- permission list for a given context for an entire pipeline -->
<PipelineName>=<Context>:<PermissionID></pre>

The key is PipelineName-StartNodeName. The value is a semicolon separated list of Context:PermissionID pairs. In addition, you can define a default access control list for each pipeline without a start node, or an empty access control list for a pipeline.

...
ViewCatalog=Channel:NONE;Organization:SLD_MANAGE_CATALOGS
ViewCatalog-Dispatch=Channel:NONE;Organization:NONE
ViewCatalog-Edit=Channel:NONE;Organization:SLD_VIEW_CATALOGS
...
ViewCatalogCategoryEditing=Enterprise:SLD_MANAGE_CATALOGS
...

The entries for ViewCatalog-EditViewCatalog-Dispatch and ViewCatalog are treated as independent entries and are not merged during the cache initialization.

A call for ViewCatalog-Edit returns Channel:NONE;Organization:SLD_VIEW_CATALOGS (the context Channel denotes PrimeTech-Specials and the context Organization denotes PrimeTech), a call for ViewCatalog-Dispatch returns an empty list.
A call for ViewCatalog returns Channel:NONE;Organization:SLD_MANAGE_CATALOGS which is the pipelines fallback if a specific start node of the pipeline is not listed in the pipelines-acl.properties file.
The context Enterprise of the pipeline ViewCatalogCategoryEditing means both, the Organization context and the Channel context.

Permissions are always checked against an AuthorizationObject, i.e., a context, and that one or more permissions need to be checked before a pipeline is executed upon a user’s request. This behavior is represented in the Context:PermissionID values. Context defines the authorization object used to check the permission specified in PermissionID.

For example, the ACL:

ViewCatalog-Edit=Channel:NONE;Organization:SLD_VIEW_CATALOGS

means that if a user wants to start the pipeline ViewCatalog via the start node Edit, the permission SLD_VIEW_CATALOGS must be checked against the authorization object Organization. The number of Context:PermissionID pairs per access control list is not limited, but a Context:PermissionID pair should not appear more than one time in an access control list.

See the Intershop Studio User Guide – Creating Pipelines | Manage Pipeline Access Control for detailed information on how to manage the permissions of the access control list. The Intershop Studio User Guide is available as Online Help of Intershop Studio.

Secure Jumps On Form Submits

In Intershop it is common that a web form submit can trigger different actions. The actual action is not determined by the action attribute of the web form, but by the value of the submit button. Here’s an example from the BrowseCatalogCatagory.isml template:

...
<form action="#URL(Action('ViewCategory-Dispatch'))#" method="post" name="editCategoryForm">
  <table border="0" cellspacing="4" cellpadding="0">
    <tr>
      <td class="button">
        <input type="hidden" name="CatalogID" value="<isprint value="#Catalog:Id#">"/>
        <input type="hidden" name="CatalogUUID" value="<isprint value="#Catalog:UUID#">"/>
        <input type="hidden" name="ParentCategoryID" value="<isprint value="#Category:Parent:UUID#">"/>
        <input type="hidden" name="CatalogCategoryID" value="<isprint value="#Category:UUID#">"/>
        <input type="submit" name="edit" value="<isif condition="#isDefined(CurrentUserPermissionMap:SLD_MANAGE_CATALOGS) AND (NOT(Catalog:isProxy))#">Edit Properties<iselse>View Properties</isif>" class="button"/>
      </td>
    </tr>
  </table>
</form>
...

To avoid bypassing the ACL pipeline access checks it is strongly encouraged to use the SecureJump-Start pipeline when dispatching the action as this one does a explicit permission check on the resolved action. The simple example below shows how form actions should be dispatched at pipeline level.

SecureJump-Start Example

Co-Authors: Thomas Bergmann, Nils Breitmann and Intershop Consulting Stuttgart

OWASP Top Ten Project 2013 No 7 – Missing Function Level Access Control