180 lines
7.3 KiB
Plaintext
180 lines
7.3 KiB
Plaintext
[[modules-scripting-security]]
|
|
=== Scripting and security
|
|
|
|
While Elasticsearch contributors make every effort to prevent scripts from
|
|
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.
|
|
|
|
[float]
|
|
=== 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.
|
|
|
|
[float]
|
|
=== Do not expose Elasticsearch directly to users
|
|
Do not expose Elasticsearch directly to users, instead have an application
|
|
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.
|
|
|
|
[float]
|
|
=== 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:
|
|
|
|
Good:
|
|
* Users type text into a search box and the text is sent directly to a
|
|
<<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.
|
|
|
|
Bad:
|
|
* Users can write arbitrary scripts, queries, `_search` requests.
|
|
* User actions make documents with structure defined by users.
|
|
|
|
[float]
|
|
[[modules-scripting-security-do-no-weaken]]
|
|
=== Do not weaken script security settings
|
|
By default Elasticsearch will run inline, stored, and filesystem scripts for
|
|
the builtin 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. The Elasticsearch committers do not support any
|
|
non-sandboxed scripting languages and using any would be 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.
|
|
|
|
|
|
[float]
|
|
[[modules-scripting-other-layers]]
|
|
=== 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]]
|
|
[float]
|
|
=== Script source settings
|
|
|
|
Which scripts Elasticsearch will execute where is controlled by settings
|
|
starting with `scripts.`. The simplest settings allow scripts to be enabled
|
|
or disabled based on where they are stored. For example:
|
|
|
|
[source,yaml]
|
|
-----------------------------------
|
|
script.inline: false <1>
|
|
script.stored: false <2>
|
|
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: These settings override the defaults mentioned
|
|
<<modules-scripting-security-do-no-weaken, above>>. Recreating the defaults
|
|
requires more fine grained settings described <<security-script-fine, below>>.
|
|
|
|
[[security-script-context]]
|
|
[float]
|
|
=== Script context settings
|
|
|
|
Scripting may also be enabled or disabled in different contexts in the
|
|
Elasticsearch API. The supported contexts are:
|
|
|
|
[horizontal]
|
|
`aggs`:: Aggregations
|
|
`search`:: Search api, Percolator API and Suggester API
|
|
`update`:: Update api
|
|
`plugin`:: Any plugin that makes use of scripts under the generic `plugin` category
|
|
|
|
Plugins can also define custom operations that they use scripts for instead
|
|
of using the generic `plugin` category. Those operations can be referred to
|
|
in the following form: `${pluginName}_${operation}`.
|
|
|
|
The following example disables scripting for `update` and `plugin` operations,
|
|
regardless of the script source or language. Scripts can still be executed
|
|
as part of `aggregations`, `search` and plugins execution though, as the above
|
|
defaults still get applied.
|
|
|
|
[source,yaml]
|
|
-----------------------------------
|
|
script.update: false
|
|
script.plugin: false
|
|
-----------------------------------
|
|
|
|
[[security-script-fine]]
|
|
[float]
|
|
=== Fine-grained script settings
|
|
|
|
First, the high-level script settings described above are applied in order
|
|
(context settings have precedence over source settings). Then fine-grained
|
|
settings which include the script language take precedence over any high-level
|
|
settings. They have two forms:
|
|
|
|
[source,yaml]
|
|
------------------------
|
|
script.engine.{lang}.{inline|file|stored}.{context}: true|false
|
|
------------------------
|
|
|
|
And
|
|
|
|
[source,yaml]
|
|
------------------------
|
|
script.engine.{lang}.{inline|file|stored}: true|false
|
|
------------------------
|
|
|
|
For example:
|
|
|
|
[source,yaml]
|
|
-----------------------------------
|
|
script.inline: false <1>
|
|
script.stored: false <1>
|
|
script.file: false <1>
|
|
|
|
script.engine.painless.inline: true <2>
|
|
script.engine.painless.stored.search: true <3>
|
|
script.engine.painless.stored.aggs: true <3>
|
|
|
|
script.engine.mustache.stored.search: true <4>
|
|
-----------------------------------
|
|
<1> Disable all scripting from any source.
|
|
<2> Allow inline Painless scripts for all operations.
|
|
<3> Allow stored Painless scripts to be used for search and aggregations.
|
|
<4> Allow stored Mustache templates to be used for search.
|