Skip to main content
Version: 2.11

Deserialization

The deserialization security feature addresses such attacks by reducing system privileges. This means that 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.

The deserialization security feature can be safely enabled in all types of applications in order to be protected against Java and XML deserialization attacks.

info

Note that JSON deserialization vulnerabilities are not currently supported.

info

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 deserialization security feature can be used safely and pro-actively 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 .

info

Deserial vulnerabilities are covered by

  • CWE-502

  • CWE-250

  • CWE-799

  • CWE-400

Given(Condition)

deserializeThe keyword deserialize is one of two components that must be supplied in the marshal rule with only one being allowed to be configured in a single rule. java and dotnet are the only parameters accepted.

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.

rceRemote Code Execution
dosDenial of Service

Then(Action)

protectAll attempts to deserial are blocked.If configured, a log message is generated with details of the event.
detectMonitoring mode: the application behaves as normal.If configured, a log message is generated with details of all attempts to deserial.

A log message must be specified with this action.

As part of the action statement, the user may optionally specify the parameter stacktrace: “full”. When this parameter is specified, the stacktrace of the location of the attempted exploit is included in the security log entry.

Examples

Protecting the Java application from the dos attack.

app("myapp"):
requires(version: ARMR/2.7)

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.7)

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

    <10>1 2021-03-24T10:14:24.055Z userX_system java 9699 - - CEF:0|ARMR:ARMR|ARMR|2.7|MarshalRule|Execute Rule|High|rt=Mar 24 2021 10:14:24.053 +0000 dvchost=jenkins-qa-secondary-centos.aws.example.org procid=9699 appVersion=1 act=protect msg=Walter limit=100000 reason=CWE-400: Uncontrolled CPU consumption via API abuse methodName=java.util.EnumMap.hashCode()
    <10>1 2020-09-10T00:24:50.513Z userX_system java 29417 - - CEF:0|ARMR:ARMR|ARMR|2.7|MarshalRule|Execute Rule|High|rt=Sep 10 2020 00:24:50.512 +0000 dvchost=jenkins-qa-secondary-centos.aws.example.org procid=29417 act=protect msg=Walter limit=100000 reason=CWE-400: Uncontrolled CPU consumption via API abuse methodName=java.util.Hashtable.hashCode()
  • rce

    <10>1 2021-03-22T12:24:53.327Z userX_system java 28013 - - CEF:0|ARMR:ARMR|ARMR|2.7|MarshalRule|Execute Rule|High|rt=Mar 22 2021 12:24:53.326 +0000 dvchost=jenkins-qa-secondary-centos.aws.example.org procid=28013 appVersion=1 act=protect msg=Walter methodName=java.lang.Runtime.exec() httpRequestUri=/objectinputstream-deserial/examples/deserial-PM-59-test.jsp httpRequestMethod=GET remoteIpAddress=127.0.0.1 httpSessionId=D194C19D465595307BBD2F04F5F7B632

The second example above has extra CEF extensions for httpRequestUri, remoteIpAddress and httpSessionId.

Further Examples

Protecting the Java application from the dos attack with the stacktrace also logged.

app("Mod for Marshal dos Rule"):
requires(version: ARMR/2.7)

marshal("Marshal dos Rule"):
deserialize(dotnet, java)
dos()
protect(message: "Testing Marshal dos Rule", severity: Very-High, stacktrace: "full")
endmarshal

endapp

Protecting the Java application from rce attack with the stacktrace also logged.

app("Walter"):
requires(version: ARMR/2.7)

marshal("Marshal sys Rule"):
deserialize(java)
rce()
protect(message: "Walter", severity: High, stacktrace: "full")
endmarshal

endapp

Logging

<9>1 2021-03-31T15:38:48.279+01:00 userX_system java 104596 - - CEF:0|ARMR:ARMR|ARMR|2.7|Marshal dos Rule|Execute Rule|Very-High|rt=Mar 31 2021 15:38:48.278 +0100 dvchost=ckang-XPS-15-9570 procid=104596 appVersion=1 act=protect msg=Testing Marshal dos Rule stacktrace=java.util.AbstractSet.hashCode(AbstractSet.java)\ndeserialjar.runners.OverwrittenReadObject.abstractSetHashCode(OverwrittenReadObject.java:434)\ndeserialjar.runners.OverwrittenReadObject.invokeMethod(OverwrittenReadObject.java:375)\ndeserialjar.runners.OverwrittenReadObject.readObject(OverwrittenReadObject.java:57)\nsun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\nsun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\nsun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\njava.lang.reflect.Method.invoke(Method.java:498)\njava.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1170)\njava.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2232)\njava.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2123)\njava.io.ObjectInputStream.readObject0(ObjectInputStream.java:1624)\njava.io.ObjectInputStream.readObject(ObjectInputStream.java:464)\njava.io.ObjectInputStream.readObject(ObjectInputStream.java:422)\ndeserialjar.runners.OverwrittenReadObjectRunner.run(OverwrittenReadObjectRunner.java:32)\nMain.main(Main.java:63) limit=100000 reason=CWE-400: Uncontrolled CPU consumption via API abuse methodName=java.util.AbstractSet.hashCode()
<10>1 2021-03-31T15:51:32.787+01:00 userX_system java 105393 - - CEF:0|ARMR:ARMR|ARMR|2.7|Marshal sys Rule|Execute Rule|High|rt=Mar 31 2021 15:51:32.785 +0100 dvchost=ckang-XPS-15-9570 procid=105393 appVersion=1 act=protect msg=Walter stacktrace=deserialjar.runners.OverwrittenReadObject.invokeMethod(OverwrittenReadObject.java:103)\ndeserialjar.runners.OverwrittenReadObject.readObject(OverwrittenReadObject.java:57)\nsun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\nsun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\nsun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\njava.lang.reflect.Method.invoke(Method.java:498)\njava.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1170)\njava.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2232)\njava.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2123)\njava.io.ObjectInputStream.readObject0(ObjectInputStream.java:1624)\njava.io.ObjectInputStream.readObject(ObjectInputStream.java:464)\njava.io.ObjectInputStream.readObject(ObjectInputStream.java:422)\ndeserialjar.runners.OverwrittenReadObjectRunner.run(OverwrittenReadObjectRunner.java:32)\nMain.main(Main.java:63) methodName=java.lang.Runtime.exec()

Protecting the Java application from dos deserialization attacks with logging switched OFF. Logging is switched OFF by the omission of the protect action message attribute.

app("Mod for Marshal dos Rule"):
requires(version: ARMR/2.7)

marshal("Marshal dos Rule"):
deserialize(java)
dos()
protect(severity: Very-High)
endmarshal
endapp

Protecting the Java application from dos deserialization attacks. Logging is switched ON by the inclusion of the protect action message attribute. As the message attribute is defined as an empty string (""), a default message will be included in the security event msg extension. (Optionally, a custom message may be defined in the message attribute.)

app("Mod for Marshal dos Rule"):
requires(version: ARMR/2.7)

marshal("Marshal dos Rule"):
deserialize(java)
dos()
protect(message: "", severity: Very-High)
endmarshal
endapp

Whitelist

In the rare case where the deserial rule must allow specific privileges in certain environments, an optional 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()