mirror of
https://github.com/j3ssie/osmedeus.git
synced 2026-08-20 22:52:32 +02:00
327 lines
11 KiB
Python
327 lines
11 KiB
Python
from api.models import *
|
|
from workflow import general, direct, direct_list
|
|
from core import utils
|
|
|
|
|
|
def parse_special_line(line):
|
|
parts = line.split(';;')
|
|
jsonl = {}
|
|
for part in parts:
|
|
key = part.split('|')[0].lower()
|
|
value = ''.join(part.split('|')[1:])
|
|
jsonl[key] = value
|
|
return jsonl
|
|
|
|
|
|
def update_field(default, value, update_type='partial'):
|
|
final_value = ''
|
|
if update_type.lower() == 'full':
|
|
final_value = value
|
|
if default == 'N/A' or default == '' or default == 'None':
|
|
final_value = value.strip(',')
|
|
else:
|
|
final_value = default.strip(',') + ',' + value.strip(',')
|
|
|
|
if ',' in final_value:
|
|
results = [x.strip() for x in final_value.split(',')]
|
|
final_value = ",".join(list(set(results)))
|
|
return final_value
|
|
|
|
|
|
def clean_up(record):
|
|
model_fields = ['domain', 'ip_address', 'technologies', 'ports', 'workspace', 'paths', 'screenshot', 'note', 'checksum']
|
|
keys = list(record.keys())
|
|
for key in keys:
|
|
if key not in model_fields:
|
|
del record[key]
|
|
return record
|
|
|
|
|
|
def parse_summary_field(instance, jsonl, update_type):
|
|
# just something we don't want to update
|
|
blacklist = ['domain']
|
|
record = instance.as_json()
|
|
checksum = record.get('checksum')
|
|
for key, value in jsonl.items():
|
|
if key not in blacklist:
|
|
record[key] = update_field(record[key], str(value), update_type)
|
|
record = clean_up(record)
|
|
updated = Summaries.objects.filter(checksum=checksum).update(**record)
|
|
|
|
|
|
def import_domain_summary(jsonl, workspace, update_type):
|
|
# print(jsonl)
|
|
domain = jsonl.get('domain', None)
|
|
if domain is None:
|
|
domain = jsonl.get('ip_address')
|
|
instance, created = Summaries.objects.get_or_create(domain=domain, workspace=workspace)
|
|
|
|
parse_summary_field(instance, jsonl, update_type)
|
|
|
|
|
|
# Summaries part
|
|
def parse_domains(line):
|
|
if utils.is_json(line.strip()):
|
|
jsonl = utils.get_json(line)
|
|
elif ';;' in line.strip():
|
|
jsonl = parse_special_line(line)
|
|
else:
|
|
jsonl = {'domain': line.strip()}
|
|
return jsonl
|
|
|
|
|
|
# remove report part
|
|
def removeReport(speed):
|
|
if speed.lower() in 'report':
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
|
|
def clean_input(raw_input, module='general'):
|
|
if 'general' in module.lower():
|
|
return utils.get_domain(raw_input)
|
|
|
|
elif 'dir' in module.lower():
|
|
return raw_input
|
|
|
|
|
|
def gen_default_config(config_path):
|
|
config_path = utils.absolute_path(config_path)
|
|
utils.file_copy(utils.TEMPLATE_SERVER_CONFIG, config_path)
|
|
|
|
configs = utils.just_read_config(config_path, raw=True)
|
|
|
|
workspaces = utils.join_path(utils.get_parent(
|
|
utils.DEAFULT_CONFIG_PATH), 'workspaces')
|
|
plugins_path = utils.join_path(utils.ROOT_PATH, 'plugins')
|
|
go_path = utils.join_path(utils.ROOT_PATH, 'plugins/go')
|
|
data_path = utils.join_path(utils.ROOT_PATH, 'data')
|
|
alias_path = utils.join_path(utils.ROOT_PATH, 'lib/alias')
|
|
|
|
# set some path
|
|
configs.set('Enviroments', 'workspaces', workspaces)
|
|
configs.set('Enviroments', 'plugins_path', plugins_path)
|
|
configs.set('Enviroments', 'data_path', data_path)
|
|
configs.set('Enviroments', 'alias_path', alias_path)
|
|
configs.set('Enviroments', 'go_path', go_path)
|
|
|
|
# set some tokens
|
|
github_api_key = utils.get_enviroment("GITHUB_API_KEY")
|
|
slack_bot_token = utils.get_enviroment("SLACK_BOT_TOKEN")
|
|
log_channel = utils.get_enviroment("LOG_CHANNEL")
|
|
status_channel = utils.get_enviroment("STATUS_CHANNEL")
|
|
report_channel = utils.get_enviroment("REPORT_CHANNEL")
|
|
stds_channel = utils.get_enviroment("STDS_CHANNEL")
|
|
verbose_report_channel = utils.get_enviroment("VERBOSE_REPORT_CHANNEL")
|
|
configs.set('Enviroments', 'github_api_key', github_api_key)
|
|
configs.set('Slack', 'slack_bot_token', slack_bot_token)
|
|
configs.set('Slack', 'log_channel', log_channel)
|
|
configs.set('Slack', 'status_channel', status_channel)
|
|
configs.set('Slack', 'report_channel', report_channel)
|
|
configs.set('Slack', 'stds_channel', stds_channel)
|
|
configs.set('Slack', 'verbose_report_channel', verbose_report_channel)
|
|
|
|
# monitor mode
|
|
backups = utils.join_path(utils.get_parent(
|
|
utils.DEAFULT_CONFIG_PATH), 'backups')
|
|
utils.make_directory(backups)
|
|
|
|
monitors = utils.join_path(utils.get_parent(
|
|
utils.DEAFULT_CONFIG_PATH), 'monitors')
|
|
utils.make_directory(monitors)
|
|
|
|
configs.set('Monitor', 'monitors', monitors)
|
|
configs.set('Monitor', 'backups', backups)
|
|
monitor_level = utils.get_enviroment("monitor_level", 'final')
|
|
configs.set('Monitor', 'monitor_level', monitor_level)
|
|
|
|
# monitor bot
|
|
slack_monitor_token = utils.get_enviroment("SLACK_MONITOR_TOKEN")
|
|
new_channel = utils.get_enviroment("NEW_CHANNEL")
|
|
new_name = utils.get_enviroment("NEW_NAME")
|
|
missing_channel = utils.get_enviroment("MISSING_CHANNEL")
|
|
missing_name = utils.get_enviroment("MISSING_NAME")
|
|
configs.set('Monitor', 'slack_monitor_token', slack_monitor_token)
|
|
configs.set('Monitor', 'new_channel', new_channel)
|
|
configs.set('Monitor', 'new_name', new_name)
|
|
configs.set('Monitor', 'missing_channel', missing_channel)
|
|
configs.set('Monitor', 'missing_name', missing_name)
|
|
|
|
# write it again
|
|
with open(config_path, 'w+') as configfile:
|
|
configs.write(configfile)
|
|
|
|
# read it again and return
|
|
options = utils.just_read_config(config_path)
|
|
return options
|
|
|
|
|
|
def load_default_config(config_file=None, forced_reload=False):
|
|
if not config_file:
|
|
config_file = '~/.osmedeus/server.conf'
|
|
options = utils.just_read_config(config_file)
|
|
|
|
# no config found generate one from default config
|
|
if not options:
|
|
options = gen_default_config(config_file)
|
|
if forced_reload:
|
|
options = gen_default_config(config_file)
|
|
|
|
# looping and adding field to db
|
|
for key, value in options.items():
|
|
item = {
|
|
'name': key,
|
|
'value': value,
|
|
'alias': key,
|
|
'desc': key,
|
|
}
|
|
instance, created = Configurations.objects.get_or_create(
|
|
name=key)
|
|
Configurations.objects.filter(name=key).update(**item)
|
|
return options
|
|
|
|
|
|
def get_stateless_options(config_file=None):
|
|
if config_file:
|
|
options = utils.just_read_config(config_file)
|
|
else:
|
|
raw_options = list(Configurations.objects.values_list('name', 'value'))
|
|
options = {}
|
|
for item in raw_options:
|
|
options[item[0]] = item[1]
|
|
return options
|
|
|
|
|
|
# get variable to replace in the command
|
|
def get_stateful_options(workspace):
|
|
# finding workspace in db
|
|
record = Workspaces.objects.filter(workspace=workspace)
|
|
if not record.first():
|
|
record = Workspaces.objects.filter(target=workspace)
|
|
if not record.first():
|
|
record = Workspaces.objects.filter(raw_target=workspace)
|
|
|
|
if not record.first():
|
|
return False
|
|
stateless_options = get_stateless_options()
|
|
|
|
# options = record.as_json()
|
|
options = {**record.first().as_json(), **stateless_options}
|
|
argument_options = {}
|
|
|
|
# just upper all key
|
|
for key in options.keys():
|
|
argument_options[key.upper()] = options.get(key)
|
|
|
|
return argument_options
|
|
|
|
|
|
# @TODO should be done dynamic later
|
|
def get_modules(mode='general'):
|
|
general = [
|
|
'SubdomainScanning',
|
|
'Recon',
|
|
'ScreenShot',
|
|
'TakeOverScanning',
|
|
'AssestFinding',
|
|
'IPSpace',
|
|
'CorsScan',
|
|
'PortScan',
|
|
'VulnScan'
|
|
]
|
|
if 'general' in mode.lower():
|
|
return ','.join(general)
|
|
|
|
|
|
# really parse command from classes
|
|
def really_commands(mode):
|
|
modules = utils.get_classes('workflow.{0}'.format(mode))
|
|
for module in modules:
|
|
# get RCE if you can edit general file in workflow folder :)
|
|
module_name = module[0].strip()
|
|
module_object = eval('{0}.{1}'.format(mode, module_name))
|
|
# parsing commands
|
|
try:
|
|
routines = module_object.commands
|
|
except:
|
|
continue
|
|
for routine, commands in routines.items():
|
|
for command in commands:
|
|
item = command
|
|
item['mode'] = mode
|
|
item['speed'] = routine
|
|
item['module'] = module_name
|
|
item['alias'] = module_name + "__" + routine.lower() + "__" + \
|
|
str(item.get('banner')).lower()
|
|
Commands.objects.create(**item)
|
|
|
|
reports = module_object.reports
|
|
parse_report(reports, module_name, mode)
|
|
|
|
|
|
def internal_parse_commands(override=True):
|
|
if override:
|
|
Commands.objects.all().delete()
|
|
ReportsSkeleton.objects.all().delete()
|
|
really_commands('general')
|
|
really_commands('direct')
|
|
really_commands('direct_list')
|
|
|
|
|
|
def parse_report(reports, module, mode):
|
|
if type(reports) == str:
|
|
item = {
|
|
'report_path': reports,
|
|
'report_type': 'bash',
|
|
'module': module,
|
|
'mode': mode,
|
|
}
|
|
ReportsSkeleton.objects.create(**item)
|
|
elif type(reports) == list:
|
|
for report in reports:
|
|
item = {
|
|
'report_path': report.get('path'),
|
|
'report_type': report.get('type', 'bash'),
|
|
'note': report.get('note', ''),
|
|
'module': module,
|
|
'mode': mode,
|
|
}
|
|
ReportsSkeleton.objects.create(**item)
|
|
|
|
|
|
# parsing skeleton commands
|
|
def parse_commands(command_path):
|
|
if not utils.not_empty_file(command_path):
|
|
return False
|
|
|
|
content = utils.just_read(command_path, get_json=True)
|
|
if not content:
|
|
return False
|
|
|
|
modules = content.keys()
|
|
for module in modules:
|
|
for speed, values in content.get(module).items():
|
|
if speed.lower() == 'report':
|
|
parse_report(values, module)
|
|
else:
|
|
for value in values:
|
|
if not value.get('cmd'):
|
|
continue
|
|
item = {
|
|
'cmd': value.get('cmd'),
|
|
'output_path': value.get('output_path'),
|
|
'std_path': value.get('std_path'),
|
|
'banner': str(value.get('banner')),
|
|
'module': module,
|
|
'cmd_type': value.get('cmd_type') if value.get('cmd_type') else 'single',
|
|
'speed': speed.lower(),
|
|
'alias': module + "__" + speed.lower() + "__" + str(value.get('banner')).lower(),
|
|
'chunk': value.get('chunk') if value.get('chunk') else 0,
|
|
}
|
|
Commands.objects.create(**item)
|
|
# print(modules)
|
|
return True
|
|
|
|
|