=doc Make it easier to disable Java serialization, #22283 (#22315)

* one single config option to disable it completely
* improve security documentation

Co-authored-by: Patrik Nordwall <patrik.nordwall@gmail.com>
This commit is contained in:
Konrad `ktoso` Malawski 2017-02-16 14:09:04 +01:00 committed by GitHub
parent 552481b511
commit d306700feb
18 changed files with 843 additions and 191 deletions

View file

@ -236,6 +236,37 @@ you can advise the system to create a child on that remote node like so:
.. includecode:: code/docs/remoting/RemoteDeploymentDocTest.java#deploy
Remote deployment whitelist
^^^^^^^^^^^^^^^^^^^^^^^^^^^
As remote deployment can potentially be abused by both users and even attackers a whitelist feature
is available to guard the ActorSystem from deploying unexpected actors. Please note that remote deployment
is *not* remote code loading, the Actors class to be deployed onto a remote system needs to be present on that
remote system. This still however may pose a security risk, and one may want to restrict remote deployment to
only a specific set of known actors by enabling the whitelist feature.
To enable remote deployment whitelisting set the ``akka.remote.deployment.enable-whitelist`` value to ``on``.
The list of allowed classes has to be configured on the "remote" system, in other words on the system onto which
others will be attempting to remote deploy Actors. That system, locally, knows best which Actors it should or
should not allow others to remote deploy onto it. The full settings section may for example look like this:
.. includecode:: ../../../akka-remote/src/test/scala/akka/remote/RemoteDeploymentWhitelistSpec.scala#whitelist-config
Actor classes not included in the whitelist will not be allowed to be remote deployed onto this system.
.. _remote-security-java-artery:
Remote Security
---------------
An ``ActorSystem`` should not be exposed via Akka Remote (Artery) over plain Aeron/UDP to an untrusted network (e.g. internet).
It should be protected by network security, such as a firewall. There is currently no support for encryption with Artery
so if network security is not considered as enough protection the classic remoting with
:ref:`TLS and mutual authentication <remote-tls-java>` should be used.
It is also security best-practice to :ref:`disable the Java serializer <disable-java-serializer-java-artery>` because of
its multiple `known attack surfaces <https://community.hpe.com/t5/Security-Research/The-perils-of-Java-deserialization/ba-p/6838995>`_.
Untrusted Mode
^^^^^^^^^^^^^^
@ -255,6 +286,14 @@ a denial of service attack). :class:`PossiblyHarmful` covers the predefined
messages like :class:`PoisonPill` and :class:`Kill`, but it can also be added
as a marker trait to user-defined messages.
.. warning::
Untrusted mode does not give full protection against attacks by itself.
It makes it slightly harder to perform malicious or unintended actions but
it should be complemented with :ref:`disabled Java serializer <disable-java-serializer-java-artery>`.
Additional protection can be achieved when running in an untrusted network by
network security (e.g. firewalls).
Messages sent with actor selection are by default discarded in untrusted mode, but
permission to receive actor selection messages can be granted to specific actors
defined in configuration::
@ -441,24 +480,27 @@ Note that the array based methods can be implemented by delegation like this:
.. includecode:: code/docs/actor/ByteBufferSerializerDocTest.java#bytebufserializer-with-manifest
.. _disable-java-serializer-java-artery:
Disabling the Java Serializer
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
It is possible to completely disable Java Serialization for the entire Actor system.
Java serialization is known to be slow and prone to attacks of various kinds - it never was designed for high
throughput messaging after all. However it is very convenient to use, thus it remained the default serialization
mechanism that Akka used to serialize user messages as well as some of its internal messages in previous versions.
Akka internals do not rely on Java serialization (exceptions to that being ``java.lang.Throwable`` and "remote deployment").
Java serialization is known to be slow and `prone to attacks
<https://community.hpe.com/t5/Security-Research/The-perils-of-Java-deserialization/ba-p/6838995>`_
of various kinds - it never was designed for high throughput messaging after all. However, it is very
convenient to use, thus it remained the default serialization mechanism that Akka used to
serialize user messages as well as some of its internal messages in previous versions.
Since the release of Artery, Akka internals do not rely on Java serialization anymore (exceptions to that being ``java.lang.Throwable`` and "remote deployment").
.. note::
Akka does not use Java Serialization for any of it's internal messages.
Akka does not use Java Serialization for any of its internal messages.
It is highly encouraged to disable java serialization, so please plan to do so at the earliest possibility you have in your project.
One may think that network bandwidth and latency limit the performance of remote messaging, but serialization is a more typical bottleneck.
For user messages the default serializer implemented using Java serialization remains available and enabled by default.
For user messages, the default serializer, implemented using Java serialization, remains available and enabled.
We do however recommend to disable it entirely and utilise a proper serialization library instead in order effectively utilise
the improved performance and ability for rolling deployments using Artery. Libraries that we recommend to use include,
but are not limited to, `Kryo`_ by using the `akka-kryo-serialization`_ library or `Google Protocol Buffers`_ if you want
@ -469,13 +511,18 @@ your ``application.conf``:
.. code-block:: ruby
akka {
actor {
serialization-bindings {
"java.io.Serializable" = none
}
}
}
akka.actor.allow-java-serialization = off
This will completely disable the use of ``akka.serialization.JavaSerialization`` by the
Akka Serialization extension, instead ``DisabledJavaSerializer`` will
be inserted which will fail explicitly if attempts to use java serialization are made.
The log messages emitted by such serializer SHOULD be be treated as potential
attacks which the serializer prevented, as they MAY indicate an external operator
attempting to send malicious messages intending to use java serialization as attack vector.
The attempts are logged with the SECURITY marker.
Please note that this option does not stop you from manually invoking java serialization.
Please note that this means that you will have to configure different serializers which will able to handle all of your
remote messages. Please refer to the :ref:`serialization-java` documentation as well as :ref:`ByteBuffer based serialization <remote-bytebuffer-serialization-java>` to learn how to do this.

View file

@ -278,24 +278,33 @@ those actors are serializable. Failing to do so will cause the system to behave
For more information please see :ref:`serialization-java`.
.. _disable-java-serializer-java:
Disabling the Java Serializer
-----------------------------
It is possible to completely disable Java Serialization for the entire Actor system.
Java serialization is known to be slow and `prone to attacks
<https://community.hpe.com/t5/Security-Research/The-perils-of-Java-deserialization/ba-p/6838995>`_
of various kinds - it never was designed for high throughput messaging after all. However, it is very
convenient to use, thus it remained the default serialization mechanism that Akka used to
serialize user messages as well as some of its internal messages in previous versions.
Since the release of Artery, Akka internals do not rely on Java serialization anymore (one exception being ``java.lang.Throwable``).
Java serialization is known to be slow and prone to attacks of various kinds - it never was designed for high
throughput messaging after all. However it is very convenient to use, thus it remained the default serialization
mechanism that Akka used to serialize user messages as well as some of its internal messages in previous versions.
Akka internals do not rely on Java serialization (exceptions to that being ``java.lang.Throwable`` and "remote deployment").
.. warning::
Please note Akka 2.5 by default does not use any Java Serialization for its own internal messages, unlike 2.4 where
by default it sill did for a few of the messages. If you want an 2.4.x system to communicate with a 2.5.x series, for
example during a rolling deployment you should first enable ``additional-serialization-bindings`` on the old systems.
You must do so on all nodes participating in a cluster, otherwise the mis-aligned serialization
configurations will cause deserialization errors on the receiving nodes. These additional serialization bindings are
enabled by default in Akka 2.5.x.
.. note::
Akka does not use Java Serialization for any of it's internal messages.
When using the new remoting implementation (codename Artery), Akka does not use Java Serialization for any of its internal messages.
It is highly encouraged to disable java serialization, so please plan to do so at the earliest possibility you have in your project.
One may think that network bandwidth and latency limit the performance of remote messaging, but serialization is a more typical bottleneck.
For user messages the default serializer implemented using Java serialization remains available and enabled by default.
For user messages, the default serializer, implemented using Java serialization, remains available and enabled.
We do however recommend to disable it entirely and utilise a proper serialization library instead in order effectively utilise
the improved performance and ability for rolling deployments using Artery. Libraries that we recommend to use include,
but are not limited to, `Kryo`_ by using the `akka-kryo-serialization`_ library or `Google Protocol Buffers`_ if you want
@ -306,16 +315,21 @@ your ``application.conf``:
.. code-block:: ruby
akka {
actor {
serialization-bindings {
"java.io.Serializable" = none
}
}
}
akka.actor.allow-java-serialization = off
This will completely disable the use of ``akka.serialization.JavaSerialization`` by the
Akka Serialization extension, instead ``DisabledJavaSerializer`` will
be inserted which will fail explicitly if attempts to use java serialization are made.
The log messages emitted by such serializer SHOULD be be treated as potential
attacks which the serializer prevented, as they MAY indicate an external operator
attempting to send malicious messages intending to use java serialization as attack vector.
The attempts are logged with the SECURITY marker.
Please note that this option does not stop you from manually invoking java serialization.
Please note that this means that you will have to configure different serializers which will able to handle all of your
remote messages. Please refer to the :ref:`serialization-scala` documentation as well as :ref:`ByteBuffer based serialization <remote-bytebuffer-serialization-scala>` to learn how to do this.
remote messages. Please refer to the :ref:`serialization-java` documentation as well as :ref:`ByteBuffer based serialization <remote-bytebuffer-serialization-java>` to learn how to do this.
.. _Kryo: https://github.com/EsotericSoftware/kryo
.. _akka-kryo-serialization: https://github.com/romix/akka-kryo-serialization
@ -401,58 +415,19 @@ which includes the addresses of local and remote ActorSystems.
To intercept generic remoting related errors, listen to ``RemotingErrorEvent`` which holds the ``Throwable`` cause.
.. _remote-security-java:
Remote Security
^^^^^^^^^^^^^^^
Untrusted Mode
--------------
An ``ActorSystem`` should not be exposed via Akka Remote over plain TCP to an untrusted network (e.g. internet).
It should be protected by network security, such as a firewall. If that is not considered as enough protection
:ref:`TLS with mutual authentication <remote-tls-java>` should be enabled.
As soon as an actor system can connect to another remotely, it may in principle
send any possible message to any actor contained within that remote system. One
example may be sending a :class:`PoisonPill` to the system guardian, shutting
that system down. This is not always desired, and it can be disabled with the
following setting::
It is also security best-practice to :ref:`disable the Java serializer <disable-java-serializer-java>` because of
its multiple `known attack surfaces <https://community.hpe.com/t5/Security-Research/The-perils-of-Java-deserialization/ba-p/6838995>`_.
akka.remote.untrusted-mode = on
This disallows sending of system messages (actor life-cycle commands,
DeathWatch, etc.) and any message extending :class:`PossiblyHarmful` to the
system on which this flag is set. Should a client send them nonetheless they
are dropped and logged (at DEBUG level in order to reduce the possibilities for
a denial of service attack). :class:`PossiblyHarmful` covers the predefined
messages like :class:`PoisonPill` and :class:`Kill`, but it can also be added
as a marker trait to user-defined messages.
Messages sent with actor selection are by default discarded in untrusted mode, but
permission to receive actor selection messages can be granted to specific actors
defined in configuration::
akka.remote.trusted-selection-paths = ["/user/receptionist", "/user/namingService"]
The actual message must still not be of type :class:`PossiblyHarmful`.
In summary, the following operations are ignored by a system configured in
untrusted mode when incoming via the remoting layer:
* remote deployment (which also means no remote supervision)
* remote DeathWatch
* ``system.stop()``, :class:`PoisonPill`, :class:`Kill`
* sending any message which extends from the :class:`PossiblyHarmful` marker
interface, which includes :class:`Terminated`
* messages sent with actor selection, unless destination defined in ``trusted-selection-paths``.
.. note::
Enabling the untrusted mode does not remove the capability of the client to
freely choose the target of its message sends, which means that messages not
prohibited by the above rules can be sent to any actor in the remote system.
It is good practice for a client-facing system to only contain a well-defined
set of entry point actors, which then forward requests (possibly after
performing validation) to another actor system containing the actual worker
actors. If messaging between these two server-side systems is done using
local :class:`ActorRef` (they can be exchanged safely between actor systems
within the same JVM), you can restrict the messages on this interface by
marking them :class:`PossiblyHarmful` so that a client cannot forge them.
.. _remote-tls-java:
Configuring SSL/TLS for Akka Remoting
-------------------------------------
@ -506,6 +481,13 @@ as well as the `Oracle documentation on creating KeyStore and TrustStores <https
are both great resources to research when setting up security on the JVM. Please consult those resources when troubleshooting
and configuring SSL.
Since Akka 2.5.0 mutual authentication between TLS peers is enabled by default.
Mutual authentication means that the the passive side (the TLS server side) of a connection will also request and verify
a certificate from the connecting peer. Without this mode only the client side is requesting and verifying certificates.
While Akka is a peer-to-peer technology, each connection between nodes starts out from one side (the "client") towards
the other (the "server").
See also a description of the settings in the :ref:`remote-configuration-scala` section.
.. note::
@ -513,6 +495,65 @@ See also a description of the settings in the :ref:`remote-configuration-scala`
When using SHA1PRNG on Linux it's recommended specify ``-Djava.security.egd=file:/dev/urandom`` as argument
to the JVM to prevent blocking. It is NOT as secure because it reuses the seed.
Untrusted Mode
--------------
As soon as an actor system can connect to another remotely, it may in principle
send any possible message to any actor contained within that remote system. One
example may be sending a :class:`PoisonPill` to the system guardian, shutting
that system down. This is not always desired, and it can be disabled with the
following setting::
akka.remote.untrusted-mode = on
This disallows sending of system messages (actor life-cycle commands,
DeathWatch, etc.) and any message extending :class:`PossiblyHarmful` to the
system on which this flag is set. Should a client send them nonetheless they
are dropped and logged (at DEBUG level in order to reduce the possibilities for
a denial of service attack). :class:`PossiblyHarmful` covers the predefined
messages like :class:`PoisonPill` and :class:`Kill`, but it can also be added
as a marker trait to user-defined messages.
.. warning::
Untrusted mode does not give full protection against attacks by itself.
It makes it slightly harder to perform malicious or unintended actions but
it should be complemented with :ref:`disabled Java serializer <disable-java-serializer-java>`.
Additional protection can be achieved when running in an untrusted network by
network security (e.g. firewalls) and/or enabling
:ref:`TLS with mutual authentication <remote-tls-java>`.
Messages sent with actor selection are by default discarded in untrusted mode, but
permission to receive actor selection messages can be granted to specific actors
defined in configuration::
akka.remote.trusted-selection-paths = ["/user/receptionist", "/user/namingService"]
The actual message must still not be of type :class:`PossiblyHarmful`.
In summary, the following operations are ignored by a system configured in
untrusted mode when incoming via the remoting layer:
* remote deployment (which also means no remote supervision)
* remote DeathWatch
* ``system.stop()``, :class:`PoisonPill`, :class:`Kill`
* sending any message which extends from the :class:`PossiblyHarmful` marker
interface, which includes :class:`Terminated`
* messages sent with actor selection, unless destination defined in ``trusted-selection-paths``.
.. note::
Enabling the untrusted mode does not remove the capability of the client to
freely choose the target of its message sends, which means that messages not
prohibited by the above rules can be sent to any actor in the remote system.
It is good practice for a client-facing system to only contain a well-defined
set of entry point actors, which then forward requests (possibly after
performing validation) to another actor system containing the actual worker
actors. If messaging between these two server-side systems is done using
local :class:`ActorRef` (they can be exchanged safely between actor systems
within the same JVM), you can restrict the messages on this interface by
marking them :class:`PossiblyHarmful` so that a client cannot forge them.
.. _remote-configuration-java:
Remote Configuration