Rewrite the scripting security docs (#23930)
They needed to be updated now that Painless is the default and the non-sandboxed scripting languages are going away or gone. I dropped the entire section about customizing the classloader whitelists. In master this barely does anything (exposes more things to expressions).
This commit is contained in:
parent
a3cceb8a00
commit
7fad7c675d
|
@ -87,7 +87,6 @@ buildRestTests.expectedUnconvertedCandidates = [
|
||||||
'reference/mapping/types/nested.asciidoc',
|
'reference/mapping/types/nested.asciidoc',
|
||||||
'reference/mapping/types/object.asciidoc',
|
'reference/mapping/types/object.asciidoc',
|
||||||
'reference/mapping/types/percolator.asciidoc',
|
'reference/mapping/types/percolator.asciidoc',
|
||||||
'reference/modules/scripting/security.asciidoc',
|
|
||||||
'reference/modules/cross-cluster-search.asciidoc', // this is hard to test since we need 2 clusters -- maybe we can trick it into referencing itself...
|
'reference/modules/cross-cluster-search.asciidoc', // this is hard to test since we need 2 clusters -- maybe we can trick it into referencing itself...
|
||||||
'reference/search/field-stats.asciidoc',
|
'reference/search/field-stats.asciidoc',
|
||||||
'reference/search/profile.asciidoc',
|
'reference/search/profile.asciidoc',
|
||||||
|
|
|
@ -76,6 +76,7 @@ Read more in {ref}/integration-tests.html#changing-node-configuration[Changing N
|
||||||
|
|
||||||
|
|
||||||
[float]
|
[float]
|
||||||
|
[[plugin-authors-jsm]]
|
||||||
=== Java Security permissions
|
=== Java Security permissions
|
||||||
|
|
||||||
Some plugins may need additional security permissions. A plugin can include
|
Some plugins may need additional security permissions. A plugin can include
|
||||||
|
@ -111,4 +112,3 @@ AccessController.doPrivileged(
|
||||||
|
|
||||||
See http://www.oracle.com/technetwork/java/seccodeguide-139067.html[Secure Coding Guidelines for Java SE]
|
See http://www.oracle.com/technetwork/java/seccodeguide-139067.html[Secure Coding Guidelines for Java SE]
|
||||||
for more information.
|
for more information.
|
||||||
|
|
||||||
|
|
|
@ -1,73 +1,115 @@
|
||||||
[[modules-scripting-security]]
|
[[modules-scripting-security]]
|
||||||
=== Scripting and security
|
=== Scripting and security
|
||||||
|
|
||||||
You should never run Elasticsearch as the `root` user, as this would allow a
|
While Elasticsearch contributors make every effort to prevent scripts from
|
||||||
script to access or do *anything* on your server, without limitations.
|
running amok, security is something best done in
|
||||||
|
https://en.wikipedia.org/wiki/Defense_in_depth_(computing)[layers] because
|
||||||
|
all software has bugs and it is important to minimize the risk of failure in
|
||||||
|
any security layer. Find below rules of thumb for how to keep Elasticsearch
|
||||||
|
from being a vulnerability.
|
||||||
|
|
||||||
You should not expose Elasticsearch directly to users, but instead have a
|
|
||||||
proxy application inbetween. If you *do* intend to expose Elasticsearch
|
|
||||||
directly to your users, then you have to decide whether you trust them enough
|
|
||||||
to run scripts on your box or not, and apply the appropriate safety measures.
|
|
||||||
|
|
||||||
[[enable-dynamic-scripting]]
|
|
||||||
[float]
|
[float]
|
||||||
=== Enabling dynamic scripting
|
=== Do not run as root
|
||||||
|
First and foremost, never run Elasticsearch as the `root` user as this would
|
||||||
|
allow any successful effort to circumvent the other security layers to do
|
||||||
|
*anything* on your server. Elasticsearch will refuse to start if it detects
|
||||||
|
that it is running as `root` but this is so important that it is worth double
|
||||||
|
and triple checking.
|
||||||
|
|
||||||
The `script.*` settings allow for <<security-script-fine,fine-grained>>
|
[float]
|
||||||
control of which script languages (e.g `painless`) are allowed to
|
=== Do not expose Elasticsearch directly to users
|
||||||
run in which context ( e.g. `search`, `aggs`, `update`), and where the script
|
Do not expose Elasticsearch directly to users, instead have an application
|
||||||
source is allowed to come from (i.e. `inline`, `stored`, `file`).
|
make requests on behalf of users. If this is not possible, have an application
|
||||||
|
to sanitize requests from users. If *that* is not possible then have some
|
||||||
|
mechanism to track which users did what. Understand that it is quite possible
|
||||||
|
to write a <<search, `_search`>> that overwhelms Elasticsearch and brings down
|
||||||
|
the cluster. All such searches should be considered bugs and the Elasticsearch
|
||||||
|
contributors make an effort to prevent this but they are still possible.
|
||||||
|
|
||||||
For instance, the following setting enables `stored` `update` scripts for
|
[float]
|
||||||
`painless`:
|
=== Do not expose Elasticsearch directly to the Internet
|
||||||
|
Do not expose Elasticsearch to the Internet, instead have an application
|
||||||
|
make requests on behalf of the Internet. Do not entertain the thought of having
|
||||||
|
an application "sanitize" requests to Elasticsearch. Understand that it is
|
||||||
|
possible for a sufficiently determined malicious user to write searches that
|
||||||
|
overwhelm the Elasticsearch cluster and bring it down. For example:
|
||||||
|
|
||||||
[source,yaml]
|
Good:
|
||||||
----------------
|
* Users type text into a search box and the text is sent directly to a
|
||||||
script.engine.painless.inline.update: true
|
<<query-dsl-match-query>>, <<query-dsl-match-query-phrase>>,
|
||||||
----------------
|
<<query-dsl-simple-query-string-query>>, or any of the <<search-suggesters>>.
|
||||||
|
* Running a script with any of the above queries that was written as part of
|
||||||
|
the application development process.
|
||||||
|
* Running a script with `params` provided by users.
|
||||||
|
* User actions makes documents with a fixed structure.
|
||||||
|
|
||||||
Less fine-grained settings exist which allow you to enable or disable scripts
|
Bad:
|
||||||
for all sources, all languages, or all contexts. The following settings
|
* Users can write arbitrary scripts, queries, `_search` requests.
|
||||||
enable `inline` and `stored` scripts for all languages in all contexts:
|
* User actions make documents with structure defined by users.
|
||||||
|
|
||||||
[source,yaml]
|
[float]
|
||||||
-----------------------------------
|
[[modules-scripting-security-do-no-weaken]]
|
||||||
script.inline: true
|
=== Do not weaken script security settings
|
||||||
script.stored: true
|
By default Elasticsearch will run inline, stored, and filesystem scripts for
|
||||||
-----------------------------------
|
sandboxed languages, namely the scripting language Painless, the template
|
||||||
|
language Mustache, and the expression language Expressions. These *ought* to be
|
||||||
|
safe to expose to trusted users and to your application servers because they
|
||||||
|
have strong security sandboxes. By default Elasticsearch will only run
|
||||||
|
filesystem scripts for non-sandboxed languages and enabling them is a poor
|
||||||
|
choice because:
|
||||||
|
1. This drops a layer of security, leaving only Elasticsearch's builtin
|
||||||
|
<<modules-scripting-other-layers, security layers>>.
|
||||||
|
2. Non-sandboxed scripts have unchecked access to Elasticsearch's internals and
|
||||||
|
can cause all kinds of trouble if misused.
|
||||||
|
|
||||||
WARNING: The above settings mean that anybody who can send requests to your
|
|
||||||
Elasticsearch instance can run whatever scripts they choose! This is a
|
[float]
|
||||||
security risk and may well lead to your Elasticsearch cluster being
|
[[modules-scripting-other-layers]]
|
||||||
compromised.
|
=== Other security layers
|
||||||
|
In addition to user privileges and script sandboxing Elasticsearch uses the
|
||||||
|
http://www.oracle.com/technetwork/java/seccodeguide-139067.html[Java Security Manager]
|
||||||
|
and native security tools as additional layers of security.
|
||||||
|
|
||||||
|
As part of its startup sequence Elasticsearch enables the Java Security Manager
|
||||||
|
which limits the actions that can be taken by portions of the code. Painless
|
||||||
|
uses this to limit the actions that generated Painless scripts can take,
|
||||||
|
preventing them from being able to do things like write files and listen to
|
||||||
|
sockets.
|
||||||
|
|
||||||
|
Elasticsearch uses
|
||||||
|
https://en.wikipedia.org/wiki/Seccomp[seccomp] in Linux,
|
||||||
|
https://www.chromium.org/developers/design-documents/sandbox/osx-sandboxing-design[Seatbelt]
|
||||||
|
in macOS, and
|
||||||
|
https://msdn.microsoft.com/en-us/library/windows/desktop/ms684147[ActiveProcessLimit]
|
||||||
|
on Windows to prevent Elasticsearch from forking or executing other processes.
|
||||||
|
|
||||||
|
Below this we describe the security settings for scripts and how you can
|
||||||
|
change from the defaults described above. You should be very, very careful
|
||||||
|
when allowing more than the defaults. Any extra permissions weakens the total
|
||||||
|
security of the Elasticsearch deployment.
|
||||||
|
|
||||||
[[security-script-source]]
|
[[security-script-source]]
|
||||||
[float]
|
[float]
|
||||||
=== Script source settings
|
=== Script source settings
|
||||||
|
|
||||||
Scripts may be enabled or disabled depending on their source: `inline`,
|
Which scripts Elasticsearch will execute where is controlled by settings
|
||||||
`stored` in the cluster state, or from a `file` on each node in the cluster.
|
starting with `scripts.`. The simplest settings allow scripts to be enabled
|
||||||
Each of these settings takes one of these values:
|
or disabled based on where they are stored. For example:
|
||||||
|
|
||||||
|
|
||||||
[horizontal]
|
|
||||||
`false`:: Scripting is disabled.
|
|
||||||
`true`:: Scripting is enabled.
|
|
||||||
|
|
||||||
The default values are the following:
|
|
||||||
|
|
||||||
[source,yaml]
|
[source,yaml]
|
||||||
-----------------------------------
|
-----------------------------------
|
||||||
script.inline: false
|
script.inline: false <1>
|
||||||
script.stored: false
|
script.stored: false <2>
|
||||||
script.file: true
|
script.file: true <3>
|
||||||
-----------------------------------
|
-----------------------------------
|
||||||
|
<1> Refuse to run scripts provided inline in the API.
|
||||||
|
<2> Refuse to run scripts stored using the API.
|
||||||
|
<3> Run scripts found on the filesystem in `/etc/elasticsearch/scripts`
|
||||||
|
(rpm or deb) or `config/scripts` (zip or tar).
|
||||||
|
|
||||||
NOTE: Global scripting settings affect the `mustache` scripting language.
|
NOTE: These settings override the defaults mentioned
|
||||||
<<search-template,Search templates>> internally use the `mustache` language,
|
<<modules-scripting-security-do-no-weaken, above>>. Recreating the defaults
|
||||||
and will still be enabled by default as the `mustache` engine is sandboxed,
|
requires more fine grained settings described <<security-script-fine, below>>.
|
||||||
but they will be enabled/disabled according to fine-grained settings
|
|
||||||
specified in `elasticsearch.yml`.
|
|
||||||
|
|
||||||
[[security-script-context]]
|
[[security-script-context]]
|
||||||
[float]
|
[float]
|
||||||
|
@ -102,15 +144,13 @@ script.plugin: false
|
||||||
=== Fine-grained script settings
|
=== Fine-grained script settings
|
||||||
|
|
||||||
First, the high-level script settings described above are applied in order
|
First, the high-level script settings described above are applied in order
|
||||||
(context settings have precedence over source settings). Then, fine-grained
|
(context settings have precedence over source settings). Then fine-grained
|
||||||
settings which include the script language take precedence over any high-level
|
settings which include the script language take precedence over any high-level
|
||||||
settings.
|
settings. They have two forms:
|
||||||
|
|
||||||
Fine-grained settings have the form:
|
|
||||||
|
|
||||||
[source,yaml]
|
[source,yaml]
|
||||||
------------------------
|
------------------------
|
||||||
script.engine.{lang}.{source}.{context}: true|false
|
script.engine.{lang}.{inline|file|stored}.{context}: true|false
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
And
|
And
|
||||||
|
@ -135,121 +175,6 @@ script.engine.painless.stored.aggs: true <3>
|
||||||
script.engine.mustache.stored.search: true <4>
|
script.engine.mustache.stored.search: true <4>
|
||||||
-----------------------------------
|
-----------------------------------
|
||||||
<1> Disable all scripting from any source.
|
<1> Disable all scripting from any source.
|
||||||
<2> Allow inline Groovy scripts for all operations
|
<2> Allow inline Painless scripts for all operations.
|
||||||
<3> Allow stored Groovy scripts to be used for search and aggregations.
|
<3> Allow stored Painless scripts to be used for search and aggregations.
|
||||||
<4> Allow stored Mustache templates to be used for search.
|
<4> Allow stored Mustache templates to be used for search.
|
||||||
|
|
||||||
[[java-security-manager]]
|
|
||||||
[float]
|
|
||||||
=== Java Security Manager
|
|
||||||
|
|
||||||
Elasticsearch runs with the https://docs.oracle.com/javase/tutorial/essential/environment/security.html[Java Security Manager]
|
|
||||||
enabled by default. The security policy in Elasticsearch locks down the
|
|
||||||
permissions granted to each class to the bare minimum required to operate.
|
|
||||||
The benefit of doing this is that it severely limits the attack vectors
|
|
||||||
available to a hacker.
|
|
||||||
|
|
||||||
Restricting permissions is particularly important with scripting languages
|
|
||||||
like Groovy which is designed to do anything that can be done
|
|
||||||
in Java itself, including writing to the file system, opening sockets to
|
|
||||||
remote servers, etc.
|
|
||||||
|
|
||||||
[float]
|
|
||||||
=== Script Classloader Whitelist
|
|
||||||
|
|
||||||
Scripting languages are only allowed to load classes which appear in a
|
|
||||||
hardcoded whitelist that can be found in
|
|
||||||
https://github.com/elastic/elasticsearch/blob/{branch}/core/src/main/java/org/elasticsearch/script/ClassPermission.java[`org.elasticsearch.script.ClassPermission`].
|
|
||||||
|
|
||||||
|
|
||||||
In a script, attempting to load a class that does not appear in the whitelist
|
|
||||||
_may_ result in a `ClassNotFoundException`, for instance this script:
|
|
||||||
|
|
||||||
[source,js]
|
|
||||||
------------------------------
|
|
||||||
GET _search
|
|
||||||
{
|
|
||||||
"script_fields": {
|
|
||||||
"the_hour": {
|
|
||||||
"script": "use(java.math.BigInteger); new BigInteger(1)"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
------------------------------
|
|
||||||
|
|
||||||
will return the following exception:
|
|
||||||
|
|
||||||
[source,js]
|
|
||||||
------------------------------
|
|
||||||
{
|
|
||||||
"reason": {
|
|
||||||
"type": "script_exception",
|
|
||||||
"reason": "failed to run inline script [use(java.math.BigInteger); new BigInteger(1)] using lang [painless]",
|
|
||||||
"caused_by": {
|
|
||||||
"type": "no_class_def_found_error",
|
|
||||||
"reason": "java/math/BigInteger",
|
|
||||||
"caused_by": {
|
|
||||||
"type": "class_not_found_exception",
|
|
||||||
"reason": "java.math.BigInteger"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
------------------------------
|
|
||||||
|
|
||||||
[float]
|
|
||||||
== Dealing with Java Security Manager issues
|
|
||||||
|
|
||||||
If you encounter issues with the Java Security Manager, you have two options
|
|
||||||
for resolving these issues:
|
|
||||||
|
|
||||||
[float]
|
|
||||||
=== Fix the security problem
|
|
||||||
|
|
||||||
The safest and most secure long term solution is to change the code causing
|
|
||||||
the security issue. We recognise that this may take time to do correctly and
|
|
||||||
so we provide the following two alternatives.
|
|
||||||
|
|
||||||
[float]
|
|
||||||
=== Customising the classloader whitelist
|
|
||||||
|
|
||||||
The classloader whitelist can be customised by tweaking the local Java
|
|
||||||
Security Policy either:
|
|
||||||
|
|
||||||
* system wide: `$JAVA_HOME/lib/security/java.policy`,
|
|
||||||
* for just the `elasticsearch` user: `/home/elasticsearch/.java.policy`
|
|
||||||
* by adding a system property to the <<jvm-options,jvm.options>> configuration: `-Djava.security.policy=someURL`, or
|
|
||||||
* via the `ES_JAVA_OPTS` environment variable with `-Djava.security.policy=someURL`:
|
|
||||||
+
|
|
||||||
[source,js]
|
|
||||||
---------------------------------
|
|
||||||
export ES_JAVA_OPTS="${ES_JAVA_OPTS} -Djava.security.policy=file:///path/to/my.policy`
|
|
||||||
./bin/elasticsearch
|
|
||||||
---------------------------------
|
|
||||||
|
|
||||||
Permissions may be granted at the class, package, or global level. For instance:
|
|
||||||
|
|
||||||
[source,js]
|
|
||||||
----------------------------------
|
|
||||||
grant {
|
|
||||||
permission org.elasticsearch.script.ClassPermission "java.util.Base64"; // allow class
|
|
||||||
permission org.elasticsearch.script.ClassPermission "java.util.*"; // allow package
|
|
||||||
permission org.elasticsearch.script.ClassPermission "*"; // allow all (disables filtering basically)
|
|
||||||
};
|
|
||||||
----------------------------------
|
|
||||||
|
|
||||||
[TIP]
|
|
||||||
======================================
|
|
||||||
|
|
||||||
Before adding classes to the whitelist, consider the security impact that it
|
|
||||||
will have on Elasticsearch. Do you really need an extra class or can your code
|
|
||||||
be rewritten in a more secure way?
|
|
||||||
|
|
||||||
It is quite possible that we have not whitelisted a generically useful and
|
|
||||||
safe class. If you have a class that you think should be whitelisted by
|
|
||||||
default, please open an issue on GitHub and we will consider the impact of
|
|
||||||
doing so.
|
|
||||||
|
|
||||||
======================================
|
|
||||||
|
|
||||||
See http://docs.oracle.com/javase/7/docs/technotes/guides/security/PolicyFiles.html for more information.
|
|
||||||
|
|
|
@ -28,8 +28,8 @@ documentation of the mustache project].
|
||||||
|
|
||||||
NOTE: The mustache language is implemented in elasticsearch as a sandboxed
|
NOTE: The mustache language is implemented in elasticsearch as a sandboxed
|
||||||
scripting language, hence it obeys settings that may be used to enable or
|
scripting language, hence it obeys settings that may be used to enable or
|
||||||
disable scripts per language, source and operation as described in
|
disable scripts per language, source and operation as described in the
|
||||||
<<enable-dynamic-scripting, scripting docs>>
|
<<security-script-source, scripting docs>>
|
||||||
|
|
||||||
[float]
|
[float]
|
||||||
==== More template examples
|
==== More template examples
|
||||||
|
|
Loading…
Reference in New Issue