Pattern Examples
Source/Passthrough Pattern Examples
The following passthrough pattern defines that, when calling any method of org.apache.commons.httpclient.util.URIUtil class with one or more parameters with a name beginning with encode, all flags of a null argument must be assigned and a URL_ENCODE flag must be added to a returned value:
<Rule>
<RuleId>SOURCE_00AF03C6</RuleId>
<Patterns>
<Pattern patternId="75b459">
<Categories>
<Category>JavaWeb</Category>
</Categories>
<Definitions>
<Class id="class">
<Supers includeSelf="true">
<Class>
<Name>
<Value>org.apache.commons.httpclient.util.URIUtil</Value>
</Name>
</Class>
</Supers>
<Method id="method">
<Name>
<Regex>encode.*</Regex>
</Name>
<Parameters>
<WildCard min="1" />
</Parameters>
</Method>
</Class>
<Instruction id="target_invoke">
<Class>
<Ref id="class" reftype="classref" />
</Class>
<Method>
<Ref id="method" reftype="methodref" />
</Method>
<Arguments>
<Argument id="arg0">
<Pos>0</Pos>
</Argument>
</Arguments>
</Instruction>
</Definitions>
<Condition>
<InstructionCondition>
<Ref id="target_invoke" reftype="instructionref" />
</InstructionCondition>
</Condition>
<ChangeFlags>
<FlagsSet>
<To>
<Argument>
<Return />
</Argument>
</To>
<From>
<Argument>
<Ref id="arg0" reftype="argumentref" />
</Argument>
</From>
<FlagsDiff>+URL_ENCODE</FlagsDiff>
</FlagsSet>
</ChangeFlags>
</Pattern>
</Patterns>
</Rule>
Source patterns are written in the same manner and only differ from passthrough patterns by the absence of From element from the Flagset.
Sink pattern example
The following sink pattern defines that calling a dangerousMethod method of org.example.DangerousClass class with a null int parameter and one or several additional parameters is insecure, if the first parameter has a TAINTED flag:
<Rule>
<RuleId>TEST_RULE</RuleId>
<Patterns>
<Pattern patternId="123abc">
<Categories>
<Category>JavaWeb</Category>
</Categories>
<Severity>1</Severity>
<Definitions>
<Class id="class">
<Supers includeSelf="true">
<Class>
<Name>
<Value>org.example.DangerousClass</Value>
</Name>
</Class>
</Supers>
<Method id="method">
<Name>
<Regex>dangerousMethod</Regex>
</Name>
<Parameters>
<Parameter>
<Type>int</Type>
</Parameter>
<WildCard min="1" />
</Parameters>
</Method>
</Class>
<Instruction id="target_invoke">
<Class>
<Ref id="class" reftype="classref" />
</Class>
<Method>
<Ref id="method" reftype="methodref" />
</Method>
<Arguments>
<Argument>
<Pos>1</Pos>
<Flags>
<Flag>TAINTED</Flag>
</Flags>
</Argument>
</Arguments>
</Instruction>
</Definitions>
<Condition>
<InstructionCondition>
<Ref id="target_invoke" reftype="instructionref" />
</InstructionCondition>
</Condition>
<ReportValues>
<ReportValue key="bad_instruction">
<Ref id="target_invoke" reftype="instructionref" />
</ReportValue>
</ReportValues>
</Pattern>
</Patterns>
</Rule>
Writing a Pattern for C# and PHP
Structure of source/passthrough pattern for C# and PHP:
<Pattern>
<Categories>
<Category>LANG</Category>
</Categories>
<XPath>self::node[] </XPath>
<Instruction>node </Instruction>
<ChangeFlags>
<FlagSet>
…
</FlagSet>
</ChangeFlags>
</Pattern>
The value of a LANG text field is the respective language for which the pattern is written, i.e. CS or PHP.
XPath element defines a call of a specified method of a specified class with specified arguments. The value of an XPath element is an XPath query beginning with a self axis with subsequent element:
- For C#:
member_access2
orprimary_expression_start
(depending on whether a class method or constructor is the key element). - For PHP:
memberAccess
orfunctionCall
(depending on whether a class method or constructor is the key element).
Instruction element has the following value:
- For C#:
member_access2
orprimary_expression_start
(depending on which element XPath query starts with). - For PHP:
memberAccess
orfunctionCall
(depending on which element XPath query starts with).
ChangeFlags element contains one or more FlagsSet. Each FlagsSet element shows how flags must be changed for a specified set of entities (arguments).
FlagsSet element contains the following elements: To, From, FlagsDiff and optional clearAll, attribute that may be either true or false.
To and From elements define entities that are involved in flag changing. The following entities can be flagged: Argument, Range.
Argument element defines a condition for one actual argument and contains a pos attribute (positions numbering starts from 0).
The Range element contains PosMin and PosMax attributes and defines a group of consecutive arguments starting from the PosMin index and ending with (inclusive) the PosMax index (index numbering starts from 0).
The FlagsDiff element contains a string specifying a flag change. The change type is specified as a diff attribute that may have one of the following values:
- add: add FLAG
- remove: remove FLAG if it exists
- inverse: change value of FLAG if it exists
Structure of sink pattern for C# and PHP:
<Pattern>
<XPath>//node</XPath>
</Pattern>
Writing Patterns for Other Languages
To analyze languages that cannot be compiled into Java bytecode, an intermediate AST representation is used. In this case, search patterns are defined in terms of Xpath queries to this representation.
General structure of Xpath-based XML pattern:
<Pattern>
<XPath>//node</XPath>
</Pattern>
Different languages are translated to intermediate representation differently. This is why XPath queries for different source languages have different structures. Examples of XPath queries for supported languages are provided below (editable parameters are highlighted in bold font).
Writing Pattern for JavaScript
Call of testMethod method of testClass class with an integer constant less than 128 as the first argument:
//singleExpression[
singleExpression[singleExpression/text()='testClass']
[identifierName/text()='testMethod']
][
arguments/argumentList[
singleExpression[1]/literal/numericLiteral[number(text()) < 128]
]
]
Writing Pattern for LotusScript
Call of testMethod method of testClass class:
//iCS_B_MemberProcedureCall[
implicitCallStmt_InStmt/
iCS_S_VariableOrProcedureCall/
ambiguousIdentifier[text()[1] = 'TestClass']
][
ambiguousIdentifier/
ambiguousKeyword[text()[1] = 'TestMethod']
]
Writing Pattern for TypeScript
Call of testFunction function with a constant argument that satisfies the regular expression:
//callExpression[
memberExpression/identifierName[text()[1] = 'testFunction']
][
arguments//literal[matches(text()[1], '.*val.*', 'i')]
]
Writing Pattern for VBScript
Call of TestMethod method of TestClass class with a constant string as the third argument:
//iCS_B_MemberProcedureCall[
implicitCallStmt_InStmt//
ambiguousIdentifier[
matches(@class, '^TestClass$', 'i')
]
][
ambiguousIdentifier/
ambiguousKeyword/text()[1] = 'TestMethod'
][
argsCall/argCall[3]//
literal[text()[1]]
]
Writing Pattern for Python
Call of test_method method of TestClass class with a string-type argument with length of less than 16 characters:
//power[
atom[1]/text()[1] = 'TestClass'
][
trailer[1]/text()[1] = 'test_method'
][
trailer[2]/arglist/argument//
arith_expr/term/factor/power/atom/string[
string-length(text()[1])<16
]
]
Writing Pattern for Perl
Call of insecure_operator() method with two arguments:
//listOperatorCall[
listOperatorName[text()[1] = 'insecure_operator']
][
list/operators[
operator[1]
][
operator[2]
][
not(operator[3])
]
]
Writing Pattern for Objective-C and C
Call of TEST_FUNC1 or TEST_FUNC2 function:
//CallExpr[
./*[1]//FunctionDecl[
@name = 'TEST_FUNC1' or @name = 'TEST_FUNC2'
]
]
Writing Pattern for C++
Call of “bad_function” function:
<Patterns>
<Pattern id="kjdfbgv132">
<Condition>
<callExpr>
<callee>
<functionDecl>
<hasName id="bad_function"/>
</functionDecl>
</callee>
</callExpr>
</Condition>
<Action>
<Report id="bad_function" severity="1" confidence="5"/>
</Action>
</Pattern>
</Patterns>
Writing Pattern for PL/SQL
Call of test_proc procedure of test_class class with a constant argument:
//function_call[
routine_name[
./id/id_expression/regular_id[
matches(text(), '^test_class$', 'i')
]
][
./id_expression/regular_id[
matches(text(), '^test_proc$', 'i')
]
]
][
function_argument[
.//constant
]
]
Writing Pattern for Rust
Hardcoded my_variable variable:
//let[
assignee/pattern//identifier[
matches(text(), 'my_variable')
]
][
initialization/expression[
count(*) = 1 and literal[text()[1]]
]
]
Writing Pattern for T-SQL
Call of TESTFUNC function with the following constant string argument: TEST_STRING_CONSTANT:
//function_call[
scalar_function_name/func_proc_name/
id/simple_id[
matches(text()[1], '^TESTFUNC$', 'i')
]
][
expression_list/expression[1]/
constant[
matches(text()[1], '^TEST_STRING_CONSTANT$', 'i')
]
]
Writing Pattern for ABAP
Call of test_func function:
//statement/
callStatement/
call_method_static_short/
methodId1/
methodId[1]/
anySingleToken[
matches(text()[1], 'test_func', 'i')
]
Writing Pattern for Apex
Call a constructor with the fifth argument's value equal to bad_value:
//statement/callStatement/call_method_static_short/
methodId1/methodId[1]/
anySingleToken[
matches(text()[1], 'test_func', 'i')
]
Writing Pattern for Go
Call of testFunc function:
//primaryExpr[
primaryExpr/operand/operandName[
matches(text()[1], '^testFunc$', 'i')
]
]
Writing Pattern for Ruby
Call of test_method method with an integer argument:
//function_call[
function_name[1]/id/text()[1] = 'test_method'
][
function_call_param_list[1]/
function_call_params/
function_param/
function_unnamed_param/
int_result/
int_t
]
Writing Pattern for Groovy
Call of testMethod method:
//expression[
callExpressionRule[
selectorName/IDENTIFIER[
matches(text()[1], '^testMethod$', 'i')
]
]
]
Writing Pattern for Dart
Call of TestMethod method of TestClass class:
//postfixExpression[
primary/identifier/identifierNotFUNCTION[
text()[1] = 'testClass'
]
][
selector/assignableSelector/unconditionalAssignableSelector/
identifier/identifierNotFUNCTION[
text()[1] = 'testMethod'
]
]
Writing Pattern for Delphi
Call of test_func function:
//statement[.//designator//ident[matches(text()[1], '^test_func$')]] [ .//expression//factor[(intNum|stringFactor[string-length(text()[1]) > 0])]]
Writing Pattern for Pascal
Call of test_func function:
//methodOrFunctionId/extendedIdentifier/identifier/ident[
matches(text()[1], '^test_func$', 'i')
]
Writing Pattern for HTML5
Attribute attribute with value bad_value:
//htmlElement[
htmlAttribute[
htmlAttributeName[matches(text()[1], 'attribute', 'i')]
]
[
htmlAttributeValue[matches(text()[1], 'bad_value', 'i')]
]
]
Writing Pattern for VB.NET
Call of TestMethod method of TestClass class with a constant string as the third argument:
//iCS_B_MemberProcedureCall[
implicitCallStmt_InStmt//
ambiguousIdentifier[matches(@class, '^TestClass$', 'i')]
][
ambiguousIdentifier/
ambiguousKeyword/text()[1] = 'TestMethod'
][
argsCall/
argCall[3]//
literal[text()[1]]
]
Writing Pattern for VBA
Call of the TestFunction function with a hardcoded string as an argument:
//iCS_S_VariableOrProcedureCall[
ambiguousIdentifier[matches(text()[1], '^TestFunction$', 'i')]
][
subscripts/subscript[1]/
ambiguousIdentifier/literal
]
Writing Pattern for Visual Basic 6.0
Call of TestMethod method of TestClass class with a constant string as the third argument:
//iCS_B_MemberProcedureCall[
implicitCallStmt_InStmt//
ambiguousIdentifier[matches(@class, '^TestClass$', 'i')]
][
ambiguousIdentifier/
ambiguousKeyword/text()[1] = 'TestMethod'
][
argsCall/
argCall[3]//literal[text()[1]]
]
Writing Pattern for Solidity
Call of testfunc function:
//functionName/identifier[
matches(text()[1], '^testfunc$', 'i')
]
Writing Pattern for Vyper
Call of insecure_function() function:
//atom_name[
text()[1] = 'insecure_function'
]
Writing Pattern for COBOL
Hardcoded sensitiveData variable:
//moveToStatement[
moveToSendingArea/literal
]/identifier
//cobolWord[
matches(text()[1], '^sensitiveData$', 'i')
]