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>; ... )
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.
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.
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;)
Template Lookup
The following parameter allows to specify a template against which the IPS will scan the packet payload:
.pattern[!]="string";
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:
|
.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:
|
.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. |
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
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.
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:
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 0х prefix; arithmetic operators (+, -, *, /) can also be used. |
<offset> |
Offset in the data field of the packet:
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):
|
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). |
|
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.
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:
Modifiers:
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.