def add_client(self, event): edata = event.data ip = edata.get('ip') client = self.data.clients.get(ip) if not client: client = utils.Data() client.ip = ip client.ip_country = self.geoip_country(ip) client.agents = {} client.session_count = 0 client.environment = {} self.data.clients[ip] = client client.email = edata.get('email') env = edata.get('environment') if env: client.environment.update(env) user_agent = self.get_user_agent(edata) if not user_agent: return os, browser = parse_agent(user_agent) agent = client.agents.get(user_agent) if not agent: agent = utils.Data() agent.name = user_agent agent._browser = browser agent.browser = ' '.join(browser) agent._os = os agent.os = ' '.join(os) agent.plugins = {} client.agents[user_agent] = agent recon = edata.get('recon') if not recon: return plugins = recon.get('plugins') if plugins: plugins.pop('AGENT', None) agent.language = plugins.pop('language', None) agent.cpu = plugins.pop('CPU', None) agent.platform = plugins.pop('platform', None) plugins = utils.dict_fix_unicode(plugins) agent.plugins.update(plugins)
def process_event(self, event): if event.module != 'canvas': return ename = event.name if ename == 'new host': ip = event.data['ip'] self.add_host(ip, event) elif ename == 'new node': node = utils.Data(event.data) node.exploit = utils.Data(node.exploit) if node.exploit else None node.time = event.time node.session_id = event.session_id self.data._nodes.append(node) elif ename.startswith('exploit'): self.add_exploit_event(event)
def add_session(self, event): edata = event.data sid = edata.get('sid') if not sid: return session = self.data.sessions.get(sid) if session: return session = utils.Data() session.sid = sid self.data.sessions[sid] = session session.email = edata.get('email') session.ip = edata.get('ip') session.time = utils.format_datetime(event.time) session.agent = edata.get('user agent') ip = edata.get('ip') client = self.data.clients.get(ip) client.session_count += 1 stats = self.data.stats stats.session_count += 1
def collect(self, data_file): # set up the data structure data = self.data data.hosts = {} data._nodes = [] data._exploits = {} data.attacks = [] data.exploits = {} stats = data.stats = utils.Data() stats.hosts_discovered = 0 stats.hosts_attacked = set() stats.exploits_attempted = collections.defaultdict(int) stats.hosts_compromised = set() stats.successful_exploits = collections.defaultdict(int) stats.timeline = collections.defaultdict(lambda: [0, 0]) # process the pickle file self.process_report_pickle(data_file) # add attacks from collected data self.add_attacks() # calc some stats stats.hosts_attacked = len(stats.hosts_attacked) stats.hosts_compromised = len(stats.hosts_compromised) stats.total_exploits_attempted = sum(stats.exploits_attempted.values()) stats.total_exploits_successful = sum(stats.successful_exploits.values()) stats.exploits_attempted = len(stats.exploits_attempted) stats.exploits_successful = len(stats.successful_exploits) return self.data
def __init__(self): self.data = utils.Data() self._geoip = None geoip_path = utils.get_canvas_path('gui', 'WorldMap', 'GeoLiteCity.dat') if os.path.exists(geoip_path): self._geoip = pygeoip.GeoIP(geoip_path, pygeoip.MMAP_CACHE)
def add_exploit_to_data(self, name): """Add exploit details to a *Data* object. Returns a new or existing *Data* object for the exploit. """ import canvasengine # see if it has already been added exploit = self.data.exploits.get(name) if exploit: return exploit # helper func def attach_docs(exploit, module): def process_value(value): if isinstance(value, list): return '\n'.join([process_value(v) for v in value]) elif isinstance(value, bool): return 'Yes' if value else 'No' else: return value exploit.title = module.NAME exploit.version = getattr(module, 'VERSION', '') exploit.description = getattr(module, 'DESCRIPTION', 'No description available.') exploit.cve = self.get_exploit_cve(module) p = getattr(module, 'PROPERTY', {}) p.update(getattr(module, 'DOCUMENTATION', {})) props = exploit.properties = {} for k, v in p.iteritems(): lk = k.lower() v = str(process_value(v)).strip() if not v: continue elif lk == 'notes': continue elif lk in ['cve', 'cve name']: k = 'CVE' v = exploit.cve elif re.search('cve|cvss|mfsa|msadv|osvdb', lk): k = k.upper() else: k = k.title() props[k] = v # collect the exploit details exploit = utils.Data() self.data.exploits[name] = exploit # get exploit description from canvas mod = canvasengine.getModule(name) exploit.name = name attach_docs(exploit, mod) return exploit
def add_host(self, ip, event=None): data = self.data host = data.hosts.get(ip) if not host: host = utils.Data(event.data if event else {}) host.ip = ip host.attacks = [] host.commands = [] data.hosts[ip] = host data.stats.hosts_discovered += 1 return host
def add_exploit_event(self, event): edata = event.data key = (event.session_id, edata['id'], edata['name']) exploit = self.data._exploits.get(key) if not exploit: exploit = utils.Data(edata) self.data._exploits[key] = exploit else: exploit.update(edata) start_time = event.time if event.name == 'exploit started' else None exploit.started = start_time # prefer finished, but take whichever is available if event.name == 'exploit finished': exploit.ended = event.time elif event.name == 'exploit returned': exploit.ended = event.time
def add_attacks(self, event, successful=False): edata = event.data names = edata.get('attacks') if not names: name = edata.get('attack') if name: names = [name] sid = edata.get('sid') if not (names and sid): return data = self.data session = data.sessions[sid] for name in names: attack = data.attacks.get((name, sid)) if not attack: attack = utils.Data() data.attacks[(name, sid)] = attack attack.name = name attack.sid = sid attack.successful = successful exploit = self.add_exploit_to_data(name) attack.exploit = exploit attack.agent = session.agent attack.time = utils.format_datetime(event.time) # raw time for sorting attack._time = event.time attack.ip = edata.get('ip') attack.email = edata.get('email') stats = data.stats stats.attacks[name] += 1 if successful: stats.exploited_clients[(attack.ip, attack.agent)] += 1 stats.successful_attacks[name] += 1
def collect(self, data_file): data = self.data # set up the data structure data.sessions = {} data.clients = {} data.attacks = {} data.exploits = {} data.stats = stats = utils.Data() stats.session_count = 0 stats.recon_sessions = collections.defaultdict(int) stats.attack_sessions = collections.defaultdict(int) stats.exploited_clients = collections.defaultdict(int) stats.attacks = collections.defaultdict(int) stats.successful_attacks = collections.defaultdict(int) # process the pickle file self.process_report_pickle(data_file) # calc some stats stats.client_count = len(data.clients) stats.recon_session_count = len(stats.recon_sessions) stats.attack_session_count = len(stats.attack_sessions) stats.exploited_client_count = len(stats.exploited_clients) # plugins plugins = stats.plugins = collections.defaultdict(int) for client in data.clients.itervalues(): for agent in client.agents.itervalues(): for name, version in agent.plugins.iteritems(): plugins[(name, version)] += 1 return self.data
def add_attacks(self): data = self.data seen = set() # use nodes as a more reliable way to find successful attacks for node in data._nodes: attack = utils.Data() attack.target = node.ip attack.successful = True attack.node_type = node.type attack.node_time = utils.format_datetime(node.time) # raw time for sorting attack.raw_node_time = node.time key = None if node.exploit: attack.name = node.exploit['name'] key = (node.session_id, node.exploit['id'], attack.name) exploit = self.add_exploit_to_data(attack.name) if exploit: attack.title = exploit.title attack.cve = exploit.cve else: attack.name = '<unknown>' attack.title = 'Unknown Exploit' event_data = data._exploits.get(key) if event_data: seen.add(key) attack.logdata = event_data.get('logdata', []) else: attack.logdata = [] self._set_times(attack, event_data) self.add_attack(attack) # now check any left over exploit events for key, event_data in data._exploits.iteritems(): if key in seen: continue name = key[2] exploit = self.add_exploit_to_data(name) exploit_type = exploit.properties['Type'].lower() if exploit_type == 'commands': continue elif exploit_type != 'exploit': continue attack = utils.Data() attack.name = name attack.target = event_data.get('target') attack.successful = event_data.get('success') attack.title = exploit.title attack.cve = exploit.cve attack.logdata = event_data.get('logdata', []) self._set_times(attack, event_data) self.add_attack(attack)