def cmd_usercheck(username, no_cache, verbose, wopen, output): habucfg = loadcfg() if verbose: logging.basicConfig(level=logging.INFO, format='%(message)s') if not no_cache: homedir = pwd.getpwuid(os.getuid()).pw_dir requests_cache.install_cache(homedir + '/.habu_requests_cache') logging.info('using cache on ' + homedir + '/.habu_requests_cache') existent = {} for site, url in urls.items(): u = url.format(username) logging.info(u) try: r = requests.head(u, allow_redirects=False) except Exception: continue if r.status_code == 200: if requests.head(url.format('zei4fee3q9'), allow_redirects=False).status_code == 200: logging.error( 'Received status 200 for user zei4fee3q9, maybe, the check needs to be fixed' ) else: existent[site] = u if wopen: webbrowser.open_new_tab(u) output.write(json.dumps(existent, indent=4)) output.write('\n')
def cmd_shodan(ip, no_cache, verbose, output): habucfg = loadcfg() if 'SHODAN_APIKEY' not in habucfg: print('You must provide a shodan apikey. Use the ~/.habu.json file (variable SHODAN_APIKEY), or export the variable HABU_SHODAN_APIKEY') sys.exit(1) if verbose: logging.basicConfig(level=logging.INFO, format='%(message)s') if not no_cache: homedir = pwd.getpwuid(os.getuid()).pw_dir requests_cache.install_cache(homedir + '/.habu_requests_cache') url = 'https://api.shodan.io/shodan/host/{}?key={}'.format(ip, habucfg['SHODAN_APIKEY']) r = requests.get(url) if r.status_code not in [200, 404]: print('ERROR', r) return False if r.status_code == 404: print("Not Found") return False data = r.json() output.write(json.dumps(data, indent=4)) output.write('\n')
def cmd_cymon_ip_timeline(ip, no_cache, verbose, output, pretty): """Simple cymon API client. Prints the JSON result of a cymon IP timeline query. Example: \b $ habu.cymon.ip.timeline 8.8.8.8 { "timeline": [ { "time_label": "Aug. 18, 2018", "events": [ { "description": "Posted: 2018-08-18 23:37:39 CEST IDS Alerts: 0 URLQuery Alerts: 1 ...", "created": "2018-08-18T21:39:07Z", "title": "Malicious activity reported by urlquery.net", "details_url": "http://urlquery.net/report/b1393866-9b1f-4a8e-b02b-9636989050f3", "tag": "malicious activity" } ] }, ... """ habucfg = loadcfg() if 'CYMON_APIKEY' not in habucfg: print('You must provide a cymon apikey. Use the ~/.habu.json file (variable CYMON_APIKEY), or export the variable HABU_CYMON_APIKEY') print('Get your API key from https://www.cymon.io/') sys.exit(1) if verbose: logging.basicConfig(level=logging.INFO, format='%(message)s') if not no_cache: homedir = pwd.getpwuid(os.getuid()).pw_dir requests_cache.install_cache(homedir + '/.habu_requests_cache') url = 'https://www.cymon.io:443/api/nexus/v1/ip/{}/timeline/'.format(ip) headers = { 'Authorization': 'Token {}'.format(habucfg['CYMON_APIKEY']) } r = requests.get(url, headers=headers) if r.status_code not in [200, 404]: print('ERROR', r) return False if r.status_code == 404: print("Not Found") return False data = r.json() if pretty: output.write(pretty_print(data)) else: output.write(json.dumps(data, indent=4)) output.write('\n')
def cmd_cymon_ip(ip, no_cache, verbose, output): """Simple cymon API client. Prints the JSON result of a cymon IP query. Example: \b $ habu.cymon.ip 8.8.8.8 { "addr": "8.8.8.8", "created": "2015-03-23T12:03:42Z", "updated": "2018-08-24T04:06:07Z", "sources": [ "safeweb.norton.com", "botscout.com", "virustotal.com", "phishtank" ], "events": "https://www.cymon.io/api/nexus/v1/ip/8.8.8.8/events", "domains": "https://www.cymon.io/api/nexus/v1/ip/8.8.8.8/domains", "urls": "https://www.cymon.io/api/nexus/v1/ip/8.8.8.8/urls" } """ habucfg = loadcfg() if 'CYMON_APIKEY' not in habucfg: print('You must provide a cymon apikey. Use the ~/.habu.json file (variable CYMON_APIKEY), or export the variable HABU_CYMON_APIKEY') print('Get your API key from https://www.cymon.io/') sys.exit(1) if verbose: logging.basicConfig(level=logging.INFO, format='%(message)s') if not no_cache: homedir = pwd.getpwuid(os.getuid()).pw_dir requests_cache.install_cache(homedir + '/.habu_requests_cache') url = 'https://www.cymon.io:443/api/nexus/v1/ip/{}'.format(ip) headers = { 'Authorization': 'Token {}'.format(habucfg['CYMON_APIKEY']) } r = requests.get(url, headers=headers) if r.status_code not in [200, 404]: print('ERROR', r) return False if r.status_code == 404: print("Not Found") return False data = r.json() output.write(json.dumps(data, indent=4)) output.write('\n')
def cmd_shodan(input, output, verbose): habucfg = loadcfg() if 'VIRUSTOTAL_APIKEY' not in habucfg: logging.error( 'You must provide a virustotal apikey. Use the ~/.habu.json file (variable VIRUSTOTAL_APIKEY), or export the variable HABU_VIRUSTOTAL_APIKEY' ) sys.exit(1) if verbose: logging.basicConfig(level=logging.INFO, format='%(message)s') filename = Path(input.name).name data = input.read() sha256 = hashlib.sha256(data).hexdigest() logging.info('Verifying if hash already submitted: {}'.format(sha256)) params = {'apikey': habucfg['VIRUSTOTAL_APIKEY'], 'resource': sha256} response = requests.post('https://www.virustotal.com/vtapi/v2/file/rescan', params=params) json_response = response.json() if json_response['response_code'] == 0: files = {'file': (filename, data)} params = {'apikey': habucfg['VIRUSTOTAL_APIKEY']} response = requests.post( 'https://www.virustotal.com/vtapi/v2/file/scan', files=files, params=params) json_response = response.json() resource = json_response['resource'] logging.info('Waiting/retrieving the report...') while True: params = {'apikey': habucfg['VIRUSTOTAL_APIKEY'], 'resource': sha256} response = requests.get( 'https://www.virustotal.com/vtapi/v2/file/report', params=params) json_response = response.json() if json_response['response_code'] == 1: break sleep(5) output.write(json.dumps(json_response, indent=4, sort_keys=True)) output.write('\n')
def cmd_fernet(key, decrypt, ttl, i, o): """Fernet cipher. Uses AES-128-CBC with HMAC Note: You must use a key to cipher with Fernet. Use the -k paramenter or set the FERNET_KEY configuration value. The keys can be generated with the command habu.fernet.genkey Reference: https://github.com/fernet/spec/blob/master/Spec.md Example: \b $ "I want to protect this string" | habu.fernet gAAAAABbXnCGoCULLuVNRElYTbEcwnek9iq5jBKq9JAN3wiiBUzPqpUgV5oWvnC6xfIA... \b $ echo gAAAAABbXnCGoCULLuVNRElYTbEcwnek9iq5jBKq9JAN3wiiBUzPqpUgV5oWvnC6xfIA... | habu.fernet -d I want to protect this string """ habucfg = loadcfg() if not key: if 'FERNET_KEY' in habucfg: key = habucfg['FERNET_KEY'] else: print(ERROR_NOKEY, file=sys.stderr) sys.exit(1) if not ttl: ttl=None cipher = Fernet(key) data = i.read() if decrypt: try: token = cipher.decrypt(data, ttl) except Exception as e: print("Error decrypting", file=sys.stderr) sys.exit(1) else: token = cipher.encrypt(data) print(token.decode(), end='')
def cmd_usercheck(username, no_cache, verbose, wopen): """Check if the given username exists on various social networks and other popular sites. \b $ habu.usercheck portantier { "aboutme": "https://about.me/portantier", "disqus": "https://disqus.com/by/portantier/", "github": "https://github.com/portantier/", "ifttt": "https://ifttt.com/p/portantier", "lastfm": "https://www.last.fm/user/portantier", "medium": "https://medium.com/@portantier", "pastebin": "https://pastebin.com/u/portantier", "pinterest": "https://in.pinterest.com/portantier/", "twitter": "https://twitter.com/portantier", "vimeo": "https://vimeo.com/portantier" } """ habucfg = loadcfg() if verbose: logging.basicConfig(level=logging.INFO, format='%(message)s') if not no_cache: homedir = pwd.getpwuid(os.getuid()).pw_dir requests_cache.install_cache(homedir + '/.habu_requests_cache') logging.info('using cache on ' + homedir + '/.habu_requests_cache') existent = {} for site, url in urls.items(): u = url.format(username) logging.info(u) try: r = requests.head(u, allow_redirects=False) except Exception: continue if r.status_code == 200: if requests.head(url.format('zei4fee3q9'), allow_redirects=False).status_code == 200: logging.error( 'Received status 200 for user zei4fee3q9, maybe, the check needs to be fixed' ) else: existent[site] = u if wopen: webbrowser.open_new_tab(u) print(json.dumps(existent, indent=4))
def cmd_crypto_fernet(key, decrypt, ttl, i, o): """Fernet cipher. Uses AES-128-CBC with HMAC Note: You must use a key to cipher with Fernet. Use the -k paramenter or set the FERNET_KEY configuration value. The keys can be generated with the command habu.crypto.fernet.genkey Reference: https://github.com/fernet/spec/blob/master/Spec.md Example: \b $ "I want to protect this string" | habu.crypto.fernet gAAAAABbXnCGoCULLuVNRElYTbEcwnek9iq5jBKq9JAN3wiiBUzPqpUgV5oWvnC6xfIA... \b $ echo gAAAAABbXnCGoCULLuVNRElYTbEcwnek9iq5jBKq9JAN3wiiBUzPqpUgV5oWvnC6xfIA... | habu.crypto.fernet -d I want to protect this string """ habucfg = loadcfg() if not key: if 'FERNET_KEY' in habucfg: key = habucfg['FERNET_KEY'] else: print(ERROR_NOKEY, file=sys.stderr) sys.exit(1) if not ttl: ttl = None cipher = Fernet(key) data = i.read() if decrypt: try: token = cipher.decrypt(data, ttl) except Exception as e: print("Error decrypting", file=sys.stderr) sys.exit(1) else: token = cipher.encrypt(data) print(token.decode(), end='')
def cmd_shodan(ip, no_cache, verbose, output): """Simple shodan API client. Prints the JSON result of a shodan query. Example: \b $ habu.shodan 8.8.8.8 { "hostnames": [ "google-public-dns-a.google.com" ], "country_code": "US", "org": "Google", "data": [ { "isp": "Google", "transport": "udp", "data": "Recursion: enabled", "asn": "AS15169", "port": 53, "hostnames": [ "google-public-dns-a.google.com" ] } ], "ports": [ 53 ] } """ habucfg = loadcfg() if 'SHODAN_APIKEY' not in habucfg: print( 'You must provide a shodan apikey. Use the ~/.habu.json file (variable SHODAN_APIKEY), or export the variable HABU_SHODAN_APIKEY' ) print('Get your API key from https://www.shodan.io/') sys.exit(1) if verbose: logging.basicConfig(level=logging.INFO, format='%(message)s') data = shodan_get_result(ip, habucfg['SHODAN_APIKEY'], no_cache, verbose) output.write(json.dumps(data, indent=4)) output.write('\n')
def cmd_shodan(input, output, verbose): habucfg = loadcfg() if verbose: logging.basicConfig(level=logging.INFO, format='%(message)s') filename = Path(input.name).name data = input.read() sha1 = hashlib.sha1(data).hexdigest() output.write(json.dumps(get_cymru(sha1), indent=4, sort_keys=True)) output.write('\n')
def cmd_config_del(key): """Delete a KEY from the configuration. Note: By default, KEY is converted to uppercase. Example: \b $ habu.config.del DNS_SERVER """ habucfg = loadcfg(environment=False) habucfg.pop(key.upper(), None) with Path('~/.habu.json').expanduser().open('w') as f: f.write(json.dumps(habucfg, indent=4, sort_keys=True))
def cmd_config_del(key): """Delete a KEY from the configuration. Note: By default, KEY is converted to uppercase. Example: \b $ habu.config.del DNS_SERVER """ habucfg = loadcfg(environment=False) habucfg.pop(key.upper(), None) with Path('~/.habu.json').expanduser().open('w') as f: f.write(json.dumps(habucfg, indent=4, sort_keys=True, default=str))
def cmd_config_set(key, value): """Set VALUE to the config KEY. Note: By default, KEY is converted to uppercase. Example: \b $ habu.config.set DNS_SERVER 8.8.8.8 """ habucfg = loadcfg(environment=False) habucfg[key.upper()] = value with Path('~/.habu.json').expanduser().open('w') as f: f.write(json.dumps(habucfg, indent=4, sort_keys=True))
def cmd_shodan(ip, no_cache, verbose, output): """Simple shodan API client. Prints the JSON result of a shodan query. Example: \b $ habu.shodan 8.8.8.8 { "hostnames": [ "google-public-dns-a.google.com" ], "country_code": "US", "org": "Google", "data": [ { "isp": "Google", "transport": "udp", "data": "Recursion: enabled", "asn": "AS15169", "port": 53, "hostnames": [ "google-public-dns-a.google.com" ] } ], "ports": [ 53 ] } """ habucfg = loadcfg() if 'SHODAN_APIKEY' not in habucfg: print('You must provide a shodan apikey. Use the ~/.habu.json file (variable SHODAN_APIKEY), or export the variable HABU_SHODAN_APIKEY') print('Get your API key from https://www.shodan.io/') sys.exit(1) if verbose: logging.basicConfig(level=logging.INFO, format='%(message)s') data = shodan_get_result(ip, habucfg['SHODAN_APIKEY'], no_cache, verbose) output.write(json.dumps(data, indent=4)) output.write('\n')
def cmd_usercheck(username, no_cache, verbose, wopen): """Check if the given username exists on various social networks and other popular sites. \b $ habu.usercheck portantier { "aboutme": "https://about.me/portantier", "disqus": "https://disqus.com/by/portantier/", "github": "https://github.com/portantier/", "ifttt": "https://ifttt.com/p/portantier", "lastfm": "https://www.last.fm/user/portantier", "medium": "https://medium.com/@portantier", "pastebin": "https://pastebin.com/u/portantier", "pinterest": "https://in.pinterest.com/portantier/", "twitter": "https://twitter.com/portantier", "vimeo": "https://vimeo.com/portantier" } """ habucfg = loadcfg() if verbose: logging.basicConfig(level=logging.INFO, format='%(message)s') if not no_cache: homedir = pwd.getpwuid(os.getuid()).pw_dir requests_cache.install_cache(homedir + '/.habu_requests_cache') logging.info('using cache on ' + homedir + '/.habu_requests_cache') existent = {} for site, url in urls.items(): u = url.format(username) logging.info(u) try: r = requests.head(u, allow_redirects=False) except Exception: continue if r.status_code == 200: if requests.head(url.format('zei4fee3q9'), allow_redirects=False).status_code == 200: logging.error('Received status 200 for user zei4fee3q9, maybe, the check needs to be fixed') else: existent[site] = u if wopen: webbrowser.open_new_tab(u) print(json.dumps(existent, indent=4))
def cmd_fernet_genkey(writecfg): """Generate a new Fernet Key, optionally write it to ~/.habu.json Example: \b $ habu.fernet.genkey xgvWCIvjwe9Uq7NBvwO796iI4dsGD623QOT9GWqnuhg= """ key = Fernet.generate_key() print(key.decode()) if writecfg: habucfg = loadcfg(environment=False) habucfg['FERNET_KEY'] = key.decode() with Path('~/.habu.json').expanduser().open('w') as f: f.write(json.dumps(habucfg, indent=4, sort_keys=True))
def cmd_fernet_genkey(writecfg): """Generate a new Fernet Key, optionally write it to ~/.habu.json Example: \b $ habu.fernet.genkey xgvWCIvjwe9Uq7NBvwO796iI4dsGD623QOT9GWqnuhg= """ key = Fernet.generate_key() print(key.decode()) if writecfg: habucfg = loadcfg(environment=False) habucfg['FERNET_KEY'] = key.decode() with Path('~/.habu.json').expanduser().open('w') as f: f.write(json.dumps(habucfg, indent=4, sort_keys=True))
def cmd_nmap_excluded(lowest, highest): """ Prints a random port that is not present on nmap-services file so is not scanned automatically by nmap. Useful for services like SSH or RDP, that are continuously scanned on their default ports. Example: \b # habu.nmap.excluded 58567 """ if lowest >= highest: logging.error('lowest can not be greater or equal than highest') cfg = loadcfg() with (cfg['DATADIR'] / 'nmap-services').open() as nsf: nmap_services = nsf.read() unwanted = set() for line in nmap_services.strip().split('\n'): if line.startswith('#'): continue service,port,_ = line.split('\t', maxsplit=2) unwanted.add(int(port.split('/')[0])) choices = list(range(lowest,highest)) random.shuffle(choices) found = False for choice in choices: if choice not in unwanted: print(choice) found = True break if not found: logging.error('Can\'t find a port number with the specified parameters')
def cmd_shodan_open(ip, no_cache, json_output, nmap_command, verbose, output): """Output the open ports for an IP against shodan (nmap format). Example: \b $ habu.shodan.open 8.8.8.8 T:53,U:53 """ habucfg = loadcfg() if 'SHODAN_APIKEY' not in habucfg: print( 'You must provide a shodan apikey. Use the ~/.habu.json file (variable SHODAN_APIKEY), or export the variable HABU_SHODAN_APIKEY' ) print('Get your API key from https://www.shodan.io/') sys.exit(1) if verbose: logging.basicConfig(level=logging.INFO, format='%(message)s') data = shodan_get_result(ip, habucfg['SHODAN_APIKEY'], no_cache, verbose) ports = [] if 'data' in data: for service in data['data']: ports.append('{}:{}'.format(service['transport'][0].upper(), service['port'])) if nmap_command: if ports: output.write('nmap -A -v -p {} {}'.format(','.join(ports), ip)) else: if json_output: output.write(json.dumps(ports, indent=4)) output.write('\n') else: output.write(','.join(ports))
def cmd_shodan_open(ip, no_cache, json_output, nmap_command, verbose, output): """Output the open ports for an IP against shodan (nmap format). Example: \b $ habu.shodan.open 8.8.8.8 T:53,U:53 """ habucfg = loadcfg() if 'SHODAN_APIKEY' not in habucfg: print('You must provide a shodan apikey. Use the ~/.habu.json file (variable SHODAN_APIKEY), or export the variable HABU_SHODAN_APIKEY') print('Get your API key from https://www.shodan.io/') sys.exit(1) if verbose: logging.basicConfig(level=logging.INFO, format='%(message)s') data = shodan_get_result(ip, habucfg['SHODAN_APIKEY'], no_cache, verbose) ports = [] if 'data' in data: for service in data['data']: ports.append('{}:{}'.format( service['transport'][0].upper(), service['port'] )) if nmap_command: if ports: output.write('nmap -A -v -p {} {}'.format(','.join(ports), ip)) else: if json_output: output.write(json.dumps(ports, indent=4)) output.write('\n') else: output.write(','.join(ports))
def cmd_config_show(option, show_keys): """Show the current config. Note: By default, the options with 'KEY' in their name are shadowed. Example: \b $ habu.config.show { "DNS_SERVER": "8.8.8.8", "FERNET_KEY": "*************" } """ habucfg = loadcfg() if not show_keys: for key in habucfg.keys(): if 'KEY' in key: habucfg[key] = '*************' print(json.dumps(habucfg, indent=4, sort_keys=True, default=str))
def cmd_config(option, show_keys): """Show the current config. Note: By default, the options with 'KEY' in their name are shadowed. Example: \b $ habu.config { "DNS_SERVER": "8.8.8.8", "FERNET_KEY": "*************" } """ habucfg = loadcfg() if not show_keys: for key in habucfg.keys(): if 'KEY' in key: habucfg[key] = '*************' print(json.dumps(habucfg, indent=4, sort_keys=True))
#!/usr/bin/env python3 import logging import os import os.path import requests import requests_cache from pathlib import Path from habu.lib.loadcfg import loadcfg config = loadcfg() def shodan_get_result(ip, api_key=None, cache=True, verbose=False): if verbose: logging.basicConfig(level=logging.INFO, format='%(message)s') if cache: homedir = Path(os.path.expanduser('~')) requests_cache.install_cache(str(homedir / '.habu_requests_cache'), expire_after=3600) if not api_key: api_key = config['SHODAN_APIKEY'] url = 'https://api.shodan.io/shodan/host/{}?key={}'.format(ip, api_key)
def cmd_virustotal(input, verbose): """Send a file to VirusTotal https://www.virustotal.com/ and print the report in JSON format. Note: Before send a file, will check if the file has been analyzed before (sending the sha256 of the file), if a report exists, no submission will be made, and you will see the last report. \b $ habu.virustotal meterpreter.exe Verifying if hash already submitted: f4826b219aed3ffdaa23db26cfae611979bf215984fc71a1c12f6397900cb70d Sending file for analysis Waiting/retrieving the report... { "md5": "0ddb015b5328eb4d0cc2b87c39c49686", "permalink": "https://www.virustotal.com/file/c9a2252b491641e15753a4d0c4bb30b1f9bd26ecff2c74f20a3c7890f3a1ea23/analysis/1526850717/", "positives": 49, "resource": "c9a2252b491641e15753a4d0c4bb30b1f9bd26ecff2c74f20a3c7890f3a1ea23", "response_code": 1, "scan_date": "2018-05-20 21:11:57", "scan_id": "c9a2252b491641e15753a4d0c4bb30b1f9bd26ecff2c74f20a3c7890f3a1ea23-1526850717", "scans": { "ALYac": { "detected": true, "result": "Trojan.CryptZ.Gen", "update": "20180520", "version": "1.1.1.5" }, ... The other scanners ... }, "sha1": "5fa33cab1729480dd023b08f7b91a945c16d0a9e", "sha256": "c9a2252b491641e15753a4d0c4bb30b1f9bd26ecff2c74f20a3c7890f3a1ea23", "total": 67, "verbose_msg": "Scan finished, information embedded" } """ habucfg = loadcfg() if 'VIRUSTOTAL_APIKEY' not in habucfg: logging.error('You must provide a virustotal apikey. Use the ~/.habu.json file (variable VIRUSTOTAL_APIKEY), or export the variable HABU_VIRUSTOTAL_APIKEY') sys.exit(1) if verbose: logging.basicConfig(level=logging.INFO, format='%(message)s') filename = Path(input.name).name data = input.read() sha256 = hashlib.sha256(data).hexdigest() logging.info('Verifying if hash already submitted: {}'.format(sha256)) params = {'apikey': habucfg['VIRUSTOTAL_APIKEY'], 'resource': sha256} response = requests.post('https://www.virustotal.com/vtapi/v2/file/rescan', params=params) if response.status_code != 200 or response.json()['response_code'] == 0: logging.info('Sending file for analysis') files = {'file': (filename, data)} params = {'apikey': habucfg['VIRUSTOTAL_APIKEY']} response = requests.post('https://www.virustotal.com/vtapi/v2/file/scan', files=files, params=params) json_response = response.json() resource = json_response['resource'] logging.info('Waiting/retrieving the report...') while True: params = {'apikey': habucfg['VIRUSTOTAL_APIKEY'], 'resource': sha256} response = requests.get('https://www.virustotal.com/vtapi/v2/file/report', params=params) if response.status_code == 200: json_response = response.json() if json_response['response_code'] == 1: break sleep(5) print(json.dumps(json_response, indent=4, sort_keys=True))
def cmd_cymon_ip_timeline(ip, no_cache, verbose, output, pretty): """Simple cymon API client. Prints the JSON result of a cymon IP timeline query. Example: \b $ habu.cymon.ip.timeline 8.8.8.8 { "timeline": [ { "time_label": "Aug. 18, 2018", "events": [ { "description": "Posted: 2018-08-18 23:37:39 CEST IDS Alerts: 0 URLQuery Alerts: 1 ...", "created": "2018-08-18T21:39:07Z", "title": "Malicious activity reported by urlquery.net", "details_url": "http://urlquery.net/report/b1393866-9b1f-4a8e-b02b-9636989050f3", "tag": "malicious activity" } ] }, ... """ habucfg = loadcfg() if 'CYMON_APIKEY' not in habucfg: print( 'You must provide a cymon apikey. Use the ~/.habu.json file (variable CYMON_APIKEY), or export the variable HABU_CYMON_APIKEY' ) print('Get your API key from https://www.cymon.io/') sys.exit(1) if verbose: logging.basicConfig(level=logging.INFO, format='%(message)s') if not no_cache: homedir = pwd.getpwuid(os.getuid()).pw_dir requests_cache.install_cache(homedir + '/.habu_requests_cache') url = 'https://www.cymon.io:443/api/nexus/v1/ip/{}/timeline/'.format(ip) headers = {'Authorization': 'Token {}'.format(habucfg['CYMON_APIKEY'])} r = requests.get(url, headers=headers) if r.status_code not in [200, 404]: print('ERROR', r) return False if r.status_code == 404: print("Not Found") return False data = r.json() if pretty: output.write(pretty_print(data)) else: output.write(json.dumps(data, indent=4)) output.write('\n')
def cmd_shodan(ip, cache, verbose, output_format): """Simple shodan API client. Prints the JSON result of a shodan query. Example: \b $ habu.shodan 216.58.222.36 asn AS15169 isp Google hostnames eze04s06-in-f4.1e100.net, gru09s17-in-f36.1e100.net country_code US region_code CA city Mountain View org Google open_ports tcp/443, tcp/80 """ habucfg = loadcfg() if 'SHODAN_APIKEY' not in habucfg: print( 'You must provide a shodan apikey. Use the ~/.habu.json file (variable SHODAN_APIKEY), or export the variable HABU_SHODAN_APIKEY' ) print('Get your API key from https://www.shodan.io/') sys.exit(1) if verbose: logging.basicConfig(level=logging.INFO, format='%(message)s') data = shodan_get_result(ip, habucfg['SHODAN_APIKEY'], cache=cache, verbose=verbose) if output_format == 'json': print(json.dumps(data, indent=4)) return True if output_format == 'nmap': ports_string = ','.join([ '{}:{}'.format(port['transport'][0].upper(), port['port']) for port in data['data'] ]) print(ports_string, end='') return True default_fields = [ 'asn', 'isp', 'hostnames', 'country_code', 'region_code', 'city', 'org', 'os', ] for field in default_fields: value = data.get(field, None) if not value: continue if output_format == 'csv': if not isinstance(value, list): value = [value] for v in sorted(value): print('"{}","shodan.{}","{}"'.format(ip, field, v)) else: if isinstance(value, list): value = ', '.join(sorted(value)) print('{:<25}{}'.format(field, value)) if output_format == 'txt': ports_string = ', '.join([ '{}/{}'.format(port['transport'], port['port']) for port in data['data'] ]) print('{:<25}{}'.format('open_ports', ports_string)) else: for port in data['data']: print('"{}","shodan.open_port","{}/{}"'.format( ip, port['transport'], port['port']))
def cmd_virustotal(input, verbose): """Send a file to VirusTotal https://www.virustotal.com/ and print the report in JSON format. Note: Before send a file, will check if the file has been analyzed before (sending the sha256 of the file), if a report exists, no submission will be made, and you will see the last report. \b $ habu.virustotal meterpreter.exe Verifying if hash already submitted: f4826b219aed3ffdaa23db26cfae611979bf215984fc71a1c12f6397900cb70d Sending file for analysis Waiting/retrieving the report... { "md5": "0ddb015b5328eb4d0cc2b87c39c49686", "permalink": "https://www.virustotal.com/file/c9a2252b491641e15753a4d0c4bb30b1f9bd26ecff2c74f20a3c7890f3a1ea23/analysis/1526850717/", "positives": 49, "resource": "c9a2252b491641e15753a4d0c4bb30b1f9bd26ecff2c74f20a3c7890f3a1ea23", "response_code": 1, "scan_date": "2018-05-20 21:11:57", "scan_id": "c9a2252b491641e15753a4d0c4bb30b1f9bd26ecff2c74f20a3c7890f3a1ea23-1526850717", "scans": { "ALYac": { "detected": true, "result": "Trojan.CryptZ.Gen", "update": "20180520", "version": "1.1.1.5" }, ... The other scanners ... }, "sha1": "5fa33cab1729480dd023b08f7b91a945c16d0a9e", "sha256": "c9a2252b491641e15753a4d0c4bb30b1f9bd26ecff2c74f20a3c7890f3a1ea23", "total": 67, "verbose_msg": "Scan finished, information embedded" } """ habucfg = loadcfg() if 'VIRUSTOTAL_APIKEY' not in habucfg: logging.error( 'You must provide a virustotal apikey. Use the ~/.habu.json file (variable VIRUSTOTAL_APIKEY), or export the variable HABU_VIRUSTOTAL_APIKEY' ) sys.exit(1) if verbose: logging.basicConfig(level=logging.INFO, format='%(message)s') filename = Path(input.name).name data = input.read() sha256 = hashlib.sha256(data).hexdigest() logging.info('Verifying if hash already submitted: {}'.format(sha256)) params = {'apikey': habucfg['VIRUSTOTAL_APIKEY'], 'resource': sha256} response = requests.post('https://www.virustotal.com/vtapi/v2/file/rescan', params=params) if response.status_code != 200 or response.json()['response_code'] == 0: logging.info('Sending file for analysis') files = {'file': (filename, data)} params = {'apikey': habucfg['VIRUSTOTAL_APIKEY']} response = requests.post( 'https://www.virustotal.com/vtapi/v2/file/scan', files=files, params=params) json_response = response.json() logging.info('Waiting/retrieving the report...') while True: params = {'apikey': habucfg['VIRUSTOTAL_APIKEY'], 'resource': sha256} response = requests.get( 'https://www.virustotal.com/vtapi/v2/file/report', params=params) if response.status_code == 200: json_response = response.json() if json_response['response_code'] == 1: break sleep(5) print(json.dumps(json_response, indent=4, sort_keys=True))
def cmd_shodan(ip, no_cache, verbose, output): """Simple shodan API client. Prints the JSON result of a shodan query. Example: \b $ habu.shodan 8.8.8.8 { "hostnames": [ "google-public-dns-a.google.com" ], "country_code": "US", "org": "Google", "data": [ { "isp": "Google", "transport": "udp", "data": "Recursion: enabled", "asn": "AS15169", "port": 53, "hostnames": [ "google-public-dns-a.google.com" ] } ], "ports": [ 53 ] } """ habucfg = loadcfg() if 'SHODAN_APIKEY' not in habucfg: print( 'You must provide a shodan apikey. Use the ~/.habu.json file (variable SHODAN_APIKEY), or export the variable HABU_SHODAN_APIKEY' ) sys.exit(1) if verbose: logging.basicConfig(level=logging.INFO, format='%(message)s') if not no_cache: homedir = pwd.getpwuid(os.getuid()).pw_dir requests_cache.install_cache(homedir + '/.habu_requests_cache') url = 'https://api.shodan.io/shodan/host/{}?key={}'.format( ip, habucfg['SHODAN_APIKEY']) r = requests.get(url) if r.status_code not in [200, 404]: print('ERROR', r) return False if r.status_code == 404: print("Not Found") return False data = r.json() output.write(json.dumps(data, indent=4)) output.write('\n')