Table Of Contents
Developing Rules and Signatures
Overview
Message Normalization
Passive Normalization
normalize() Function
Developing Signatures
Viewing Existing Signatures
Basic Example
About the Quick Pattern
Built-In Signature Notes
Uploading Custom Signatures
General Signature Development Guidelines
Signature Syntax
Sample Signature File
Developing Rules
Viewing Existing Rules
Uploading Custom Rules
General Rule Development Guidelines
Rule Syntax
Rule Group Declaration
Message Inspection Rule Format
Message Rewrite Rule Format
Rule Statement Format
Developing Rules and Signatures
This chapter describes how to develop custom web application security rules and signatures. It covers these topics:
•
Overview
•
Message Normalization
•
Developing Signatures
•
Developing Rules
Overview
The Cisco ACE Web Application Firewall includes an extensive library of rules and signatures you can use to secure web applications out-of-the-box. Built-in rules exist for stopping many types of server attacks, such as cross-site scripting attacks, SQL and LDAP injection attacks, and command injection attacks.
Nevertheless, applications often have unique security and content privacy concerns. The built-in resources may not address all requirements specific to your application or environment. For such cases, the Cisco ACE Web Application Firewall enables you to create your own custom rules and signatures. This extensibility enables you to tightly mold the capabilities of the Cisco ACE Web Application Firewall to your specific requirements.
You create custom rules and signatures using the Reactor rules language, as described here. After you have uploaded your rules and signatures into the Manager, they can be applied in web application profiles in the same manner as built-in rules.
In most cases, rule development will be motivated by a requirement to apply new signatures based on new or emerging attack patterns. Therefore, rule development projects will typically involve development of new signatures along with new rules.
The general steps for developing signatures and rules are:
1.
Create the signatures needed to match the traffic you want to be processed or secured by the rules.
Both signatures and rules are created and loaded into the system as text files. However, since the Manager treats rules and signatures as separate resources, you should create them in separate text files.
2.
Create custom rules and rule groups in a separate text file. The rules can rely on built-in signatures or custom signatures.
3.
Load the signature file into the Manager (before loading any rule that relies upon the custom signatures). The Manager validates the signatures in the file, and indicates problems on the web console page.
4.
Upload the custom rules file. When importing the rules, the Manager checks that signatures referenced in the rules exist in the system, and performs other validation checks on the rules.
Once uploaded, the custom rules are available to be applied in profiles. Also, note that the rules can be modified later directly from the Manager interface.
While these steps describe development that includes signatures along with rules, there are cases in which developing new rules will not depend on new signatures. For example, you may need to apply one of the built-in unused rules, or you may want to apply a built-in signature differently from how it is applied by the built-in rules. Most commonly, you may need to write a rule that does not use signatures. For example, to implement a rule that checks for data overflow, you would have a rule statement such as:
REQUEST_PARAMS.count() gt 100
As another example, checking a specific parameter against a regular expression could be achieved with an expression such as:
REQUEST_PARAM['username'] nre '[A-Za-z0-9]+'
The following sections provide more information on the rule development steps and requirements.
Message Normalization
To simplify rule development, the ACE Web Application Firewall automatically normalizes the message before evaluating rules against it. This alleviates you from having to deal with various types of message variations in the rules and signatures you create. For example, you do not need to create one version of a signature or rule for ISO-8859-1-based attacks and another for the same attack in UTF-8. It can also sanitize message content.
Message normalization does not affect the message that is actually passed through the ACE Web Application Firewall to the destination (except for NULL-byte screening and header unfolding); it is performed only on a copy of the message, or, more precisely, on the values from the message used to populate the variables that are used for rule evaluation, such as REQUEST_PARAMS or REQUEST_URL (see Rule Variables).
While normalization does not itself modify the output message (except for header whitespace unfolding), it can affect the output if you use variables in other contexts of the policy, such as in custom error messages or HTTP header processing. For instance, you can normalize a part of a request and use it to populate an outgoing header value.
Messages are subject to two types of message normalization. The first is called passive normalization. It happens to every message automatically. The second type of normalization is invoked directly from rules using the normalize() function.
Passive Normalization
Passive normalization affects messages as follows:
•
Any message that contains a NULL byte is rejected. (The presence of null bytes are treated as fatal errors. The ACE Web Application Firewall will respond with a 400/client error and generate a warning-level event that indicates a malformed request.)
•
In the request URL (including any GET arguments) and the body of any POST, the Firewall:
–
Decodes URL-encoded (that is, percent-encoded) characters into UTF-8 encoded characters. For rule and signature composition, this means that:
For ASCII characters, to match an argument that contains a percent-encoded character such as %27 (the URL-encoded single tick character), your custom signature can simply look for "'".
You can use Unicode characters in rules and signatures (such as certain cyrillic characters), which will be successfully matched, although the uploaded signature or rules file must be in UTF-8 format.
To look for a non-character decoded value in a signature, you can do so by putting a hex expression in the signature or regular expression, such as \x09, to look for a byte that just represents 9.
–
Decodes %u-encoded characters (non-standard Microsoft-used unicode encoding) to UTF-8.
•
In the request path only (this does not include the query string, that is, anything after "?"), the Firewall normalizes potentially obfuscating path commands like self-references (./) and back-references (../). This also helps properly match traffic to virtual web applications (that is, requests for "/app/../path" actually match the handler for "/path" rather than mistakenly matching the "/app" prefix handler.)
•
In HTTP headers, the Firewall:
–
Applies whitespace unfolding (http://www.w3.org/Protocols/rfc822/3_Lexical.html), where multiple-line headers are converted to a single line.
Note
Whitespace unfolding is the only aspect of normalization that affects the output message.
–
Other HTTP header are unchanged, except for the Host header. For the Host header, the Firewall changes URL-encoded or %u-encoded values to UTF-8. The entire header value is converted to lowercase, since hostnames are not intended to be evaluated in a case-sensitive manner. Host header normalization facilitates Referer header checking.
normalize() Function
The purpose of the normalization process described in "Passive Normalization" section is to alleviate signatures and rules from having to be written to contend with many low-level encoding issues in evaluated message content. However, except for path normalization (which helps to assign a request to a handler), this level of normalization is not intended to prevent higher-level obfuscations, such as excessive whitespace, encoded entities (such as using <script instead of <script), and breaking up attack strings with comments.
The second level of normalization, direct normalization, is intended to deal with just this type of obfuscation. To use direct normalization, you invoke the normalize() function on a part of a message, as follows:
VARIABLE['fieldName'].normalize() op testvalue
Such as:
REQUEST_HEADER['My-Header'].normalize(charset|uunicode) re 'attack!'
In this case, the value of the HTTP header, My-Header, is normalized prior to being tested against the regular expression, "attack!".
In the case of GET and POST parameters and POST bodies, many of the normalization processes described here are applied automatically, and do not need to be applied again with this function. However HTTP headers, multipart content disposition, and so on, are not extensively normalized by passive normalization and are subject to manual normalization through the normalize function.
The normalize() function can apply all processing that is applied to GET or POST arguments automatically (that is, URL-decoding and %u-decoding). In addition, it can:
1.
Convert letters to lowercase.
2.
Collapse all whitespace runs (any type of whitespace char) into a single "space" character (equivalent to ASCII 32).
3.
Strip C language and CSS-style comments (in the form: /* ... */) as well as HTML/XML comments (in the form: <!-- ... -->). These can be used to disguise attacks by interrupting the sequence of characters checked for by regular expression-type scanners with unrelated characters that will ultimately be ignored by the destination parser.
4.
Decode HTML, hexadecimal (&#xNN), and decimal (&#N...N;) entities.
5.
Decode JavaScript- and C-language-style encoding, such as \t, \001. \xAA, \hHH, \0OOO.
While the primary intent of normalize() is to deter obfuscation attempts, it also eases signature and rule authoring. For instance, instead of writing a regular expression to look for an arbitrary amount of whitespace between an attribute name and its value, you can assume there will be zero or one space.
Executing normalize() on a value when running an expression against it (such as in the example, REQUEST_HEADER['My-Header'].normalize(charset|uunicode) re 'attack!') does not alter the value of the parameter Name. The normalized value will be produced and used only for this particular regular expression evaluation.
In general, you should apply normalize() to any value before running a content-based signature (such as command injection) against it. However, there may be cases where running normalize() renders an attack unrecognizable, and in which the attack can only be caught in its raw form.
You can also use normalize() in any place in the virtual web application configuration in which you an output content, such as in custom error response messages or in headers. For example, you can replace a raw header with a sanitized version in the HTTP header processing configuration, that is, by replacing the value of header Custom-header with REQUEST_HEADER['Custom-header'].normalize(). Thus, while a normalized version of the message is not propagated to the outgoing request, you can use the HTTP header processing feature to normalize the headers propagated to the outgoing message.
Note
Note that while you can completely reconstruct the header list using HTTP header processing, you cannot currently rewrite GET or POST parameters.
To use the normalize() function, you must identify the aspect of normalization you want to apply to the message as a parameter. The supported parameters follow. You can pass multiple parameters using the pipe operator ("|"):
•
url - Performs URL-decoding, that is, %-encoded characters into their binary equivalents. This may result in normal readable characters or in non-character bytes. Generally, this option would be used together with the charset option.
•
charset - Takes any non-character bytes from the previous step and turns them into UTF-8 encoding (using the assumption that the original encoding was ISO-8859-1). This option would generally by used with the url argument, although it can be used alone as well (for example, if you have a value that is not URL-encoded, such as an HTTP header, that you want to inspect for extended-ASCII injection).
•
uunicode - Converts %u-encoded characters to UTF-8 equivalents.
•
htmlent - Converts all types of entities (&...;), including decimal and hex, into their non-entity equivalents.
•
escapes - Converts C-style backslash-escaped characters into their non-escaped equivalents.
•
nullsp - Converts embedded NULL characters to spaces. Note that requests with NULL bytes are rejected during passive normalization, so that this aspect of normalization does not usually need to be performed on requests. However, it's provided as a mechanism for inspecting other types of content for NULL characters.
•
nullremove - Strips embedded NULL characters. Note that requests with NULL bytes are rejected during passive normalization, and this aspect of normalization does not usually need to be performed on requests. However, it's provided as a mechanism for inspecting other types of content for NULL characters.
•
ccomment - Strips C-/Javascript-style comments.
•
xmlcomment - Strips XML/SGML-style comments.
•
backslash - Strips backslashes \
•
selfref - Strips self-reference paths: ./
•
backref - Strips back-reference paths: ../
•
trailingslash - Strips the trailing slash from a path
•
white - Normalizes and collapses whitespace runs to a single space character (ASCII 32)
•
lower - Converts all letters in string to lowercase.
Developing Signatures
A signature contains at least one content pattern designed to match messages of interest to rules. Messages matched by the signature are subject to the rule action. The system includes numerous built-in signatures. In addition you can create and apply your own, as described here.
You first create signatures in a text file that you then upload to the Manager. The text file may contain one or more signatures, each of which must belong to a signature group. A rule applies a signature through a reference to its signature group, as illustrated in .
Figure 6-1 Ruleset and signature set file
While the system does not impose requirements on how you organize signatures by groups, organizing signatures sensibly can help optimize performance. Since the ACE Web Application Firewall compiles each signature group into a single executable unit, multiple signatures in a single group can be applied to traffic more rapidly than the same number of signatures in multiple groups. As a general rule, signatures that target a particular class of attack should be grouped together into a single signature group. Keep in mind that if a particular signature within a group is not applicable for a given web application, policy developers can use a modifier to exempt the non-applicable signature for the application.
A signature statement consists of an identifier for the signature, its group, and several other properties. One of the properties is the regex attribute, which contains a regular expression to be applied to message content. The regular expression implementation employed by web application security features of the Cisco ACE Web Application Firewall is PCRE (Perl-Compatible Regular Expressions). The regular expression can include PRCE regular expression special characters, such as a dollar ($) to match the end of a string or a caret (^) to match the start of a string. A backslash escapes special characters, causing them to be evaluated as simple characters. Not all PCRE features are supported. Specifically, referencing captured groups is not supported.
Note
For more information on the PCRE syntax, see http://www.pcre.org/pcre.txt.
Viewing Existing Signatures
When creating your own signatures or rules, it is usually helpful to start from an example provided by one of the built-in resources. There are two views to the source code of the signatures loaded in the policy, the formatted view and the raw view:
•
For the formatted view, click the View Signatures button in the Rules & Signatures page. All signature groups loaded in the system appears in the window. To view signatures in a given group, click the group's expander control. When expanded, the source of the regular expression pattern that comprises the signature appears.
•
For the raw view, click the Rules & Signatures menu link, and then the Manage Signatures button. Click on the name of the signature set resource to view the source code of resource file in a new browser window.
The raw view is helpful when you are first creating the signature source file. The formatted view is useful to quickly find regular expression patterns used in the system for various attack signatures.
Basic Example
As shown in the signature source code view, a basic signature declaration appears as follows:
SQLInjection_m.drop:DROP
regex: ;\s*\bDROP\b
nocase: true
name: DROP
The sample has one signature, drop, which belongs to the signature group SQLInjection_m. Along with the signature name and group declaration, the signature has these properties:
•
After the name declaration is a quick pattern expression, "DROP," in this case. When used with a regular expression, this expression serves as an optimized, preliminary content test. You compose quick pattern expressions using a subset of the regular expression language features available for the regex attribute. For more information, see "About the Quick Pattern" section.
•
regex is the regular expression intended to match message content of interest. The regular expression pattern include the DROP string surrounded by the word boundary expression.
•
nocase indicates whether the regular expression is applied with case-sensitivity enabled. By default, comparisons are performed in a case-insensitive manner. You can specify a case-sensitive comparison by including this attribute and setting its value to false.
•
name is a descriptive name for the signature which appears in the web console interface.
A rule applies a signature to traffic by referencing the name of the signature group, as follows:
RULEGROUPNAME.RuleName:REQUEST_ALL sig SQLInjection_m
The identifier following the sig keyword, SQLInjection_m, identifies the signature group.
The following sections provide more information on the parts of a signature.
About the Quick Pattern
A signature can apply a regular expression to message content in two phases: the first is the quick pattern expression. If a message matches the quick pattern and the regex attribute also appears in the signature, the full regular expression in the regex attribute is applied to the message content.
The quick pattern is an optimization feature that allows the ACE Web Application Firewall to quickly disqualify messages from signature applicability. It uses a limited regular-expression-like syntax to do a very fast initial check of the message. If the quick pattern matches a message, the ACE Web Application Firewall applies the full regular expression (if present). Both expressions need to produce a positive match for the rule to be triggered. A signature can have just one of a quick pattern or regex property, in which case only that expression needs to be satisfied by the message content for the rule action to be triggered.
Note
Rewrite rules can only use quick pattern expressions to match content. That is, they can only reference signatures that use quick patterns.
In practice, the quick pattern commonly checks for the minimum character sequence that indicates potential content of interest, while the regular expression provides a more thorough test of the content, as illustrated by the built-in SQL injection signature for the DROP command:
Quick pattern: DROP
Regex pattern: ;\s*\bDROP\b
The quick pattern expression syntax comprises a subset of the PCRE syntax. Besides literal character matching, it includes support for:
•
Simple character class wildcards, such as "." (dot) to match any character
•
Pre-defined character classes, which include:
–
\d - digit
–
\D - not-digit
–
\s - whitespace
–
\S - not-whitespace
–
\w - word (alpha, numeric, or underscore)
–
\W - not-word
•
User-defined character classes, such as [a-z].
•
Hex-encoded character literals, such as "\x61" for "a".
Built-In Signature Notes
The following notes apply to the built-in signatures included in the base configuration and available for your rule development.
Unused signatures
While most built-in signatures are applied by one of the built-in rules, several are not. They are included in the base configuration and are available for use in your custom rules.
•
Quotes.single
•
Quotes.double
•
Tab.Tab
•
SQLComment.dashdash
These signatures match characters that are often present in legitimate messages. For instance, the single quote character may appear in surnames entered as form data, such as O'Neil. You should use them, therefore, only if you are certain that they are appropriate for your application traffic or if applying the signatures in monitor mode only.
CreditCard Signature group
The built-in signature groups include several credit card signature groups that all look for credit card numbers of various lengths. Notice that the signatures will match any appropriately delimited (with spaces or hyphens) set of numbers of the specified length. They do not apply any checksum formula (such as the Luhn algorithm) to verify that the numeric sequence of a suspected credit card number is actually a valid credit card number.
Uploading Custom Signatures
When finished developing signatures, you upload them to the Manager to make them available in the policy. To upload custom signatures:
Step 1
In the Rules & Signatures page, click the Manage Signatures button.
Step 2
Click the New Signature Resource button.
Step 3
Type a descriptive name for the signature resource. The name should be unique for signature resources in the policy. The name will appear in the signature resource list, so it should be sensible for other users of the web console.
Step 4
Locate the file that contains the signatures to be uploaded by clicking the Browse button and navigating to the file on your file system. Alternatively, if the resource is served by a web server, enter the URL at which it is available. Resources uploaded from a web server location are subject to the resource refresh feature, which provides for automatic reloading of resources at policy deployment.
Step 5
Click Upload. The Manager validates the signatures in the file and presents any errors it discovers. When finished the new resource appears in the resource list.
After the signatures are successfully loaded into the policy, they can be used to identify content of interest in messages handled by the ACE Web Application Firewall.
You can update the resource at any time by clicking the edit link next to the resource in the signature list and uploading an updated file in the edit resource page.
General Signature Development Guidelines
Each uploaded signature file comprises a single named resource in the policy. As such, it is subject to version-control and policy archiving features of the Manager.
The following lists general guidelines for signature file composition:
•
The first line of the signature file must be:
# Cisco Signature File v. <majorversion>.<minorversion>
The version numbers should match the system parser version against which you have created the signatures, 1.0 in the current release.
•
The file is in the form of new-line-delimited lines.
•
You can add single-line comments in the file by starting the line with a hash symbol (#). Other than the required first line of the file, lines that begin with the hash symbol do not affect operation of the signatures.
•
Each signature should conform to the syntax rules described in "Signature Syntax" section.
•
To use extended (non-7-bit-ASCII) characters in the signature file, you must set the signature source file to use UTF-8 encoding from your text editor.
Signature Syntax
The format for a signature definition follows:
X-<sig_group_id>.<sig_id>: <quick_pattern>
<attribute-name>: <attribute-value>
<attribute-name>: <attribute-value>
Where:
•
<sig_group_id> is the name of the signature group to which the signature belongs. To ensure uniqueness from built-in resources, the signature group names you create must start with "X-". The entire name, including the "X-" prefix, cannot be longer than 15 characters. Signature groups do not need to be separately declared.
•
<sig_id> is the identifier of the signature. It should not be longer than 15 characters. In any signature group or signature ID, you can use letters (case-sensitive), numbers, underscore characters (_), and hyphens characters (-). The IDs should be unique among signatures in the same group and should be descriptive of the signature.
•
<quick_pattern> is a pattern expression that identifies content to be matched using a subset of the regular expression syntax. A signature must have at least one of a quick pattern or regular expression (regex attribute), and may have both. If both are present, the quick pattern is evaluated first. If matched to the message, the regex pattern is compared to the matched portion as a final check.
•
In all lines of the signature, whitespace between the colon and the first non-whitespace character following the token is skipped. All other whitespace up to the new-line is significant.
•
The signature can have any of the following optional attributes.
–
regex, a PCRE-style regular expression used to match message content. While the regex attribute is optional, the signature must have at least one of a regex or quick pattern.
–
name, a descriptive name for the signature that appears in the web console.
–
cve is the optional CVE (Common Vulnerabilities and Exposures) identifier that describes the vulnerability the signature is intended to address. This information is useful for documenting the signature.
–
nocase determines case-sensitivity of the regular expression comparison. By default, the comparisons are performed in a case-insensitive manner. You can include this attribute and set it to false to have case-sensitive evaluation.
Each attribute should be on its own line, and should be preceded by one or more whitespaces. While the attributes are optional, it is recommended that all signatures have a name attribute for usability in the web console.
•
To interoperate correctly with the Manager, the fixed character portion of a signature may not be longer than 31 characters.
•
While signature group identifiers must be unique across the policy, signatures identifiers must be unique only within the context of the group. A rule can reference an individual signature by its fully qualified signature ID, which is made up of both the group and signature ID: <SigGroupID>.<SigID>. In most cases, however, a rule will reference the entire signature group.
Sample Signature File
An example signature list file follows:
Example 6-1 Signature list file
# Cisco Signature File v. 1.8
# Copyright Cisco Systems, Inc. All Rights Reserved
X-NextThreat_b.exec:exec
regex: ;\s*\bexec\b
nocase: true
name: exec nextthreat command attack
X-NextThreat_b.kick: kick
nocase: true
name: kick nextthreat command attack
X-NextThreat_m.start:start
nocase: true
name: start nextthreat command attack
X-NextThreat_m.cmd: cmdshell
nocase: true
name: cmdshell nextthreat command attack
X-PastThreat_m.cmd: dial
nocase: true
name: dial command attack
X-Privacy.USSocialSec:\d\d\d-\d\d-\d\d\d\d
name: Social Security number screening
The example creates four signature groups, X-NextThreat_b, X-NextThreat_m, X-PastThreat_m, and X-Privacy. Following the convention of the built-in signatures, the signature groups are named with the first letter of their severity level appended to the group name, "b" for basic and "m" for moderate.
While the examples set the nocase attribute to true (which means that signatures are applied in a case-insensitive fashion), setting this attribute to true is not strictly necessary since this is the default comparison mode.
You can try loading the sample by copying the text of Example 6-1 into a text file, and loading it into the Manager as described in "Uploading Custom Signatures" section. After loading the signatures, you can apply them in custom rules.
Developing Rules
A rule specifies the signatures to be applied to message content. Custom message inspection rules and message rewriting rules are supported. Message inspection rules are only applicable to requests, whereas message rewrite rules are only applicable to response messages.
A rule includes an expression that defines a condition for the rule action. In most cases, the expression is made up of the identifier for the part of the message to be checked and a reference to the signature to use for the check. It can also include functions, operators, or other advanced features.
As with signatures, custom rules are developed in a text file which, once uploaded to the Manager, comprises a named resource in the Manager. Since a rules file is treated as a single resource in the Manager, if you need to create a large number of rule groups for many applications, it may make sense to organize rule groups across multiple source files.
The following example shows the format of the rule set file:
Example 6-2 Rule set file format
# Cisco Rule File v. <major_version>.<minor_version>
GROUP X-<rulegroup_id>:<rulegroup_name>
X-<rulegroup_id>.<rule_name>:<message_inspection_scope> sig <siggroup_name>
name: <rule_descriptive_name>
Rule set files must begin with the Cisco Rule file declaration as its first line. The version numbers should reflect the version of the rule set parser against which the rules are written, 1.0 for the current version of the rule parser. The GROUP keyword declares a rule group, which can contain one or more rules.
User-created signature groups and rule groups must begin with the "X-" characters to ensure uniqueness with built-in rule groups. The rule definition starts by declaring the group to which it belongs. It then specifies the part of the message to be inspected and the signature used for the inspection.
Example 6-3 Rule set file example
# Cisco Rule File v. 1.0
# Group declarations
GROUP X-InspectRules: My Inspection Rule group
GROUP X-RewriteRules: My Message Rewrite Rule group
# rule declarations
X-InspectRules.NextThreat1:REQUEST_PARAM_ALL sig X-NextThreat_b
name: Parameter inspection for Next Threat
sev: 0
X-InspectRules.NextThreat2:REQUEST_HEADER sig X-NextThreat_b
name: Header inspection for Next Threat
sev: 0
X-InspectRules.NextThreat3:REQUEST_ALL sig X-NextThreat_m | X-PastThreat_m
name: Closer Inspection for Next Threat
sev: 1
# rewrite rules
X-RewriteRules.SsnMask: rewrite X-Privacy
name: Prevents SSN leak
rewriteChar: X
desc: Finds and rewrites SSN
The example defines three message inspection rules and a message rewrite rule. Note that the message inspection rules include a sev, or severity, property. The rule's sev value allows profiles to apply rules in a rule group selectively based on their severity, with values: 0 (basic), 1 (moderate), or 2 (strict). The message rewrite rule includes a rewriteChar value, which is used to replace each character of the matched content in the message.
The first two message inspection rules are distinguished by the part of the message to be inspected for the signature.
You can try loading the sample rules by copying the text of Example 6-3 into a text file, and loading it into the Manager as described in "Uploading Custom Rules" section. Before attempting to load the rules, you will need to upload the signatures listed in Example 6-1. After loading the rules, you can apply them in profiles.
Viewing Existing Rules
As with signatures, when creating your own rules, it is often helpful to start from an example provided by a built-in rule definition. To view the rule definitions, in the Rules & Signature page, click the Details link next to the rule, and then the View Source button at the bottom of the details page. The raw source code of the rule set appears.
Uploading Custom Rules
After you have finished developing rules, as described in the following sections, you will need to upload them to the Manager to make them available in the policy.
To upload custom rule files:
Step 1
In the Rules & Signatures page, click the New Custom Rules button.
Step 2
Type a descriptive name for the rule resource. The name should be unique for rule resources in the policy. The name will appear in the rule resource list, so it should be sensible for other users of the web console.
Step 3
To load the rules from an external text file, identify the file by clicking the Browse button and navigating to the file on your file system
Step 4
Click the Load File Contents button.
The rule source code appears in the Rule Definitions field. Note that while you can type or paste the rule source code directly into this field, in most cases, it will be loaded from an external text file.
Step 5
If needed, make changes directly to the rule source code in the Rule Definitions field, although note that changes you make in this field will not be propagated to the original rules source file.
Step 6
Click Save Changes.
The Manager validates the rules. Any validation errors are indicated at the top of the page. If rules reference signatures that have not been loaded, for instance, a rule validation error results.
The custom rules now appear in the web console page, as shown in . They are also listed in profiles, where they can be enabled to be made applicable to network traffic.
Figure 6-2 Custom rules in the web console
In the Rules & Signatures page, you can view the source code of the resource by clicking the Details link next to the name of the custom rule. After loaded to the policy, the rule source code is modifiable by clicking the Edit Rule File button at the bottom of the details page. You can edit the rule file to add new rules, modify, or remove rules from the rule set resource. Removing a rule group removes its availability from all profiles, including those in which the rule group is enabled.
General Rule Development Guidelines
Each uploaded rule file comprises a single named resource in the policy. As such, it is subject to version-control and policy archiving features of the Manager. The following lists general guidelines for rule file composition:
•
The first line of the rule file must be:
# Cisco Rule File v. <majorversion>.<minorversion>
The version should match the parser version of the system for which the rule are created, 1.0 in the current release.
•
Single-line comments can be included in your file by starting the line with a hash symbol (#). Other than the required first line of the file, lines that begin with the hash symbol do not affect the operation of the rule set.
•
The rule set may contain one or more rules and rule group declarations, in the form of new-line-delimited declarations.
•
For manageability, rewrite rules and message inspection rules cannot be in the same group.
•
Most elements of the rules files can have a desc property, which is intended to serve to document the item in the Manager user interface.
•
Severity levels are indicated by the sev attribute, with possible values of 0 (basic), 1 (moderate), or 2 (strict).
Rule Syntax
As previously mentioned, you can create two types of rules for web application security:
•
message inspection rules
•
message rewrite rules
The syntax between the two types varies slightly. However, both start by identifying the rule group to which it belongs, followed by a period, and then the rule's own identifier, as follows:
SQLINJECTION.SqlInjection1:REQUEST_ALL sig SQLInjection
...
In the example, a new rule named SqlInjection1 is declared in the rule group SQLINJECTION. After the name is a colon (:) followed by the rule statement, which includes the part of the message to be inspected along with signatures to be applied.
The example is a message inspection rule. A message rewrite rule starts with a similar arrangement of identifiers. However, the keyword rewrite follows the colon.
The following sections provide details on the message syntax.
Rule Group Declaration
A group declaration defines properties for a rule group. The only property applicable to group declaration is desc, a description property.
Note that if there is no GROUP declaration for a rule group ID reference in a rule declaration, the rule group is created automatically. Its name will be set to the same value as its ID, and it will have an empty description.
Rule groups are declared in the following format:
GROUP X-<rule_group_id>: <group name>
<wsp>desc: <description><newline>
The declaration is made up of the following components:
•
GROUP - A keyword that identifies the statement as a group definition.
•
<rule_group_id> - The rule group identifier. The identifier has these characteristics:
–
To ensure uniqueness with built-in rule groups, the group identifier must start with "X-",
–
The identifier must not be longer than 15 characters, including the required "X-" prefix.
–
The rule group identifier must be unique among all rule groups.
–
Legal characters in the identifier are upper- or lower-case letters, numbers, underscore characters (_), and hyphen (-) characters.
•
<group_name> - A user-friendly name for the rule group, for use in the Manager interface (for example, "SQL Injection").
•
<wsp> - A white space or tab precedes the group declaration attribute (the only supported group attribute is desc).
•
<description> - A description of the rule group. This description appears in the user interface after the rule file is uploaded.
Message Inspection Rule Format
Message inspection rules use the following format.
<rule_group_id>.<rule_id>: <rule_statement>
<attribute-name>: <attribute-value>
<attribute-name>: <attribute-value>
The rule is made up of the following:
•
<rule_group_id> - The identifier of the rule group to which the rule belongs. If a separate rule group definition for the group does not exist, the rule group is created. To ensure uniqueness from built-in rule groups, the group names you create must start with "X-". The entire name, including the "X-" prefix, cannot be longer than 15 characters.
•
<rule_id> - The rule identifier. The identifier has these characteristics:
–
The ID must be no longer than 15 characters.
–
The rule ID must be unique among all rules in the group.
–
Legal characters in any ID are case-sensitive letters, numbers, underscores (_), and hyphens (-).
•
<rule_statement> - A string defining a valid Reactor expression statement. For more information on this statement, see Rule Statement Format.
•
rule attributes - A rule can have rule attributes in the form of name-value pairs. Each attribute should occupy its own line, and be preceded by one or more whitespaces. The attribute is in the form of a attribute name followed by a colon, and then the attribute value followed by a line break.
Message inspection rules can have the following attributes:
–
name - A user-friendly name for the rule.
–
desc - A description of the rule that should document the rule for web console users.
–
severity - The severity level of the rule. If using severity levels, you define multiple rules that attempt to address a given security task at multiple levels of strictness or thoroughness. The profile can then apply the rule at the severity level desired for a given backend application.
Message Rewrite Rule Format
Rather than acting upon the entire message, message rewrite rules modify the portion of the message content matched by the signature. The signature may be matched multiple times in a single message. These rules are most commonly used to identify and overwrite sensitive content in a message.
Rewrite rules can only use quick pattern expressions to match content. For more information, see "About the Quick Pattern" section.
Message rewrite rules have the following format.
<rule_group_id>.<rule_id>: rewrite <sig_group_id>
<attribute-name>: <attribute-value>
<attribute-name>: <attribute-value>
The rule is made up of the following:
•
<rule_group_id> - The identifier for the rule group to which the rule belongs. If a separate rule group definition for the group does not exist, the rule group is created.
•
<rule_id> - The rule identifier. The identifier has these characteristics:
–
The ID must be no longer than 15 characters.
–
The rule ID must be unique among all rules in the group.
–
Legal characters in any ID are case-sensitive letters, numbers, underscores (_), and hyphens (-).
•
rewrite - The rewrite keyword identifies the rule as a message rewrite rule.
•
<sig_group_id> - The identifier of the signature group for the signatures that you want to apply in this rule. The signatures determine the content to be rewritten in messages subject to this rule.
Rewrite rules can only apply signatures that use DFA expressions; it cannot apply PCRE expressions. Therefore, the regular expression "\d{4,6}" could not be used, and would have to be replaced with three different signatures, each one for a different pattern length.
•
rule attributes - A rule can have rule attributes in the form of name-value pairs. Each attribute should occupy its own line, and be preceded by one or more whitespaces. The attribute is in the form of an attribute name followed by a colon, and then the attribute value followed by a line break.
Rewrite rules can have the following attributes:
–
name: A user-friendly name for the rule.
–
desc: A description of the rule that should document the rule for web console users.
–
rewriteChar - A value that is used to replace the matched pattern in the signatures. The rewriteChar is written once for every character in the matched pattern, so if the replacement character were "x", the following matched string 123-456-789-1011 would be rewritten as: xxxxxxxxxxxxxxxx.
Rule Statement Format
The rule statement is generally a conditional expression which, if resolving to true, triggers the rule action. The rule statement appears after the colon following the rule ID:
<rule_group_id>.<rule_id>: <rule_statement>
The rule statement format is:
<variable-expr> <operator> <test-value>
For example:
REQUEST_PARAM_ALL sig X-NextThreat_b
In this case, sig is the operator. It applies the test value specified by the signature or signature group name (X-NextThreat_b) to the tested value (all parameters). Rule statements can comprise tests based on other factors than a rule match. For instance, the following statement checks the number of request parameters:
REQUEST_PARAMS.count() gt 128
The sample tests whether the number of parameters in the requests exceeds 128. If true, the rule action is triggered. It is made up of:
•
A variable, REQUEST_PARAMS
•
A function, count(), and
•
An operator, gt
These rule expression features provide significant flexibility in defining custom rule behavior, as listed in these sections:
•
Rule Operators
•
Rule Variables
•
Rule Functions
Rule Operators
The following operators apply a binary test to a given test and tested value. If the test resolves to false, the tested content is excluded from rule applicability. The rule operators are listed inthe following table.
Table 6-1 Rule operators
Operator
|
True if the tested value is...
|
eq
|
equal
|
gt
|
greater than
|
gte
|
greater than or equal
|
lt
|
less than
|
lte
|
less than or equal
|
re
|
a regular expression
|
nre
|
not a regular expression
|
sig
|
a signature group, with a value that is the name of a SignatureGroup
|
Rule Variables
Rule variables provide access to runtime information. Variables exist, for example, for request parameters, headers, and client information, such as the client IP. Variables allow you to create rule conditions based on these runtime values.
In addition to rule composition, variables can be used in other areas of the policy as well. For example, you can include them in custom error response messages by referencing the variable in this form in the HTML response: $(varname). Also, they are available in header processing fields, so that variable values can be added as HTTP headers to outgoing messages.
Note
When developing rules, it may be helpful to test rule variables in a custom error response to quickly discover the types of values returned by each variable for your traffic.
Certain variables can provide access to the values of named parameters associated with a request in the following form:
VARIABLE_NAME['param']
Where param is the name of the web form variable.
For example:
REQUEST_HEADER['Referer'] sig CrossScript_m
In this case, the HTTP request header Referer is specifically checked for a content match against the signatures in CrossScript_m. Request parameter values can be retrieved in a similar fashion by passing the name of the parameter as identified in the POST form.
The variables available for rule development are listed in the following table. Where example return values are indicated, the return is based on a request URL of:
http://example.com:8080/details.do?v1=value1&v2=value2&v3=value3
Table 6-2 Rule variables
Variable
|
Description
|
CLIENT_IP
|
The IP of the client that made the request in dotted quad format.
|
CLIENT_PORT
|
The listening port to which the client made the request.
|
SERVER_IP
|
The IP of the server we are routing to in dotted quad format.
|
SERVER_PORT
|
The listening port of the destination server to be addressed.
|
REQUEST_ALL
|
A collection of the URL path, all parameters, all headers, in name-value format for each, when appropriate.
|
REQUEST_LINE
|
The complete request line including method and HTTP version.
|
REQUEST_URL_RAW
|
The request URL prior to normalization, such as:
/details.do?v1=value1&v2=value2&v3=value3
|
REQUEST_URL_FULL
|
The full request URL after normalization, such as:
/details.do
|
REQUEST_QUERY_RAW
|
The query string portion of the request. The query string is the part of the request URL after a question mark, such as:
v1=value1&v2=value2&v3=value3
|
REQUEST_URL_PATH
|
The path portion of the request URL, such as:
/details.do
|
REQUEST_URL_HOST
|
The host portion of the request URL, if present.
|
REQUEST_HOST
|
The host of the request, either from the URL or the Host header.
|
REQUEST_PARAM
|
A collection of all parameter values after normalization, keyed on parameter names (if message contains both GET and POST args, both are present), such as:
value1, value2, value3
|
REQUEST_PARAM_NAMES
|
A collection of all parameter names.
|
REQUEST_PARAM_ALL
|
A collection of all parameter names and values, keyed on parameter names, such as:
v1, v2, v3, value1, value2, value3
|
REQUEST_GETPARAM
|
A collection of all GET parameter values after normalization, keyed on parameter names, such as:
value1, value2, value3
|
REQUEST_GETPARAM_NAMES
|
A collection of all GET parameter names, keyed on parameter names.
|
REQUEST_GETPARAM_ALL
|
A collection of all GET parameter names and values, keyed on parameter names, such as:
v1, v2, v3, value1, value2, value3
|
REQUEST_POSTPARAM
|
A collection of all GET parameter values, after normalization, keyed on parameter names.
|
REQUEST_POSTPARAM_NAMES
|
A collection of all GET parameter names, keyed on parameter names.
|
REQUEST_POSTPARAM_ALL
|
A collection of all GET parameter names and values, keyed on parameter names.
|
REQUEST_HEADER
|
A collection of all request header values, keyed on header names.
|
REQUEST_HEADER_NAMES
|
A collection of all request header names.
|
REQUEST_HEADER_ALL
|
A collection of all request header names and values, keyed on header names.
|
COOKIE
|
The cookie values, keyed on cookie name.
|
COOKIE_NAMES
|
An ordered list of all cookie names.
|
COOKIE_ALL
|
Collection of all cookie names and values, keyed on names.
|
REQUEST_METHOD
|
The request method.
|
REQUEST_VERSION
|
The request HTTP version.
|
REQUEST_LENGTH
|
The length of the request.
|
AUTH_RAW
|
The raw data of the Authorization header, including the method and Base64 region.
|
AUTH_METHOD
|
Authentication method (from Authorization header, for example, Basic).
|
AUTH_USER
|
Username value from Authorization header.
|
AUTH_PASSWORD
|
Password value from Authorization header.
|
AUTH_DATA
|
Data from Authorization header, that is, the value after Auth method.
|
SSL_CIPHER
|
The cipher used for the client SSL connection.
|
SSL_CERT
|
The PEM-encoded client certificate, if present.
|
SSL_CERT_VERIFIED
|
Boolean value indicating whether the client certificate was verified.
|
SSL_CERT_REVOKED
|
Boolean value indicating whether the client certificate was revoked.
|
SSL_DIGEST_SHA1
|
The SHA1 digest of the client's SSL certificate, if present.
|
SSL_SUBJECT_DN
|
The Subject Distinguished Name of the client's SSL certificate, if present.
|
SSL_ISSUER_DN
|
The Issuer Distinguished Name of the client's SSL certificate, if present.
|
SSL_SUBJECT_ALTNAME
|
The Subject Alternative Name of the client's SSL certificate, if present.
|
SSL_SUBJECT_KEYID
|
The Subject Key Identifier of the client's SSL certificate, if present.
|
SSL_PEER_CERT_EXTENSION
|
A collection of the extension values of the client's SSL certificate, keyed on names.
|
SSL_PEER_CERT_EXTENSION_OID
|
A collection of the extension values of the client's SSL certificate, keyed on OIDs.
|
SSL_PEER_CERT_EXTENSION_NAMES
|
A collection of the extension names of the client's SSL certificate, keyed on names.
|
SSL_FINGERPRINT_CHAIN
|
An ordered list of fingerprints in the client's SSL CA verification chain.
|
SSL_VERSION
|
The version of the SSL session, one of "TLSv1", "SSLv2", "SSLv3", or an empty string.
|
REQUEST_MULTIPART_HEADERS
|
A collection, keyed on name, of all the headers of a multipart/form-data message's parts. All parts are aggregated into a single collection, so REQUEST_MULTIPART_HEADERS['Content-type'] will return all content-types of all parts.
|
REQUEST_MULTIPART_DISPOSITIONS
|
The simple value of the Content-Disposition header of all the parts of a multipart/form-data message. This is typically "form-data".
|
REQUEST_MULTIPART_DISPOSITION_NAMES
|
The name parameters of all the Content-Disposition headers of all the parts of a multipart/form-data message.
|
REQUEST_MULTIPART_DISPOSITION_FILENAMES
|
The file name parameters of all Content-Disposition headers of all parts of a multipart/form-data message.
|
REQUEST_BODY_RAW
|
The body portion of the request prior to normalization.
|
REQUEST_BODY_XML
|
The body portion of the request as XML content.
|
RESPONSE_HEADER
|
A collection of all response header values, keyed on header names.
|
RESPONSE_HEADER_NAMES
|
A collection of all response header names.
|
RESPONSE_HEADER_ALL
|
A collection of all response header names and values, keyed on header names.
|
REQUEST_PATH_AND_QUERY_RAW
|
The resource path and query portion of the request URL prior to normalization.
|
Rule Functions
Rule functions apply special processing operations to rule values before the rule is evaluated.
The following functions are available for rule composition. Note that they are also available in other contexts of the policy, such as in custom error response text or header processing fields. To apply a function to a variable value in a error response, enter them in the form $(varname.function), such as $(REQUEST_PARAMS.count()).
Table 6-3 Rule functions
Function
|
Description
|
count()
|
Returns the number of items identified by variable, such as REQUEST_PARAMS.count().
|
size()
|
Returns the total size of items referenced by variable.
|
maxsize()
|
Returns the size of the largest value of items referenced by variable.
|
urlencode()
|
Converts all values referenced by variable to their URL-encoded equivalent.
|
normalize(expr)
|
Normalizes items specified by the expr parameter. By normalizing a value, the function transforms it into canonical form, removing arbitrary variations or possible harmful content. For more information, see "normalize() Function" section.
|