This repository was archived by the owner on Aug 1, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 37
/
Copy pathcli.py
292 lines (241 loc) · 9.84 KB
/
cli.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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
from os import makedirs, path, environ
import logging
import json
import sys
from shutil import copy
from enum import Enum
from sqlite3 import DatabaseError
import pkg_resources
from robot_api.robot import Robot
from robot_api.parse import parse_args, join_abs
from robot_api.config import load_config, generate_configs, tool_check, get_config
ROOT_DIR = path.join(environ.get("HOME","."),".drrobot")
generate_configs()
class Mode(Enum):
DOCKER = 1
ANSIBLE = 2
def setup_logger():
logger = logging.getLogger()
logger.setLevel(logging.NOTSET)
formatter = logging.Formatter(
'%(asctime)s [%(levelname)-5s|%(name)s] \t%(message)s')
handler = logging.FileHandler(
filename=join_abs(
ROOT_DIR,
"logs",
"drrobot.err"))
handler.setLevel(logging.ERROR)
handler.setFormatter(formatter)
logger.addHandler(handler)
handler = logging.FileHandler(
filename=join_abs(
ROOT_DIR,
"logs",
"drrobot.dbg"))
handler.setLevel(logging.DEBUG)
handler.setFormatter(formatter)
logger.addHandler(handler)
logging.getLogger("urllib3.connectionpool").disabled = True
return logger
def run():
try:
if not path.exists(join_abs(ROOT_DIR, "logs")):
makedirs(join_abs(ROOT_DIR, "logs"))
log = setup_logger()
tools = load_config(get_config())
parser = parse_args(**tools, root_dir=ROOT_DIR)
if not len(sys.argv) > 1:
parser.print_help()
sys.exit(1)
args = parser.parse_args()
log.debug(args)
tool_check()
drrobot = Robot(root_dir=ROOT_DIR,
user_config=get_config(),
**tools,
dns=getattr(args, 'dns', None),
proxy=getattr(args, 'proxy', None),
domain=getattr(args, 'domain', None),
verbose=getattr(args, 'verbose'),
dbfile=getattr(args, 'dbfile'),
verify=getattr(args, 'verify', None))
if not path.exists(join_abs(ROOT_DIR, "dbs")):
makedirs(join_abs(ROOT_DIR, "dbs"))
if getattr(args, 'domain', None):
if not path.exists(
join_abs(
ROOT_DIR,
"output",
getattr(
args,
'domain'))):
makedirs(join_abs(ROOT_DIR, "output", getattr(args, 'domain')))
if not path.exists(
join_abs(
ROOT_DIR,
"output",
getattr(
args,
'domain'),
"aggregated")):
makedirs(
join_abs(
ROOT_DIR,
"output",
getattr(
args,
'domain'),
"aggregated"))
if args.actions in "gather":
try:
drrobot._print("Beginning gather")
webtools = {
k: v for k,
v in tools.get("webtools").items() if getattr(
args,
k) if True}
drrobot._print(f"Webtools:\n{webtools}")
scanners_dockers = {k: v for k, v
in tools.get("scanners").items()
if getattr(args, k)
is True and Mode[v["mode"]] == Mode.DOCKER}
drrobot._print(f"Scanners as Dockers: \
{json.dumps(scanners_dockers, indent=4)}")
scanners_ansible = {k: v for k, v
in tools.get("scanners").items()
if getattr(args, k)
is True
and Mode[v["mode"]] == Mode.ANSIBLE}
drrobot._print(
f"Scanners as Ansible Play: \
{json.dumps(scanners_ansible, indent=4)}")
if not webtools and \
not scanners_ansible and \
not scanners_dockers:
print("[*] No scanners/webtools provided, exiting...")
parser.print_help()
sys.exit(0)
drrobot.gather(
webtools=webtools,
scanners_dockers=scanners_dockers,
scanners_ansible=scanners_ansible,
headers=getattr(
args,
"headers",
False))
except KeyError as e:
print(f"[!] Mode {e} not found. Please fix config file")
if args.actions in 'inspect':
try:
drrobot._print("Beginning inspection")
post_enum_dockers = {k: v for k, v
in tools.get("enumeration").items()
if getattr(args, k)
is True
and Mode[v["mode"]] == Mode.DOCKER}
drrobot._print(
f"Inspection dockers \
{json.dumps(post_enum_dockers, indent=4)}")
post_enum_ansible = {k: v for k, v
in tools.get("enumeration").items()
if getattr(args, k)
is True
and Mode[v["mode"]] == Mode.ANSIBLE}
drrobot._print(
f"Inspection ansible \
{json.dumps(post_enum_ansible, indent=4)}")
if not post_enum_ansible and not post_enum_dockers:
print("[*] No scanners/webtools provided, exiting...")
parser.print_help()
sys.exit(0)
except KeyError as e:
print(f"[!] Mode {e} not found. Please fix config file")
_file = getattr(args, 'file', None)
drrobot.inspection(
post_enum_ansible=post_enum_ansible,
post_enum_dockers=post_enum_dockers,
file=_file)
if args.actions in "upload":
filepath = getattr(args, "filepath")
if filepath is None:
print("No filepath provided, exiting...")
sys.exit(0)
elif not path.exists(filepath):
print("Filepath does not exists, exiting...")
sys.exit(0)
drrobot._print(f"Beginning upload with file path: {filepath}")
upload_dest = {k: v for k, v in tools.get("upload_dest").items() if
getattr(args, k) is True}
drrobot._print(
f"Upload tools: {json.dumps(upload_dest, indent=4)}")
drrobot.upload(filepath=filepath, upload_dest=upload_dest)
if args.actions in "rebuild":
files = getattr(args, "files", None)
if files is None:
files = []
def gen_dict_extract(key, var):
if hasattr(var, 'items'):
for k, v in var.items():
if k == key:
yield v
if isinstance(v, dict):
for result in gen_dict_extract(key, v):
yield result
elif isinstance(v, list):
for d in v:
for result in gen_dict_extract(key, d):
yield result
for output in gen_dict_extract("output_file", tools):
files += [output]
for folder in gen_dict_extract("output_folder", tools):
files += [folder]
drrobot.rebuild(files=files)
if args.actions in "output":
_format = getattr(args, "format")
output = getattr(args, "output")
# TODO implement other output formats
drrobot.generate_output(_format, output)
if args.actions in "dumpdb":
dbpath = getattr(args, "dbfile")
if path.exists(dbpath):
if not path.exists(
join_abs(
ROOT_DIR,
"output",
getattr(
args,
'domain'),
"headers")):
makedirs(
join_abs(
ROOT_DIR,
"output",
getattr(
args,
'domain'),
"headers"))
drrobot.dumpdb()
else:
print("[!] DB file does not exists, try running gather first")
if args.actions in "serve":
# TODO Add check for running container
print("Serving drrobot container. \
(Warning, you will have to stop the container on your own)"
)
drrobot.serve(server=tools.get("server"))
except json.JSONDecodeError as er:
print(f"[!] JSON load error, configuration file is bad.\n {er}")
log.error(er)
except DatabaseError as er:
print(f"[!] Something went wrong with SQLite\n {er}")
log.error(er)
except KeyboardInterrupt:
print("[!] KeyboardInterrup, exiting...")
except OSError as er:
log.error(er)
print(f"[!] e {er}")
except TypeError as er:
log.error(er)
print(f"[!] {er}")
if __name__ == "__main__":
run()