UserGate Application and Security Language (UASL)


UserGate Application and Security Language (UASL)

UserGate Application and Security Language (UASL) is a language for writing user signatures and applications.

Custom signatures and applications can be added to IDPS profiles and application profiles to use in firewall rules.

Signature has the following structure:

UASL (.parameter1=<value1>; .parameter2=<value2>; ...)

Signature parameters are specified in parentheses using semicolon (;) as a delimiter.

Multiline input can also be used:

UASL (.parameter1=<value1>; .parameter2=<value2>; ... )

Note Maximum length of custom signature is 1024 bytes.

All conditions of one signature without exceptions will be combined using AND logical operator.

Created, edited and removed signatures can be tracked using event log record details.


Metainformation

The .rev field contains additional information: user who created signature, and signature creation date, type and version. This is optional field which does not affect IDPS activity; it can be used to track changes.

The field has the following format:

.rev = <date>,<version>,<status>,<author>;

and parameters have the following data types:

  • <date>: integer;

  • <version>: integer;

  • <status>: string;

  • <author>: string.


ID

The .id field contains signature or application ID.

.id=<id_value>

This field is optional. ID can also be set in signature or application details.

Note The value set in signature details on the General tab has a priority over the value set using UASL.

Signature ID can range from 1000000 to 1049999; application ID can range from 1050000 to 1099999.

If the ID is set manually, its value is not unique and might be repeated.

If the ID was not set by the administrator, UserGate will assign it automatically (and when it is assigned automatically, its values might not be repeated). When the ID pool is exhausted, an error is displayed.


Filtering by IP Address

These parameters allow to configure checking of specified IP addresses:

.src_addr[!]=<IP_address/subnet>; .dst_addr[!]=<IP_address/subnet>;

The following IP address formats can be used:

  • A.B.C.D

  • A.B.C.D/E

  • A.B.C.D:E.

When specifying an IP address, it is not necessary to specify a network mask; to specify multiple IP addresses, use parentheses, for example:

.src_addr=[<IP_address1>, <IP_address2>];


Filtering by Port

To set TCP/UDP port checking, use the following parameters:

  • .src_port: to check source ports

  • .dst_port: to check destination ports

The following expressions are supported:

Name

Description

.src_port=<port_number>;

.dst_port=<port_number>;

Specifying a certain source and/or destination port.

.src_port!=<port_number>;

.dst_port!=<port_number>;

Checking all ports except for the specified one.

.src_port=:<port_number>;

.dst_port=:<port_number>;

Checking all ports whose number is less than or equal to the specified port number.

.src_port!=:<port_number>;

.dst_port!=:<port_number>;

Checking all ports whose number is greater than the specified port number.

.src_port=<port_number>:;

.dst_port=<port_number>:;

Checking all ports whose number is greater than or equal to the specified port number.

.src_port!=<port_number>:;

.dst_port!=<port_number>:;

Checking all ports whose number is less than the specified port number.

.src_port=<port_number1>:<port_number2>;

.dst_port=<port_number1>:<port_number2>;

Checking all ports in the specified range (including port_number1 and port_number2).

.src_port!=<port_number1>:<port_number2>;

.dst_port!=<port_number1>:<port_number2>;

Checking all ports which are not in the specified range (i. e. ports with numbers less than port_number1 and greater than port_number2).


Scanning Packets Without Payload

The .nopayload field allows to scan packets which do not have payload.

Note This field cannot be used for signatures with template lookup and tag checking.

For example, this field can be used to find ports which have packets without payload. The signature for SYN scan detection is as follows:

UASL(.protocol=tcp; .tcp.flags=S; .rate=1000,2; .track=src_ip; .nopayload;)

Note Specifying the .nopayload field does not mean that the packets with payload are not scanned.


Template Lookup

The following parameter allows to specify a template against which the IPS will scan the packet payload:

.pattern[!]="string";

Note Note that the search is case sensitive.

HEX data should be specified using "|" symbol, for example: |05 00 27|.

To specify special symbols, use the notations provided in the following table:

Symbol

HEX notation

"

|22|.

;

|3B| or |3b|.

\

|5C| or |5c|.

|

|7C| or |7c|.

:

|3A| or |3a|.

In addition to the = operator, the != operator can also be used. If the latter operator is specified, it will search for packets which do not contain a specified template.

The parameter has the following general format:

.pattern[!]="string"; [.where=<MODE>;] [.no_case;] [.distance=<RANGE>[,<MODE>];] [.within=<RANGE>[,<MODE>];] [.service=<MODE>;]

Search area modifiers (.where, .no_case, .distance, .within, .service) will be detailed later.

When writing a signature a number of .pattern parameters can be used to reduce the number of false positives.


Regular Expression Search

This option allows you to create signatures containing regular expressions compatible with the Perl language (detailed information on the website http://perldoc.perl.org/perlre.html):

.pcre="regex_str";

In addition to the = operator, the != operator can also be used. If the latter operator is specified, it will search for packets which do not contain a specified regular expression.

The parameter has the following general format:

.pcre="regex_str"; [.where=<MODE>;] [.distance=<RANGE>[,<MODE>];] [.within=<RANGE>[,<MODE>];] [.service=<MODE>;]

Search area modifiers (.where, .distance, .within, .service) will be detailed later.

When writing a signature a number of .pcre parameters can be used to reduce the number of false positives.


Search Area Modifiers

.no_case

no_case modifier allows to perform case insensitive search in accordance with .pattern parameter.

.where

.where modifier is used to specify signature search area:

.where=<MODE>;

where <MODE> can take following values:

Name

Description

packet_origin

Search area is the whole packet without a protocol decoder.

uri

Search area is URI field of HTTP header.

host

Search area for HTTP session is the Host field (before line breaks).

body

Search area is the body of HTTP packets.

.service

This search area modifies is needed to select a dissector.

.service=<MODE>;

where <MODE> can take following values:

Name

Description

http

HTTP protocol parsing.

.distance, .within, .at, .startin

These modifiers allow:

Name

Description

.distance

Skip specified number of bytes (RANGE) from the start or from the last found block.

It has the following format:

.distance=<RANGE> [,<MODE>];

where <RANGE> --- integer starting from 0.

Optional parameters (<MODE>) will be detailed below.

For example, the next record specifies skipping 10 bytes from the start for the first template and from the last found block for the second and subsequent templates.

.distance=10;

Example of using optional parameters:

  • skip 10 bytes from the start:

    .distance=10, start;

  • skip 10 bytes from the last found template:

    .distance=10, match;

.within

Scan selected interval (RANGE) from the start or from the last found block (the pattern falls completely within the specified range).

It has the following format:

.within=<RANGE> [,<MODE>];

where <RANGE> --- integer starting from 1.

Optional parameters (<MODE>) will be detailed below.

For example, the next record specifies the search from the 1th to 10th byte from the start for the first template and from the last found block for the second and subsequent templates.

.within=10;

Example of using optional parameters:

  • the search from the 1st (from the start) to the 10th byte:

    .within=10, start;

  • the search within 10 bytes from the last found template:

    .within=10, match;

.startin

Scan selected interval (RANGE) from the start or from the last found block (for a match, only the beginning of the pattern can fall within the specified range).

It has the following format:

.startin=<RANGE> [,<MODE>];

where <RANGE> --- integer starting from 1.

Optional parameters (<MODE>) will be detailed below.

.at

Checking for presence of the template at the specified position.

Important! This modifier cannot be used with .distance and .within modifiers.

It has the following format:

.at=<RANGE> [,<MODE>];

where <RANGE> --- integer starting from 0.

Optional parameters (<MODE>) will be detailed below.

Optional parameters are provided in the table below:

Name

Description

start

Search from the beginning of data flow.

Important! It is default value for the first template.

packet

Scan from the beginning of the packet.

reverse

Search from the end of the packet (useful for Next Protocol checking in ESP).

match

Search from the last found template.

Important! It is default value for the second and subsequent templates.

lastmark

Scan from the last tag set using .mark pset.

Note If the optional parameter for .distance and .within modifiers has the same value, then the value of .within modifier is counted from the value of .distance modifier.

For example, the record

.distance=10,match; .within=5,match

specifies the search in the range from 10th to 15th byte from the last found template.

.protocol

This modifier allows to specify a transport level protocol to which the signature will be applied:

.protocol=<MODE>;

where <MODE> can take following values:

  • icmp: ICMP protocol traffic analysis

  • udp: UDP protocol traffic analysis

  • tcp: TCP protocol traffic analysis

Note Only one protocol can be specified. If no protocol is specified, then the signature will be applied only to TCP and UDP traffic.


Triggering Frequency

If the frequency is set, the IDPS signature will be triggered not with every match, but only after a specified number of matches is detected for a specified time interval. This parameter can be useful, for example, to write signatures for detecting brute force attacks.

To specify the triggering frequency:

.rate=<count>, <period>;

here: <count> --- number of triggered events

<period> --- time interval (in seconds) during which the specified number of triggered events should occur.

The next parameter is optional and specifies the parameter for grouping matches:

.track=<MODE>;

here: <MODE> --- the property which specifies the mode for packet tracking.

<MODE> can take following values:

  • src_ip: tracking by source IP address

  • dst_ip: tracking by destination IP address.

If .track modifier is not specified, then all matches are counted, and after the specified limit is reached, the signature is triggered.

Example:

UASL(.name="pop3.brute.force"; .protocol=tcp; .pattern="USER"; .flow=from_server; .rate=3,60; .track=src_ip;)

The signature will be triggered after the USER template (.pattern="USER";) is discovered in packets sent from the same IP address (.track=src_ip;) more than 3 times for 60 seconds (.rate=3, 60;).


Signature Prioritization

This parameter is optional and is used to assign a priority level to the signature:

.weight=<num>;

where <num> is an integer in the range from 0 to 255.

The higher the weight, the more priority the signature; the default value is 10.

Note The recommended weight for custom signatures is between 20 and 50.


Analysis Direction

This parameter is optional and allows to apply the signature to certain traffic flows. It allows to create signatures that will analyze traffic from client, from server or in both directions.

.flow=<MODE>;

where <MODE> can take following values:

Name

Description

from_client

Analyze traffic from client.

from_server

Analyze traffic from server.

bi_directional

Analyze traffic in both directions.


Binary Data Search

The .byte_test parameter allows to compare a byte with a specified value and is applied to data presented in binary or character format.

The general format is as follows:

.byte_test = <bytes>,<operator>,<value>,<offset>,[,<multiplier>][,<modifiers>];

Available parameters are provided in the table:

Name

Description

<bytes>

Number of bytes in the current position with the specified offset which are read from the packet. Can take the following values: 1, 2 or 4.

<size>

String length; specified for string data.

*

Use all characters till the first non-numeric character.

<operator>

Operator used to compare the byte with the specified value:

  • < --- less than

  • > --- greater than

  • = --- equal To;

  • != --- not equal to

  • & --- the result of the logical "AND" operation between <bytes> and <MASK> (a number which specifies the bits of interest) is not equal to 0

  • ~ --- the result of the logical "AND" operation between <bytes> and <MASK> is equal to 0

  • ^ --- the result of the logical "XOR" operation between <bytes> and <MASK> is not equal to 0.

Example:

.byte_test=1,&,0x80,0;

checks that the most significant bit of the first byte in the data field of the packet is set to 1.

<value>

The value used in comparison or packet size.

The value can be specified using prefix; arithmetic operators (+, -, *, /) can also be used.

<offset>

Offset in the data field of the packet:

  • relative: from the last match point.

If the offset parameter is not specified, then the analysis, by default, is performed from the beginning of the packet.

<post_offset>

The number of bytes to move the scan start point.

Important! Applied to .byte_jump.

<multiplier>

A numeric value by which the extracted number should be multiplied before comparison or moving the scan start point; this parameter is optional.

<modifiers>

Modifiers (optional):

  • big --- process data from the most significant bit

  • little --- process data from the least significant bit

  • string --- the packet contains string data

  • hex --- convert the data string to a hexadecimal number

  • dec --- convert the data string to a decimal number

  • oct --- convert the data string to a octal number

  • align --- round the number of converted bytes to the next 32-bit boundary; used for .byte_jump only (for example, 0 ➜ 0; 1,2,3,4 ➜ 4; 5,6 ➜ 8 etc.).

Example: comparing the first four bytes of each packet with the value of 1234: packet data have character format in decimal numeration system:

.byte_test=4,=,1234,0,string,dec;

The .byte_jump parameter moves the scan start point to the specified number of bytes. The general format for data processing from the most or the least significant bit (i.e. for big and little modifiers) is as follows:

.byte_jump = <bytes>,<offset>,<post_offset>[,<multiplier>][,<modifiers>];

For string data (string modifier):

.byte_jump = (<size> | *),<offset>,<post_offset>[,<multiplier>][,<modifiers>];


File Search

The file parameter is used to search for files of a given type (each type can contain several subtypes).

This parameter is required to search for files of a given format type:

.file=<filetype>;

The first 12 bytes are used to determine the file type.

The following format types can be specified:

Name

Description

compress

Archive files (subtypes: arj, bzip, bzip2, cab, gzip, lzh, lzw, rar, rpm, tar, upx, zip).

images

Images (subtypes: gif, gif87a, gif89a, jpeg, png).

script

Script programming language (subtypes: .bat, .css, .hta, .vba, .vbs, genscript, javascript, perlscript, shellscript, wordbasic).

video

Video format (subtypes: .avi, MPEG).

pdf

Electronic documents (subtypes: .pdf).

flash

A media container used to transmit video over the Internet (subtypes: FLASH).

exe

Executable files (subtypes: .com, .dll, .exe).

html

Markup language (subtypes: HTML).

xml

Markup language (subtypes: XML, WORDML).

etc

Other types.

The following parameter .crc32 prevents downloading of the vulnerable file:

.crc32 <checksum>, <length>;

where is the checksum.

is the file length.


Working with Tags

Named tag can be specified for each data flow. It is specified in the following way:

.mark <parameter>=<value>;

here: <value> --- tag name (in quotes "")

<parameter> can take the values provided in the table below.

Pattern matching in most cases is bases on working with data packets. Tags are used when an attack pattern exists in a number of packets. The signature triggered for the previous packet can add a tag; tags are checked when sending packets within one session.

Name

Description

set

Set the named tag for the current data flow.

pset

Set and remember the last added tag, so that it could be used with .distance and .within search area modifiers.

clear

Remove the named tag.

toggle

Change the status of the tag.

test

Check if the tag exists.

reset

Reset all tags.


Protocol Analyzers

In this section the fields of ICMP, TCP, UDP and HTTP protocols will be described.

Since only one protocol can be specified for one signature, using the following parameters will cause automatic protocol determination, i. e. it is the same as using .protocol parameter.

Note Specifying parameters from different protocols will cause an error.

ICMP

The following parameters can be used to check ICMP header properties:

Name

Description

.icmp.type

Checking ICMP type.

The following operators are supported: =, !=.

.icmp.code

Checking ICMP code value.

The following operators are supported: =, !=.

.icmp.id

Checking ICMP ID value.

The following operators are supported: =, !=.

.icmp.checksum

Verifying the checksum which is used when errors are detected.

The following operators are supported: <, >, <=, >=, =, !=.

.icmp.data_size

Checking the size of the data field of the packet. This parameter is used to detect packets of abnormal size which are often used to cause buffer overflow.

The following operators are supported: <, >, <=, >=, =, !=. When multiple conditions are set, they are combined using AND logical operator.

TCP

The following parameters can be used to check TCP header properties:

Name

Description

.tcp.sport

Checking source port number or port range.

The following operators are supported: =, !=.

.tcp.dport

Checking destination port number or port range.

The following operators are supported: =, !=.

.tcp.window_size

Checking TCP window size.

The following operators are supported: <, >, <=, >=, =, !=.

.tcp.checksum

Verifying the checksum which is used to check for errors when sending and/or receiving a packet.

The following operators are supported: <, >, <=, >=, =, !=.

.tcp.seq

Checking values of TCP sequential numbers.

The following operators are supported: <, >, <=, >=, =, !=.

The relative modifier can be used to check against the starting number of the sequence.

Application:

.tcp.seq=<value>,relative;

here: <value> is the TCP sequential number.

.tcp.flags

Checking TCP flags:

.tcp.flags=[<mod>]<tcp_flags>;

here: <mod> --- modifier

<tcp_flags> --- TCP flag which can be specified in character or numeric (hexadecimal or decimal) format.

Flags:

  • 0: flags are not set

  • F, 1, 0X001: FIN

  • S, 2, 0X002: SYN

  • R, 4, 0X004: RST

  • P, 8, 0X008: PSH

  • A, 16, 0X010: ACK

  • U, 32, 0X020: URG

  • E, 64, 0X040: ECE

  • C, 128, 0X080: CWR

  • N, 256, 0X100: NS

Modifiers:

  • * --- at least one of specified flags should be set, the rest of the flags are not checked

  • + --- all specified flags should be set, the rest of the flags are not checked

  • ! --- all specified flags should be reset, the rest of the flags are not checked

  • !0 --- at least one (any) flag should be set

Important!If no modifier is set, then all specified flags should be set (strict match), and the rest of the flags should be reset.

.tcp.data_size

TCP packet payload size (without headers).

The following operators are supported: <, >, <=, >=, =, !=.

It is possible to specify it as .data_size (in this case the parameter will be applied to TCP and UDP protocols).

UDP

The following parameters can be used to check UDP header properties:

Name

Description

.udp.sport

Checking source port number or port range.

The following operators are supported: =, !=.

.udp.dport

Checking destination port number or port range.

The following operators are supported: =, !=.

.udp.checksum

Verifying the checksum.

The following operators are supported: <, >, <=, >=, =, !=.

.udp.data_size

UDP packet payload size (without headers).

The following operators are supported: <, >, <=, >=, =, !=.

It is possible to specify it as .data_size (in this case the parameter will be applied to TCP and UDP protocols).

HTTP

The following parameters can be used to check HTTP header properties:

Name

Description

.uri

Checking resource ID (URI) field.

.body

Checking the body of HTTP request or response.

.host

Checking node domain name.


Examples

In this sections a number of UASL code examples are provided.

Example 1

UASL( .id = 1; .pattern = "ABC"; .startin = 1; .pattern = "XYZ"; .at = 3, match; )

In this example a sequential search for two patterns is performed:

  • Search for the beginning of the ABC template within the specified range, i. e. the first byte of the specified template must fall within the range. The value of .startin modifier is 1 (range = 1, the template will be searched for from the beginning of the session, because the first modifier is "start" by default) --- the byte falling within this range should be equal to the beginning of the ABC template.

  • Search for XYZ template starting from position 4 (.at=3;) from the last found ABC template.

Example 2

UASL( .id = 2; .pattern = "ABC"; .at = 0; .pattern = "XYZ"; .distance = 3, match; .startin = 1, match; )

A sequential search for two patterns is performed:

  • Search for the beginning of the ABC template from the beginning of the packet (.at=0;).

  • After skipping 3bytes from the last found ABC template (.distance=3,match;), search for the beginning of the XYZ template is performed; for the pattern to be triggered, the beginning of the XYZ template should match the first byte from which the search starts, because .startin=1,match;.

Example 3

UASL( .id = 3; .pattern = "ABC"; .pattern = "XYZ"; .distance = 3, match; .within = 3, match; )

A sequential search for two patterns is performed:

  • Search for the ABC template;

  • At 3 bytes after the last found ABC template (.distance=3,match;) the search for the XYZ template is performed: the XYZ template should completely fall within the following 3 bytes, because .within=3.