ARMR Deserial Rule
Overview
Deserializing untrusted data can cause the JVM to instantiate any class available on the application’s classpath. In the case of poorly designed classes, the attacker can use malformed serialized data to abuse application logic, deny service, or execute arbitrary code, when deserialized . Serialization is used in several components of the JVM as well as in numerous third-party frameworks and dependencies.
The Deserial rule addresses the deserialization attacks by lowering the system privileges during deserialization. For the duration of a deserialization operation, the application operates in a restricted compartment (micro-segment) where specific system privileges are not available. Deserialization operations occur in a non-privileged context. Consequently, any attack (including zero-day attacks) that tries to access or change the state of the system fails. Please refer to another document "Deserialization White Paper" for more details on Waratek approach to deserial mitigation.
The Deserial rule can be safely enabled in all types of applications in order to be protected against Java and XML deserialization attacks.
Note that JSON deserialization vulnerabilities are not currently supported.
XML deserialization vulnerabilities can be introduced by different XML APIs and libraries. Currently, the only XML API that is supported is java.beans.XMLDecoder.
The Deserial rule can be used safely and proactively on any Java application in order to protect its system resources and components during deserialization. For example, any deserialization exploit that might try to perform the following attacks will fail:
-
execute arbitrary privileged commands (Remote Command Execution)
-
perform Remote Code Injection, change the system’s internal state
-
terminate the JVM or other types of Denial-of-Service attacks
The Denial-of-Service deserialization protection safeguards critical system resources, such as the CPU and memory, by setting default limits to control the interaction frequency of the deserialized objects with the system resources . This way, legitimate serialized objects are allowed to be deserialized while malicious serialized objects that abuse the system resources are blocked. This protection mitigates Denial-of-Service attacks via brute force and resource exhaustion .
Deserial vulnerabilities are covered by
-
CWE-502
-
CWE-250
-
CWE-799
-
CWE-400
Given(Condition)
deserialize | The keyword deserialize is a required component in the marshal rule. java and dotnet are the only parameters accepted. |
deserialize(java, dotnet)
|
When(Event)
One of rce
or dos
must be declared in a marshal
rule. Only one of these can exist in a marshal
rule and neither accept any parameter.
rce | Remote Code Execution |
dos | Denial of Service |
Then(Action)
The action component is a required component in the marshal
rule. There are two available actions: protect
and detect
. An action may, optionally, specify a severity. The value of severity
may be an integer in the range of 0-10(0 is the lowest level and 10 is the highest level) or one of Low
, Med
, High
or Very-High
(case insensitive). The default severity is unknown.
protect | All attempts to deserial are blocked. If configured, a log message is generated with details of the event. |
detect | Monitoring mode: the application behaves as normal. A log message is generated with details of all attempts to deserial. |
Examples
Protecting the Java
application from the dos
attack.
app("myapp"):
requires(version: ARMR/2.2)
marshal("protect the app from denial-of-service attack"):
deserialize(java)
dos()
protect(message: "the logging message")
endmarshal
endapp
Protecting the .Net
application from rce
attack.
app("myapp"):
requires(version: ARMR/2.2)
marshal("protect the app from remote-code-execution attack"):
deserialize(dotnet)
rce()
protect(message: "the logging message", severity: Low)
endmarshal
endapp
Logging
When the above deserial
rule is triggered a log entry similar to the following is generated:
- dos
<9>1 2020-07-06T13:45:28.821+01:00 userX_system java 26704 - - CEF:0|ARMR:Mod for Marshal dos Rule|Mod for Marshal dos Rule|2.2|Marshal dos Rule|Execute Rule|Very-High|rt=Jul 06 2020 13:45:28.814 +0100 dvchost=userX_system procid=26704 nodeid=1 act=protect msg=Testing Marshal dos Rule metadata="limit":"100000","reason":"CWE-400: Uncontrolled CPU consumption via API abuse","methodName":"java.util.AbstractSet.hashCode()"
- rce
<10>1 2020-07-07T10:42:07.480+01:00 userX_system java 4911 - - CEF:0|ARMR:Walter|Walter|2.0|Marshal sys Rule|Execute Rule|High|rt=Jul 07 2020 10:42:07.474 +0100 dvchost=userX_system procid=4911 act=protect msg=Walter methodName=java.lang.Runtime.exec()
<10>1 2021-02-05T16:21:48.632Z myuser-XPS-15-9570 java 4479 - - CEF:0|ARMR:MyApp|MyApp|2.3|MarshalRule|Execute Rule|High|rt=Feb 05 2021 16:21:48.631 +0000 dvchost=myuser-XPS-15-9570 procid=4479 appVersion=1 act=protect msg=MyMessage methodName=java.lang.Runtime.exec() httpRequestUri=/objectinputstream-deserial/examples/deserial-PM-59-test.jsp remoteIpAddress=10.0.0.103 httpSessionId=D48717DEFDD0A3344470EB3C5137B3C7
The second example above has extra metadata for httpRequestUri, remoteIpAddress and httpSessionId.
Whitelist
In the rare case where the deserial rule must allow specific privileges in certain environments, an optional waratek property com.waratek.AllowDeserialPrivileges
can be used to whitelist specific deserial privileges.
Setup AllowDeserialPrivileges Flag
-
Open the
<absoulte path to waratek agent>/conf_*/waratek.properties
file. -
Add the following flag and make an adjustment according to the real-world requirement.
com.waratek.AllowDeserialPrivileges=<comma-separated-values>
Examples
Whitelist java.lang.SecurityManager.<init>()
com.waratek.AllowDeserialPrivileges=java.lang.SecurityManager.<init>()
Whitelist java.lang.SecurityManager.<init>()
and java.lang.System.getenv()
com.waratek.AllowDeserialPrivileges=java.lang.SecurityManager.<init>(),java.lang.System.getenv()