def __init__(self): self.utils = Utils() self.r = None try: self.conn_pool = redis.ConnectionPool(host=config.RDS_HOST, port=config.RDS_PORT, db=0) self.r = redis.Redis(connection_pool=self.conn_pool) except TimeoutError: logger.error('Redis Connection Timed Out!') sys.exit(1)
def get_json(self, key): tmp = {} data = self.r.get(key) if data: try: tmp = pickle.loads(data) #logger.info('Getting json from ' + str(key)) except: logger.error('Error retrieving json') return tmp
def get_domains(self): domains = [] data = self.r.get('domains') if data: try: domains = pickle.loads(data) #logger.info('domains: ' + str(domains)) except: logger.error('Error retrieving domains') return domains
def get_inventory_data(self): kv = {} for ip_key in self.r.scan_iter(match="inv*"): data = self.r.get(ip_key) if data: try: result = pickle.loads(data) kv[ip_key.decode('utf-8')] = result except: logger.error('Error retrieving key') return kv
def submit_webhook(self, webhook, cfg, data={}): logger.info('Sending the webhook...') try: data = {'status':'done', 'vulnerabilities':data, 'scan_config':cfg} requests.post(webhook, json=data, headers={'User-Agent':USER_AGENT, 'Content-Type':'application/json'}, verify=False) return True except Exception as e: logger.error('Could not submit webhook: {}'.format(e)) return
def redis_attack(self, ip, port, password): try: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((ip, port)) payload = 'AUTH {}\n'.format(password) s.sendall(payload.encode()) data = s.recv(1024) logger.info(data) if 'OK' in data.decode('utf-8'): return True except Exception as e: logger.error(e) return False finally: s.close() return False
def clean_username(self): """ Deny creation of a User if the username doesn't exist in LDAP. """ username = self.cleaned_data['username'] try: results = search_ldap_for_user(username) except ldap.LDAPError: logger.error('user.ldap.new.ldap_lookup_failed', target_user=username) raise forms.ValidationError(self.error_messages['ldap_lookup_failed']) else: if results: return username else: raise forms.ValidationError(self.error_messages['not_in_ldap'])
def populate_user_from_ldap(user): """ Populate the given User object's personal info from LDAP. """ try: _, ldap_attrs = search_ldap_for_user(user.username) user.first_name = ldap_attrs['givenName'][0] user.last_name = ldap_attrs['sn'][0] user.email = ldap_attrs['CAPPrimaryEmail'][0] except (IndexError, KeyError, TypeError, ldap.LDAPError) as err: # If any of these attrs are missing, or anything goes wrong, fail gracefully instead of crashing. # These attrs are not essential, and will be updated if possible the next time this User is saved. logger.error('user.update_from_ldap.failed', target_user=user.username, reason="{}: {}".format(err.__class__.__name__, err)) else: logger.info('user.update_from_ldap.success', target_user=user.username, first_name=user.first_name, last_name=user.last_name, email=user.email)
def get_scan_data(self): kv = {} ip_key = None for k in self.r.scan_iter(match="sca_*"): ip_key = k.decode('utf-8') break # only get one key if ip_key: data = self.r.get(ip_key) if data: try: result = pickle.loads(data) if result: ip = ip_key.split('_')[1] kv[ip] = result self.r.delete(ip_key) except pickle.UnpicklingError as e: logger.error('Error unpickling %s' % e) logger.debug('IP Key: %s' % ip_key) return kv
def submit_slack(self, hook, data={}): try: if not data: logger.info( 'Did not send slack notification, scan did not yield any result.' ) return fields = [] for _, value in data.items(): if value['rule_sev'] == 0: continue for k, v in value.items(): if not v: v = 'N/A' fields.append({'title': k, 'value': v, 'short': False}) slack_data = { "color": '#000000', "pretext": "<!channel> NERVE Notification", "author_name": ':warning: Notification', "title": 'NERVE Report', "fields": fields, } response = requests.post(hook, data=json.dumps(slack_data)) if response.status_code != 200: logger.error('Could not submit slack hook: {}'.format( response.text)) else: logger.info('Submitted slack hook') except Exception as e: logger.error('Could not submit slack hook: {}'.format(e)) return
def submit_webhook(self, webhook, cfg, data={}): logger.info('Sending the webhook and writing to tmp file...') try: #obj = json.load(data) # load json data #obj = obj['ip', 'port', 'rule_sev', 'rule_details'] # choose only required paths to webhook #write file to OS f = open("/opt/nerve/tmp/myfile.txt", "w") #create file f.write(str(data)) # write to file f.close() #close #below block with code to execute binary hooker with cmd cat /opt/nerve/tmp/myfile.txt | tr ',' '\n' | tr '{' '\n' | grep -e "'ip':" -e "'rule_sev':" -e "'rule_details':" | awk 'NR%3{printf "%s ",$0;next;}1' | grep -vi "'rule_sev': 0" | grep -vi "'rule_sev': 1" | grep -vi "'rule_sev': 2" | tr -d "'" | tr -s " " | sed 's/rule_sev: //g' | sed 's/rule_details/details/g' stream = os.popen('bash /opt/nerve/tmp/hooker') getlines1 = stream.readlines()[0:20] output1 = "".join(getlines1) stream.close() stream = os.popen('bash /opt/nerve/tmp/hooker') getlines2 = stream.readlines()[21:41] output2 = "".join(getlines2) stream.close() stream = os.popen('bash /opt/nerve/tmp/hooker') getlines3 = stream.readlines()[42:62] output3 = "".join(getlines3) stream.close() stream = os.popen('bash /opt/nerve/tmp/hooker') getlines4 = stream.readlines()[63:84] output4 = "".join(getlines4) stream.close() stream = os.popen('bash /opt/nerve/tmp/hooker') getlines5 = stream.readlines()[85:105] output5 = "".join(getlines5) stream.close() #done #sample_string = json.dumps(data) #discord limit to put only 2000 symbols webhook2 = DiscordWebhook(url=webhook, content=output1[0:1998]) response = webhook2.execute() webhook2 = DiscordWebhook(url=webhook, content=output2[0:1998]) response = webhook2.execute() webhook2 = DiscordWebhook(url=webhook, content=output3[0:1998]) response = webhook2.execute() webhook2 = DiscordWebhook(url=webhook, content=output4[0:1998]) response = webhook2.execute() webhook2 = DiscordWebhook(url=webhook, content=output5[0:1998]) response = webhook2.execute() #this is an implementation of nuclei scanner for nerve. logger.info('Starting ipmaker with httprobe to define nuclei targets ~ 3 min...') process = subprocess.Popen("/opt/nerve/tmp/ipmaker") # бинарь 1 process.wait() logger.info('Starting nucleizer for nuclei scan ~ 20 min...') process2 = subprocess.Popen("/opt/nerve/tmp/nucleizer") # бинарь 2 process2.wait() logger.info('Report nuclei issues to discord...') reader = open("/opt/nerve/tmp/nuclei-output.txt", "r") #read file to submit in discord outnuclei1 = reader.readlines()[0:20] output1 = "".join(outnuclei1) reader.close() reader = open("/opt/nerve/tmp/nuclei-output.txt", "r") outnuclei2 = reader.readlines()[21:41] output2 = "".join(outnuclei2) reader.close() reader = open("/opt/nerve/tmp/nuclei-output.txt", "r") outnuclei3 = reader.readlines()[42:62] output3 = "".join(outnuclei3) reader.close() reader = open("/opt/nerve/tmp/nuclei-output.txt", "r") outnuclei4 = reader.readlines()[63:84] output4 = "".join(outnuclei4) reader.close() reader = open("/opt/nerve/tmp/nuclei-output.txt", "r") outnuclei5 = reader.readlines()[85:105] output5 = "".join(outnuclei5) reader.close() webhooknuclei = DiscordWebhook(url=webhook, content=output1[0:1998]) response = webhooknuclei.execute() webhooknuclei = DiscordWebhook(url=webhook, content=output2[0:1998]) response = webhooknuclei.execute() webhooknuclei = DiscordWebhook(url=webhook, content=output3[0:1998]) response = webhooknuclei.execute() webhooknuclei = DiscordWebhook(url=webhook, content=output4[0:1998]) response = webhooknuclei.execute() webhooknuclei = DiscordWebhook(url=webhook, content=output5[0:1998]) response = webhooknuclei.execute() logger.info('Sleeping 5 mins to avoid angry admins...') time.sleep(1800) #commit rows above to disable nuclei scanner return True # data = {'status':'done', 'vulnerabilities':data, 'scan_config':cfg} # requests.post(webhook, # json=data, # headers={'User-Agent':USER_AGENT, # 'Content-Type':'application/json'}, # verify=False) # return True except Exception as e: logger.error('Could not submit webhook: {}'.format(e)) return
def http_request(self, ip, port, method="GET", params=None, data=None, json=None, headers=None, follow_redirects=True, timeout=None, uri='/'): resp = None if headers: self.headers = {**headers, **self.headers} if method not in ('GET', 'POST', 'OPTIONS', 'PUT', 'DELETE', 'HEAD'): logger.error('HTTP Method is not supported.') return if not timeout: timeout = self.global_timeout url = 'http://{}:{}{}'.format(ip, port, uri) if port == 443 or port == 8443 or '443' in str(port): url = 'https://{}:{}{}'.format(ip, port, uri) try: if method == 'GET': resp = requests.get(url, verify=False, timeout=timeout, params=params, allow_redirects=follow_redirects, headers=self.headers) elif method == 'PUT': resp = requests.put(url, verify=False, timeout=timeout, params=params, data=data, json=json, allow_redirects=follow_redirects, headers=self.headers) elif method == 'POST': resp = requests.post(url, verify=False, timeout=timeout, params=params, data=data, json=json, allow_redirects=follow_redirects, headers=self.headers) elif method == 'OPTIONS': resp = requests.options(url, verify=False, timeout=timeout, params=params, allow_redirects=follow_redirects, headers=self.headers) elif method == 'DELETE': resp = requests.delete(url, verify=False, timeout=timeout, params=params, data=data, json=json, allow_redirects=follow_redirects, headers=self.headers) elif method == 'HEAD': resp = requests.head(url, verify=False, timeout=timeout, params=params, allow_redirects=follow_redirects, headers=self.headers) else: # Default to GET. resp = requests.get(url, verify=False, timeout=timeout, params=params, data=data, json=json, allow_redirects=follow_redirects, headers=self.headers) except requests.exceptions.ConnectTimeout: logger.debug('http_request {} {} (Timeout)'.format(ip, port)) except urllib3.exceptions.MaxRetryError: logger.debug('http_request {} {} (MaxRetryError)'.format(ip, port)) except requests.exceptions.SSLError: logger.debug('http_request {} {} (SSL Error)'.format(ip, port)) except requests.exceptions.ConnectionError as e: logger.debug('http_request {} {} (Connection Error: {})'.format( ip, port, e)) except requests.exceptions.Timeout: logger.debug('http_request {} {} {} (Timeout)'.format( ip, port, url)) except requests.exceptions.ReadTimeout: logger.debug('http_request {} {} (Read Timeout)'.format(ip, port)) except ProtocolError: logger.debug('http_request {} {} (Protocol Error)'.format( ip, port)) except RemoteDisconnected: logger.debug('http_request {} {} (Remote Disconnected)'.format( ip, port)) except Exception as e: logger.debug('http_request {} {} (Unknown Error: {})'.format( ip, port, e)) return resp
def scan(self, hosts, max_ports, custom_ports, interface=None): data = {} hosts = ' '.join(hosts.keys()) extra_args = '' scan_cmdline = 'unpriv_scan' ports = '' if custom_ports: ports = '-p {}'.format(','.join([str(p) for p in set(custom_ports)])) elif max_ports: ports = '--top-ports {}'.format(max_ports) else: ports = '--top-ports 100' if interface: extra_args += '-e {}'.format(interface) if self.utils.is_user_root(): scan_cmdline = 'priv_scan' result = {} try: result = self.nmap.scan(hosts, arguments='{} {} {}'.format(self.nmap_args[scan_cmdline], ports, extra_args)) except nmap.nmap.PortScannerError as e: logger.error('Error with scan. {}'.format(e)) if 'scan' in result: for host, res in result['scan'].items(): data[host] = {} data[host]['status'] = res['status']['state'] data[host]['status_reason'] = res['status']['reason'] data[host]['domain'] = None data[host]['os'] = None for i in res['hostnames']: if i['type'] == 'user': data[host]['domain'] = i['name'] break if 'osmatch' in res and res['osmatch']: for match in res['osmatch']: if int(match['accuracy']) >= 90: data[host]['os'] = match['name'] break if 'tcp' in res: data[host]['port_data'] = {} data[host]['ports'] = set() for port, values in res['tcp'].items(): if port and values['state'] == 'open': data[host]['ports'].add(port) data[host]['port_data'][port] = {} data[host]['port_data'][port]['cpe'] = values['cpe'] data[host]['port_data'][port]['module'] = values['name'] data[host]['port_data'][port]['state'] = values['state'] data[host]['port_data'][port]['version'] = values['version'] data[host]['port_data'][port]['product'] = values['product'] return data