ARMR Rule
The term ARMR Rule is an umbrella term that includes all of the rules mentioned in the ARMR Rules section. Please see each rule type for a more detailed description. Each rule type has a unique set of statements to describe and configure the security control.
ARMR Rule Parts
While each ARMR rule models a different aspect of a system, each rule shares a common set of requirements. Each ARMR rule operates on a set of given conditions that need to be configured so that if and when an event
is triggered, then an action
will be taken. This style of behavior is analogous to behavioral test-driven development of given-when-then. The documentation will describe how each part is configured.
rule("An ARMR Rule"):
given("various conditions")
when("event occurs")
then("take action")
endrule
Every ARMR Rule is configured in a similar fashion, using these Given, When, Then states. Each rule will use these headings to describe how each specific rule needs to be configured.
Given (Conditions)
Each ARMR rule will allow a user to specify a unique set of conditions (configuration options) that will help to specify the nature of the event or define parameters that need to be enforced should an event be triggered. The configuration of the conditions is specific to each ARMR rule. Please consult each rule to learn how to configure it correctly.
When (Event)
The occurrence of an event is where an attack has been detected under the specified conditions, and an action will need to be taken. The configuration of the event is specific to each ARMR rule. Please consult each rule to learn how to configure it correctly.
If multiple ARMR rules exist for a given security feature, precedence is given to the ARMR rule with the more specific event condition, and this rule will be the one that triggers. For example, if a file path is specified as a condition in which the rule should trigger, then the ARMR rule with the most specific file path will take precedence.
Then (Action)
ARMR rules will perform an action on the basis of an event being triggered. In such cases, an ARMR rule can be configured to take action in a number of ways. Some actions have higher priorities than others, which will override rules with lower priority actions. This makes it possible to chain rules together. For example, it is possible to have a broad rule with a lower priority action that denies all events, and then to have more specific rule with a higher priority action that will allow events under certain conditions.
After event condition specificity, action priority then determines rule precedence. Action priority from highest to lowest is: allow (where supported), protect, detect.
detect | Used for monitoring events that have been triggered. Since this action does not interfere with other actions, it will always run. A log entry will be made in the CEF log file. |
allow | Used for allowing specific events to happen, overriding the events that are otherwise protected. A log entry will be made in the CEF log file. |
protect | Used for specifying events to protect. The type of protection is dependent on the ARMR rule type. A log entry will be made in the CEF log file. |
code | A user-specified block of code that will be run when the event has been triggered. No log entries are recorded on execution unless configured by the ARMR developer. In ARMR 2.0, code blocks are only supported in the ARMR Patch rule; in ARMR 3.0 and above, code blocks are supported in all rules. |
The action statement may specify a log message. If a log message is specified then a log entry will be generated. The user can specify a custom message to be included in the log entry or, if the log message parameter is left blank, a default log entry is generated.
The log message parameter is mandatory for an action of detect
, and is optional for an action of allow
or protect
. If the log message parameter is omitted then logging will be switched off.
For an action of detect
, allow
or protect
, the action statement may specify a severity. If no severity value is provided then the default severity is set to Unknown
. The user may specify the severity as an integer in the range of 0-10 inclusive (0 being least severe and 10 being most severe). The severity may also be specified as one of the following: Low
, Med
, High
or Very-High
(case insensitive).
Valid ARMR Example
This example shows how an ARMR Mod may be configured using the ARMR HTTP rule to detect requests to the endpoint "/webapp/index.jsp"
which do not have an origin of "host1"
, "host2"
, or "host3:8080"
. In this case, the conditions of this rule is predicated on a URI endpoint of "/webapp/index.jsp"
. Any request that matches that endpoint are then checked for the CSRF same origin event, indicated by csrf()
statement. The event needs to be configured as a same origin event using the same-origin
keyword. In this case, the request must have the origin
header that contains a host that matches one of the hosts specified in the rule. Should a request fail the parameters declared in the event, then an action will be taken. In this case, the detect()
action will take place, alerting the user that an invalid request was detected.
app("Security Rules"):
requires (version: "ARMR/2.0")
http("Detect HTTP requests with invalid origin header"):
request(paths: "/webapp/index.jsp")
csrf(same-origin,
options: {
hosts: ["host1", "host2", "host3:8080"]})
detect(message: "HTTP Same Origin validation failed", severity: 7)
endhttp
endapp
Invalid ARMR Example
Unrecognized but well-formatted rule declarations inside the app will be ignored by the parser. Consider the example below. The foo
block will be ignored but the http
rule will still be loaded. If an invalid ARMR Rule exists, an error message will be printed to the CEF log.
app("Security Rules"):
requires (version: "ARMR/2.0")
foo("a foo rule"):
endfoo
http("Deny HTTP requests with invalid origin header"):
request(paths: "/webapp/index.jsp")
csrf(same-origin,
options: {
hosts: ["host1", "host2", "host3:8080"]})
detect(message: "HTTP Same Origin validation failed", severity: 7)
endhttp
endapp
ARMR Rule Life-Cycle
Every ARMR Rule transitions through a five-stage lifecycle inside the ARMR Engine. Understanding this
lifecycle is important in order to understand the state of the rules inside the ARMR Engine. With the
exception of execute, each state of the rules lifecycle is shown in the CEF log. The following table
describes each state.
load | The syntax of the ARMR rule is valid and the rule has been loaded into the ARMR Engine. |
link | The ARMR rule has been compiled into the running application and is ready to begin executing on the next occurrence of the defined event. |
execute | The ARMR rule has executed and the action of the rule has been applied. Each unique execution of the ARMR rule is a unique execute event. Execute events are not recorded in the CEF log file, although some ARMR Engine implementations may provide special configuration options to enable CEF logging of execute events. |
unlink | The ARMR rule has been uncompiled from the running application and will no longer execute on future occurrences of the defined event. |
unload | The ARMR rule has been unloaded from the ARMR Engine. |
reload | Rule(s) will be reloaded by ARMR engine on detection of a change to rule content |
Reloading of rules will only occur when the rule’s configuration and desired behavior has changed such as log message and/or Java code, otherwise the rule will not be reloaded.
Only changed ARMR mods will be reloaded.
The output of the Security CEF log file will have the following format.
<14>1 2020-03-10T14:51:34.493Z localhost.localdomain java 52928 - - CEF:0|ARMR:2019 JULY CPU|2019 JULY CPU|2.3|CVE-2019-2769 :01|Link Rule|Low|outcome=success procid=52928 dvchost=localhost.localdomain rt=Mar 10 2020 14:51:34.493 +0000 appVersion=1
<14>1 2020-03-10T14:51:34.493Z localhost.localdomain java 52928 - - CEF:0|ARMR:2019 JULY CPU|2019 JULY CPU|2.3|CVE-2019-2769 :01|Link Rule|Low|outcome=success procid=52928 dvchost=localhost.localdomain rt=Mar 10 2020 14:51:34.494 +0000 appVersion=1
Limiting ARMR rules to specific Operating Systems
Additionally, each ARMR rule can be restricted to run on specific operating systems. This is particularly useful for security protections that are OS-dependent (e.g. file reads and writes) and allows for large-scale deployments of whole policies with ARMR Mods that target different Operating Systems. It also notifies agents of whether the rule is applicable and should be applied to the OS that it is currently running on.
To enable the OS constraint, pass the OS name, or a comma-separated list of names, as an argument to the rule. Examples:
-
rule(”my_rule”, os: [windows]):
-
rule(“my_rule2”, os: [linux, solaris]):
The valid constants are:
-
windows
-
linux
-
aix
-
solaris
-
any
When the ARMR Mod is loaded, if it does not satisfy the OS constraint, a log-entry such as the following will be produced:
<14>1 2020-07-10T11:12:06.213Z I-dev05 java 91730 - - CEF:0|ARMR:CVE-2019-2933|CVE-2019-2933|2.3|CVE-2019-2933 :04|Load Rule|Low|rt=Jul 10 2020 11:12:06.213 +0100 dvchost=I-dev05 procid=91730 outcome=failure reason=rule is not applicable to the currently running operating system appVersion=1