-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathcve-2019-15043.py
executable file
·121 lines (94 loc) · 3.93 KB
/
cve-2019-15043.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#!/usr/bin/env python3
import argparse
import requests
import re
G, B, R, W, M, C, end = '\033[92m', '\033[94m', '\033[91m', '\x1b[37m', '\x1b[35m', '\x1b[36m', '\033[0m'
info = end + W + "[-]" + W
good = end + G + "[+]" + C
bad = end + R + "[" + W + "!" + R + "]"
user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.90 Safari/537.36"
snapshot_endpoint = "api/snapshots"
def send_request(url, method):
""" sends an HTTP requset """
headers = {'User-Agent': user_agent}
try:
if method == "GET":
r = requests.get(url, headers=headers)
else:
data = ""
r = requests.post(url, headers=headers, data=data)
except Exception as e:
print(bad + " Problem with request! " + end)
print(e)
exit(-1)
if (r.status_code == 302):
print(bad + " Redirected. Try this instead: " +
r.headers['Location'] + end)
elif (r.status_code == 401):
print(bad + " Status: " + str(r.status_code) + end)
return(r.status_code)
elif (r.status_code == 415):
return(r.status_code)
elif (r.status_code == 200):
print(info + " Status: " + str(r.status_code) + end)
return(r.text)
else:
print(info + " Something went wrong! " + end)
print(bad + " Status: " + str(r.status_code) + str(r.content) + end)
exit(-1)
def check_version(grafana_server):
""" checks the version of the grafana server """
response = send_request(grafana_server+"/login", "GET")
print(info + " Checking for version..." + end)
r1 = re.search('[0-9]{1}\.[0-9]{1}\.[0-9]{1}', str(response))
print(info + " Grafana version appears to be: " + r1.group(0) + end)
target_version = r1.group(0)
if "5." in target_version :
fixed_version = '5.4.5'
else:
fixed_version = '6.3.4'
if compare_versions(fixed_version, target_version) == False:
print(bad + " Version seems to indicate it's probably not vulnerable." + end)
else:
print(good + " Version seems to indicate it might be vulnerable!" + end)
def compare_versions(fixed_version, target_version):
""" compares the version strings from the Grafana login page """
for i, j in zip(map(int, fixed_version.split(".")), map(int, target_version.split("."))):
if i == j:
continue
return i > j
return len(fixed_version.split(".")) > len(target_version.split("."))
def check_snapshots(grafana_server):
""" checks if snapshot api allows unauthenticated requests """
print(info + " Checking if snapshot api requires authentiation..." + end)
response = send_request(grafana_server+"/api/snapshots", "POST")
if (response) == 401:
print(bad + " Snapshot endpoint requires authentication! Host not vulnerable." + end)
elif (response) == 415:
print(good + " Snapshot endpoint doesn't seem to require authentication! Host may be vulnerable." + end)
else:
print(info + " Didn't received expected status code when checking snapshot API. Check again." + end)
return
def main():
""" main """
parser = argparse.ArgumentParser(
prog='cve-2019-15043.py', description='For checking if a Grafana instance is vunlerable to CVE-2019-15043')
parser.add_argument(
"-u", "--url", help="URL of the target Grafana instance e.g. '-u https://localhost:3000'")
parser.add_argument("-c", "--check-version",
help="Only check the Grafana version", action='store_true')
args = parser.parse_args()
if not args.url:
print(bad + " Missing parameters " + end)
parser.print_help()
exit(-1)
url = str(args.url)
print(info + " Testing " + url + "..." + end)
if args.check_version == True:
check_version(url)
exit(0)
else:
check_version(url)
check_snapshots(url)
if __name__ == "__main__":
main()