def create(self, request): """ Test password in request: { "password":"******" } Test password and use additional words to be blacklisted (e.g. username, first or family name, ...): { "password":"******", "blacklist": [ "john", "doe", "j.doe" ] } """ raw = request.data.get("password", None) if not raw: return Response() hashed = sha1(raw.encode("utf-8")).hexdigest().upper().encode("ascii") key = f"base-password-strength-{hashed}" cached = cache.get(key, None) if cached: time.sleep(settings.BASE_PASSWORD_STRENGTH_CACHE_SLEEP) return Response(cached) bf = BloomFilter() with open(settings.BASE_PASSWORD_STRENGTH_BLOOM_FILE, "rb") as inp: bf.read(inp) checked = zxcvbn(raw) suggestions = [_(msg) for msg in checked["feedback"]["suggestions"]] result = { "leaked": hashed in bf, "score": checked["score"], "guesses": checked["guesses"], "crack_time": checked["crack_times_display"] ["offline_slow_hashing_1e4_per_second"], "feedback": { "warning": _(checked["feedback"]["warning"]), "suggestions": suggestions, }, } cache.set(key, result, timeout=settings.BASE_PASSWORD_STRENGTH_CACHE_TIMEOUT) return Response(result)
def main(): logger = setup_logging() if len(sys.argv) != 14: print( "Usage: python splunk2tie.py [value] [id] [data_type] [categories] [min_severity] [max_severity] [min_confidence] [max_confidence] [updated_at] [last_seen] [families] [actors] [hotness]") sys.exit(1) value = sys.argv[1] id = sys.argv[2] data_type = sys.argv[3] categories = sys.argv[4] min_severity = sys.argv[5] max_severity = sys.argv[6] min_confidence = sys.argv[7] max_confidence = sys.argv[8] updated_at = sys.argv[9] last_seen = sys.argv[10] families = sys.argv[11] actors = sys.argv[12] hotness = sys.argv[13] infile = sys.stdin outfile = sys.stdout inputs = csv.DictReader(infile) header = inputs.fieldnames output = csv.DictWriter(outfile, fieldnames=inputs.fieldnames, extrasaction='ignore') output.writeheader() bf = BloomFilter() with gzip.open(os.path.join(os.path.dirname(__file__), 'splunk.bloom'), 'rb') as f: bf.read(f) for row in inputs: try: socket.inet_aton(row['value']) value = row['value'] + "/32" except: value = row['value'] if bf.check(value): content = query_tie(value) for ioc in content['iocs']: # print ioc for field_name in ('categories', 'families', 'actors'): ioc[field_name] = '|'.join(ioc[field_name]) if ioc['data_type'] == "IPv4": ioc['value'] = ioc['value'][:-3] output.writerow(ioc) else: output.writerow(row)
def __init__(self, *args, **kwargs): Signature.__init__(self, *args, **kwargs) self.bloom_location = os.path.join(CUCKOO_ROOT, "data", "dga.bloom") # the dga families have produced FPs and will not be able to change weight or malfamily # we could consider to already ignore them in create_bloom.py self.allowed_families = [ "qsnatch", "suppobox", "virut", ] try: # init bloomfilter to be able to do a really quick lookup if a domain is in the bloomfilter self.bloom = BloomFilter() with open(self.bloom_location, "rb") as f: self.bloom.read(f) # init dga lookup dict to be able to match dga domain to malware family self.dga_lookup_dict = get_dga_lookup_dict() except: self.bloom = None self.dga_lookup_dict = {}
def handle(self, *args, **options): bf = BloomFilter(n=options.get("n") * 2, p=options.get("p")) with open(options.get("input"), "r") as inp: for i in trange(options.get("n")): line = inp.readline() if not line: break bf.add(line.strip().upper().encode("ascii")) filename = settings.BASE_PASSWORD_STRENGTH_BLOOM_FILE tmpfile = f"{filename}.tmp" logger.info(f"Writing new password bloom filter: {tmpfile}") with open(tmpfile, "wb") as outp: bf.write(outp) logger.info(f"Replacing old password bloom filter: {filename}") os.rename(tmpfile, filename)
"Fraunhofer DGA API call malformed or credentials invalid") sys.exit(-1) if response.status_code != 200: logging.error("Error while querying Fraunhofer DGA API: %s", response.status_code) sys.exit(-1) dga_json = response.json() if not dga_json: logging.error("API response could not be transformed into json dict") sys.exit(-1) # 2. create empty bloomfilter logging.info("Creating bloomfilter and DGA dict") bloom = BloomFilter(n=1000000, p=0.0001) # 3. insert DGA domains from json dict into bloomfilter and create dict for family lookup dga_lookup_dict = {} first_entry = False test_domain = None test_family = None for family, domain_list in dga_json.items(): if not first_entry: test_domain = domain_list[0] test_family = family first_entry = True for domain in domain_list: # insert domain into bloomfilter if not domain.lower().encode("utf8") in bloom: bloom.add(domain.lower().encode("utf8"))
class NetworkDGAFraunhofer(Signature): name = "network_dga_fraunhofer" description = "Likely use of Domain Generation Algorithm (DGA) - Fraunhofer" weight = 1 severity = 3 categories = ["network"] authors = ["kklinger"] families = [] references = [ "https://dgarchive.caad.fkie.fraunhofer.de", "https://github.com/DCSO/flor", ] minimum = "1.3" def __init__(self, *args, **kwargs): Signature.__init__(self, *args, **kwargs) self.bloom_location = os.path.join(CUCKOO_ROOT, "data", "dga.bloom") # the dga families have produced FPs and will not be able to change weight or malfamily # we could consider to already ignore them in create_bloom.py self.allowed_families = [ "qsnatch", "suppobox", "virut", ] try: # init bloomfilter to be able to do a really quick lookup if a domain is in the bloomfilter self.bloom = BloomFilter() with open(self.bloom_location, "rb") as f: self.bloom.read(f) # init dga lookup dict to be able to match dga domain to malware family self.dga_lookup_dict = get_dga_lookup_dict() except: self.bloom = None self.dga_lookup_dict = {} def run(self): if not HAS_FLOR: return False if not os.path.exists(self.bloom_location): return False if not (self.bloom and self.dga_lookup_dict): return False # 1. check if one of the resolved DNS requests is inside our bloomfilter hitlist = [] dnslist = self.results.get("network", {}).get("dns", []) if not dnslist: return False for dns in dnslist: request = dns.get("request", "") # try to extract domain from full hostname (e.g. foobarbaz.domain.com -> domain.com) _domain = "" try: _domain = request.split(".")[-2:-1][0] + "." + request.split( ".")[-1:][0] except: pass # check length of domain to not fire on most likely false positive domains, e.g. "sds.com" if _domain and len( _domain) > 7 and _domain != request and _domain.lower( ).encode("UTF-8") in self.bloom: hitlist.append(_domain.lower()) # fallback to full hostname/request as sometimes we get hostnames as dga domain from the Fraunhofer api elif request and request.lower().encode("UTF-8") in self.bloom: hitlist.append(request.lower()) if not hitlist: return False # 2. if we have hits get malware family has_match = False for hit in hitlist: fam_check = self.dga_lookup_dict.get(hit, "") if fam_check: tmp_fam = fam_check.split("_")[0] if tmp_fam and tmp_fam not in self.families and tmp_fam not in self.allowed_families: self.families.append(tmp_fam) has_match = True return has_match