The use of XML allows for a specification of a white-listing approach which is independent of the web application firewall or validation system that is to be used. As one of the first WAF systems that the profiles can be used in, we provide a Java based compiler for transforming the profiles into a ruleset for the ModSecurity module.
In order to ease the creation of such a positive security model for an application, jwall.org
provides two approaches:
In addition to a plain white-listing approach, the XML language and the ProfileEditor allow for the integration of existing pattern-based approaches like PHP-IDS or even the Core Rules provided with the ModSecurity module. For more details on this integration see mixed models.
The language depends on nesting descriptions of your application's resources which results in a description.
Having said this, we can artlessly interpret an application as a hierarchical ordered set of resources which are identified by their URLs. Describing your application by specifying all resources that shall be accessable lets you check for a first class of common security issues of web applications: unwanted exposure of sensitive files.
The following figure 1 shows the hierarchical decomposition of a simple web application that consists of a small number of resources. Each resource is further specified in more details by more nested elements describing the request properties valid for this resource.
Resource elements for describing a resource and
by nesting resources the above tree structure can easily be described with the profile language. The
resources are further described by nesting additional XML elements within a certain resource's element.
As pointed out in the figure above the resource /intern/account.php can be described
by nesting a Method element and Parameter elements within the resource
description:
...
<Resource name="intern">
<Resource name="account.php">
<Parameter name="id" type="${SessionId}" scope="header" />
<Method value="GET">
<!--
Description of the resource /intern/account.php,
when accessed using a GET request
-->
</Method>
<Method value="POST">
<!--
Description of the resource /intern/account.php
when accessed with a POST request
-->
</Method>
</Resource>
</Resource>
...
As another feature to ease the creation of such profiles, the language allows for the specification
and use of pre-defined resource classes and parameter types. These can be used in a way similar to
the inheritance of modern object oriented programming languages.
In the example from above, the parameter type SessionID is a user-defined type that
is referenced by issuing ${SessionID} in the type attribute of the
parameter element.
A more sophisticated example is the definition and use of a resource class. This class defines several methods and parameters that can be inherited by other resources. Let the following be the definition of a resource class:
<ResourceClass name="Image">
<Method value="GET|HEAD" />
</ResourceClass>
Then we can easily define image resources by creating a Resource element within our
profile's resource tree, and let it extend the Image class:
<Resource name="images">
<Resource name="[a-z0-9]{4,8}\.gif" extends="Image" />
</Resource>
As you can probably easily guess from this simple example, this small XML snippet will specify
a set of resources which match the path /images/[a-z0-9]{4,8}\.gif and which inherit
the valid request properties from the Image class.
Thus, the images matching the specified path(s) can be accessed using a simple GET or HEAD method.
Similar definitions can also be made for specific headers, authorization or parameters.
After this small overview of the language concept, we will go into more details within the next
sections. The next session gives a description of the basic elements of the language. After this,
we describe the concept of inheritance within the language in section Abstraction.
/", the application consists
of all resources contained within that base path.
/images/logo.gif will be specified as follows:
...
<Resource name="images">
<Resource name="logo.gif">
</Resource>
</Resource>
...
Within the inner Resource-tag the legal properties of requests to that resource will
be described. Since profiles define a positive security-model, the above definition needs a little
bit more to be accessible. In the following we extend the resource-definition to allow GET-requests
to come through:
...
<Resource name="images">
<Resource name="logo.gif">
<Method value="GET" />
</Resource>
</Resource>
...
This will reflects all GET-requests without any parameter to be legal requests to images/logo.gif.
Nearly all attributes (i.e. a resources' name, a methods' value) allow for
the use of regular expressions which enables you to specify more than just one method at a time. For
example to allow HEAD-requests in addition to only the GET-method you can extend the definition above
by using
...
<Method value="(GET|HEAD)" />
...
Parameter. It has an attribute name
for refering to the parameter's name. This attribute also takes regular expressions for specifying type properties
for a set of parameters. The following example specifies a simple ID parameter which takes an hexadecimal
session ID of exactly 32 digits:
<Parameter name="ID" regexp="[a-fA-F0-9]{32,32}" required="false" scope="header" />
Obviously, the required-attribute specifies that this parameter has to be present within a request. Using
the scope attribute allows you to distinguish between parameters sent within the header, i.e. query-string,
and those transmitted in the request-body. Parameter element:
| Attribute | Description |
|---|---|
name |
This attribute specifies the name of the header or cookie that is checked using the regular expression. |
regexp |
This attribute contains either a regular expression that is used for checking the header or cookie, or
a reference, starting with a $ character, which references a pre-defined regular expression. |
required |
A parameter can either be optional or required. A value of true for this attribute
will require the parameter to be present within the request (besides matching the regular expression). |
scope |
Parameters can be transmitted either within the query string, i.e. the request header, or the message
body, e.g. within a POST request. This attribute allows for the user to specify either the header
or body scope for a request.
|
Parameter element can be nested into several of the elements described so far: Resource, for
defining a parameter type which covers all possible methods, or within the Method element, to restrict the
parameter in dependency of the request-method.
Parameters can even be dependent on each other, i.e. a certain parameter is only required to be present in case of another
one. In the following snippet, the parameter productID is mandatory if the parameter action has
the specific value "show":
<Parameter name="action" regexp="show" required="false" scope="header" >
<Parameter name="productID" regexp="\d{5,10}" required="true" scope="header" />
</Parameter>
Parameter, Header and Cookie. These
can take an expression like ${SessionID}, which will cause the compiler to look up the type named
"SessionID" before creating the ModSecurity rules.
The following snippet shows the parameter productID which references a application-specific predefined
parameter type "MyProductID":
<Parameter name="productID" type="${MyProductID}" required="false" scope="header"/>
Parameter is very universal and a central part of the profile language. Similar to checking the
types of parameters, it is also possible to use the Header and Cookie elements for type checking
header fields and request cookies.
As with the Parameter element, the elements Header and Cookie provide similar
attributes, which are listed within the following table:
| Attribute | Description |
|---|---|
name |
This attribute specifies the name of the header or cookie that is checked using the regular expression. |
regexp |
This attribute contains either a regular expression that is used for checking the header or cookie, or
a reference, starting with a $ character, which references a pre-defined regular expression. |
required |
A header and a cookie can either be optional or required. A value of true for this attribute
will require the header or cookie to be present within the request (besides matching the regular expression. |
Header and Cookie elements do not provide the scope attribute as these
properties are header properties.
Resource elements to extend
pre-defined resource classes.
This is the same principle that you probably already know from object oriented languages like Java, objective PHP or the like,
which makes it even more attractive to be utilized by users.