How to write a Fortify custom rule

Question

I would like to write custom Fortify rules for my application. What should I take into consideration when writing the rules so they will pass OIS Application Security Testing?

Answer

Fortify provides a mechanism to write custom rules that may be used to identify issues beyond what Fortify normally reports or to remove findings from being reported. While custom rules can be an effective tool for tuning a Fortify SCA scan to a specific application, care must be taken when developing rules so as to not introduce false negatives into the results.

The OIS Application Security Testing process includes steps to evaluate the custom rules to ensure they don’t result in false negatives. To facilitate the review of the custom rules, additional artifacts must be delivered as part of the review materials as described in the How to submit a code review that uses custom rules technical note.

Details on how to write custom rules are included in the “Micro Focus Fortify Static Code Analyzer Custom Rules Guide” that is included in the Fortify SCA installation package provided on the OIS Software Assurance Download Fortify Software Teams channel. When the installation package is unpacked, the guide is located in the Docs directory.

Additional Details

In general, each rule should be narrowly focused and contain a description, preferably in the rule, that describes its purpose and how it provides mitigation for that concern, similar to the comments that would be included when auditing a finding. The mitigation must address the concern of the findings that would have been reported by Fortify if the custom rule was not enabled.

The examples in remainder of this discussion will focus on cleanse rules since they are a common type of rule used to remove false positives but may also introduce false negatives. The cleanse rules are processed by the dataflow analyzer. The dataflow analyzer looks for data that comes into the application from an untrusted source and then is used in a potentially dangerous way at the sink. When the data comes into the application, it is tagged with a set of taint flags that indicate how the data is untrusted. If the data passes through a cleanse function, that cleanse function will remove some of the taint flags.

For example, if data is read from from user input, it is untrusted and is tagged with taint flags indicating it is untrusted user data. If that data is written to a web page and it contains the XSS taint flag, it will be reported as a Cross-Site Scripting: Reflected vulnerability. However, if that data passes through and HtmlEncode() function that the default rulepacks have identified as a cleanse function that removes the cross-site scripting: reflected taint flag, the flag will be removed before it gets to the sink and will not be reported.

An Example Of A Good Custom Rule

For the sample cleanse rules below, we will assume that we have a function called cleanseXSS() that uses a regular expression "[^a-zA-Z0-9\s-]" to replace any characters that are not in the allow list with a space character. With that in mind we might create the following rule:

<DataflowCleanseRule formatVersion="20.2.1" language="java">
    <RuleID>CE5C0CC4-0C2F-4082-B7B3-F8A88651271B</RuleID>
    <Notes><![CDATA[cleansXSS uses the regular expression "[^a-zA-Z0-9\s-]" to replace any characters 
           not in the allow list with a space.  It is used to validate data against XSS]]></Notes>
    <TaintFlags>+VALIDATED_CROSS_SITE_SCRIPTING_REFLECTED,+VALIDATED_CROSS_SITE_SCRIPTING_PERSISTENT,
          +VALIDATED_CROSS_SITE_SCRIPTING_DOM</TaintFlags>
    <FunctionIdentifier>
        <NamespaceName>
            <Pattern>com.example.app</Pattern>
        </NamespaceName>
        <ClassName>
            <Pattern>Util</Pattern>
        </ClassName>
        <FunctionName>
            <Pattern>cleanseXSS</Pattern>
        </FunctionName>
        <ApplyTo implements="true" overrides="true" extends="true"/>
    </FunctionIdentifier>
    <OutArguments>return</OutArguments>
</DataflowCleanseRule>

The rule above is well documented and narrowly defines the method cleanseXSS() as removing XSS taint. The method does appropriately validate against XSS, so this rule would be accepted.

An Example Of A Bad Custom Rule

However, if we create a separate rule below that uses the same method to remove log forging taint, it would not be accepted because the function cleanseXSS() does not appropriately validate against log forging and could lead to false negatives:

<DataflowCleanseRule formatVersion="20.2.1" language="java">
    <RuleID>CE5C0CC4-0C2F-4082-B7B3-F8A88651271C</RuleID>
    <Notes><![CDATA[cleansXSS uses the regular expression "[^a-zA-Z0-9\s-]" to replace any characters
not in the allow list with a space.  It is used to validate data against log forging]]></Notes>
    <TaintFlags>+VALIDATED_LOG_FORGING</TaintFlags>
    <FunctionIdentifier>
        <NamespaceName>
            <Pattern>com.example.app</Pattern>
        </NamespaceName>
        <ClassName>
            <Pattern>Util</Pattern>
        </ClassName>
        <FunctionName>
            <Pattern>cleanseXSS</Pattern>
        </FunctionName>
        <ApplyTo implements="true" overrides="true" extends="true"/>
    </FunctionIdentifier>
    <OutArguments>return</OutArguments>
</DataflowCleanseRule>