def query_path_da(graphid, exclude=None, format='vis'): if graphid not in current_app.config['JACKDAW_GRAPH_DICT']: load(graphid) pathonly = False if format.lower() == 'path': pathonly = True exclude_edgetypes = __exclude_parse(exclude) da_sids = {} for domain_id in current_app.config['JACKDAW_GRAPH_DICT'][graphid].adids: for res in current_app.db.session.query(Group).filter_by( ad_id=domain_id).filter(Group.objectSid.like('%-512')).all(): da_sids[res.objectSid] = 0 if len(da_sids) == 0: return 'No domain administrator group found', 404 res = GraphData() if pathonly is True: res = [] for sid in da_sids: res += current_app.config['JACKDAW_GRAPH_DICT'][ graphid].shortest_paths(None, sid, exclude=exclude_edgetypes, pathonly=pathonly) #print(res) return res.to_dict(format=format)
def query_path_asreproast(graphid, exclude=None, format='vis'): exclude_edgetypes = __exclude_parse(exclude) if graphid not in current_app.config['JACKDAW_GRAPH_DICT']: load(graphid) target_sids = {} da_sids = {} for domain_id in current_app.config['JACKDAW_GRAPH_DICT'][graphid].adids: for res in current_app.db.session.query(Group).filter_by( ad_id=domain_id).filter(Group.objectSid.like('%-512')).all(): da_sids[res.objectSid] = 0 for res in current_app.db.session.query(ADUser.objectSid)\ .filter_by(ad_id = domain_id)\ .filter(ADUser.UAC_DONT_REQUIRE_PREAUTH == True).all(): target_sids[res[0]] = 0 res = GraphData() for dst_sid in da_sids: for src_sid in target_sids: res += current_app.config['JACKDAW_GRAPH_DICT'][ graphid].shortest_paths(src_sid, dst_sid, exclude=exclude_edgetypes) return res.to_dict(format=format)
def query_path_kerberoastany(graphid, exclude=None, format='vis'): exclude_edgetypes = __exclude_parse(exclude) if graphid not in current_app.config['JACKDAW_GRAPH_DICT']: load(graphid) target_sids = {} domain_sids = {} path_to_da = [] for domain_id in current_app.config['JACKDAW_GRAPH_DICT'][graphid].adids: res = current_app.db.session.query(ADInfo).get(domain_id) domain_sids[res.objectSid] = 1 for res in current_app.db.session.query(ADUser.objectSid)\ .filter_by(ad_id = domain_id)\ .filter(ADUser.servicePrincipalName != None).all(): target_sids[res[0]] = 0 res = GraphData() for src_sid in target_sids: for domain_sid in domain_sids: if current_app.config['JACKDAW_GRAPH_DICT'][graphid].has_path( src_sid, domain_sid) is False: res += current_app.config['JACKDAW_GRAPH_DICT'][ graphid].shortest_paths(src_sid=src_sid, dst_sid=None, exclude=exclude_edgetypes) else: path_to_da.append(src_sid) #TODO: send the path_to_da as well! return res.to_dict(format=format)
def query_path_tohighvalue(graphid, exclude=None, format='vis'): exclude_edgetypes = __exclude_parse(exclude) if graphid not in current_app.config['JACKDAW_GRAPH_DICT']: load(graphid) target_sids = {} for domain_id in current_app.config['JACKDAW_GRAPH_DICT'][graphid].adids: for res in current_app.db.session.query(EdgeLookup.oid)\ .filter_by(ad_id = domain_id)\ .filter(EdgeLookup.oid == ADObjProps.oid)\ .filter(ADObjProps.graph_id == graphid)\ .filter(ADObjProps.prop == 'HVT')\ .all(): target_sids[res[0]] = 0 res = GraphData() for dst_sid in target_sids: res += current_app.config['JACKDAW_GRAPH_DICT'][ graphid].shortest_paths(dst_sid=dst_sid, ignore_notfound=True, exclude=exclude_edgetypes) return res.to_dict(format=format)
def query_path_kerberoastda(graphid, format='vis'): if graphid not in current_app.config['JACKDAW_GRAPH_DICT']: load(graphid) target_sids = {} da_sids = {} for res in current_app.db.session.query(Group).filter_by( ad_id=current_app.config['JACKDAW_GRAPH_DICT'] [graphid].domain_id).filter(Group.objectSid.like('%-512')).all(): da_sids[res.objectSid] = 0 for res in current_app.db.session.query(ADUser.objectSid)\ .filter_by(ad_id = current_app.config['JACKDAW_GRAPH_DICT'][graphid].domain_id)\ .filter(ADUser.servicePrincipalName != None).all(): target_sids[res[0]] = 0 res = GraphData() for dst_sid in da_sids: for src_sid in target_sids: res += current_app.config['JACKDAW_GRAPH_DICT'][ graphid].shortest_paths(src_sid, dst_sid) return res.to_dict(format=format)
def query_path_da(graphid, format='vis'): if graphid not in current_app.config['JACKDAW_GRAPH_DICT']: load(graphid) da_sids = {} #searching for domain admin SID #for node in current_app.config['JACKDAW_GRAPH_DICT'][graphid].get_node(): # print(node) # if node.id == current_app.config['JACKDAW_GRAPH_DICT'][graphid].domain_sid + '-512': # da_sids[node.id] = 1 print(current_app.config['JACKDAW_GRAPH_DICT'][graphid].domain_id) for res in current_app.db.session.query(Group).filter_by( ad_id=current_app.config['JACKDAW_GRAPH_DICT'] [graphid].domain_id).filter(Group.objectSid.like('%-512')).all(): da_sids[res.objectSid] = 0 if len(da_sids) == 0: return 'No domain administrator group found', 404 res = GraphData() for sid in da_sids: res += current_app.config['JACKDAW_GRAPH_DICT'][ graphid].shortest_paths(None, sid) #print(res) return res.to_dict(format=format)
def query_path_ownedda(graphid, exclude=None, format='vis'): exclude_edgetypes = __exclude_parse(exclude) if graphid not in current_app.config['JACKDAW_GRAPH_DICT']: load(graphid) target_sids = {} da_sids = {} for domain_id in current_app.config['JACKDAW_GRAPH_DICT'][graphid].adids: for res in current_app.db.session.query(Group).filter_by( ad_id=domain_id).filter(Group.objectSid.like('%-512')).all(): da_sids[res.objectSid] = 0 for res in current_app.db.session.query(EdgeLookup.oid)\ .filter_by(ad_id = domain_id)\ .filter(EdgeLookup.oid == ADObjProps.oid)\ .filter(ADObjProps.graph_id == graphid)\ .filter(ADObjProps.prop == 'OWNED')\ .all(): target_sids[res[0]] = 0 res = GraphData() for dst_sid in da_sids: for src_sid in target_sids: res += current_app.config['JACKDAW_GRAPH_DICT'][ graphid].shortest_paths(src_sid, dst_sid, exclude=exclude_edgetypes) return res.to_dict(format=format)
def query_path_dcsync(graphid, exclude=None, format='vis'): exclude_edgetypes = __exclude_parse(exclude) if graphid not in current_app.config['JACKDAW_GRAPH_DICT']: load(graphid) target_sids = {} da_sids = { } #{current_app.config['JACKDAW_GRAPH_DICT'][graphid].domain_sid : 0} for domain_id in current_app.config['JACKDAW_GRAPH_DICT'][graphid].adids: for res in current_app.db.session.query(Group).filter_by( ad_id=domain_id).filter(Group.objectSid.like('%-512')).all(): da_sids[res.objectSid] = 0 for res in current_app.db.session.query(EdgeLookup.oid)\ .filter_by(ad_id = domain_id)\ .filter(EdgeLookup.id == Edge.src)\ .filter(EdgeLookup.oid != None)\ .filter(or_(Edge.label == 'GetChanges', Edge.label == 'GetChangesAll'))\ .all(): target_sids[res[0]] = 0 res = GraphData() for dst_sid in da_sids: for src_sid in target_sids: res += current_app.config['JACKDAW_GRAPH_DICT'][ graphid].shortest_paths(src_sid, dst_sid, exclude=exclude_edgetypes) #for src_sid in target_sids: # res += current_app.config['JACKDAW_GRAPH_DICT'][graphid].shortest_paths(None, src_sid, exclude = exclude_edgetypes) return res.to_dict(format=format)
def get_members(self, group_sid, maxhops=1): try: network = GraphData() group_id = self.resolve_sid_to_id(group_sid) self.add_node(network, group_id) prev_groups = [group_sid] for distance in range(maxhops): next_groups = [] for group_sid in prev_groups: for sid, otype in self.get_edges_onelevel( group_sid, 'member', 'in'): if otype == 'group': next_groups.append(sid) if network.node_present(sid) is False: rid = self.resolve_sid_to_id(sid) self.add_node(network, rid) network.nodes[sid].set_distance(distance) network.add_edge(group_sid, sid, label='member') prev_groups = next_groups return network except Exception as e: import traceback traceback.print_exc() print(e) raise e
def get_members(graphid, sid, maxhops=1, format='vis'): if graphid not in current_app.config['JACKDAW_GRAPH_DICT']: load(graphid) res = GraphData() res += current_app.config['JACKDAW_GRAPH_DICT'][graphid].get_members( sid, maxhops) return res.to_dict(format='vis')
def query_path_dcsync(graphid, exclude=None, format='vis'): exclude_edgetypes = __exclude_parse(exclude) if graphid not in current_app.config['JACKDAW_GRAPH_DICT']: load(graphid) res = GraphData() res += current_app.config['JACKDAW_GRAPH_DICT'][graphid].get_dcsync() return res.to_dict(format=format)
async def do_pathasreproast(self, cmd): try: if cmd.graphid not in self.graphs: _, err = await self.loadgraph(cmd.graphid) if err is not None: await self.send_error(cmd, 'Failed to load graph cache!') return kerbsrc = {} for domainid in self.graphs[cmd.graphid].adids: for res in self.db_session.query(ADUser.objectSid)\ .filter_by(ad_id = domainid)\ .filter(ADUser.UAC_DONT_REQUIRE_PREAUTH == True).all(): kerbsrc[res[0]] = 0 if cmd.dst.upper() == 'DA': da_sids = {} for domainid in self.graphs[cmd.graphid].adids: for qres in self.db_session.query(Group).filter_by( ad_id=domainid).filter( Group.objectSid.like('%-512')).all(): da_sids[qres.objectSid] = 0 if len(da_sids) == 0: continue res = GraphData() for dst_sid in da_sids: for src_sid in kerbsrc: res += self.graphs[cmd.graphid].shortest_paths( src_sid, dst_sid) elif cmd.dst.upper() == 'ANY': res = GraphData() for sid in kerbsrc: res += self.graphs[cmd.graphid].shortest_paths(sid, None) edgeres = NestOpEdgeBuffRes() edgeres.token = cmd.token for edgeidx in res.edges: edgeres.edges.append( NestOpEdgeRes.from_graphedge(cmd, domainid, cmd.graphid, res.edges[edgeidx])) await self.websocket.send(edgeres.to_json()) await self.send_ok(cmd) except Exception as e: traceback.print_exc() await self.send_error(cmd, 'Error happened!') return False, e
def all_shortest_paths(self, src_sid = None, dst_sid = None): nv = GraphData() if src_sid is None and dst_sid is None: raise Exception('src_sid or dst_sid must be set') elif src_sid is None and dst_sid is not None: dst = self.__resolve_sid_to_id(dst_sid) if dst is None: raise Exception('SID not found!') # IN will give reverse order!!!! for path in self.graph.get_shortest_paths(str(dst), mode= igraph._igraph.IN): self.__result_path_add(nv, path) elif src_sid is not None and dst_sid is None: src = self.__resolve_sid_to_id(dst_sid) if src is None: raise Exception('SID not found!') for path in self.graph.get_all_shortest_paths(str(src), mode= self.graph.OUT): self.__result_path_add(nv, path) elif src_sid is not None and dst_sid is not None: src = self.__resolve_sid_to_id(dst_sid) if src is None: raise Exception('SID not found!') dst = self.__resolve_sid_to_id(dst_sid) if dst is None: raise Exception('SID not found!') for path in self.graph.get_all_shortest_paths(str(src), to = str(dst), mode= self.graph.OUT): self.__result_path_add(nv, path) return nv
async def do_pathshortest(self, cmd): try: if cmd.graphid not in self.graphs: _, err = await self.loadgraph(cmd.graphid) if err is not None: await self.send_error(cmd, 'Failed to load graph cache!') return res = GraphData() res += self.graphs[cmd.graphid].shortest_paths(cmd.src, cmd.dst) edgeres = NestOpEdgeBuffRes() edgeres.token = cmd.token for edgeidx in res.edges: edgeres.edges.append( NestOpEdgeRes.from_graphedge(cmd, None, cmd.graphid, res.edges[edgeidx])) await self.websocket.send(edgeres.to_json()) await self.send_ok(cmd) except Exception as e: traceback.print_exc() await self.send_error(cmd, 'Error happened!') return False, e
def __graph_asreproast_to_da(self, domainid, graphid): target_sids = {} da_sids = {} for res in self.current_app.db.session.query(Group).filter_by( ad_id=self.current_app.config['JACKDAW_GRAPH_DICT'] [graphid].domain_id).filter(Group.objectSid.like('%-512')).all(): da_sids[res.objectSid] = 0 for res in self.current_app.db.session.query(ADUser.objectSid)\ .filter_by(ad_id = self.current_app.config['JACKDAW_GRAPH_DICT'][graphid].domain_id)\ .filter(ADUser.UAC_DONT_REQUIRE_PREAUTH == True).all(): target_sids[res[0]] = 0 res = GraphData() for dst_sid in da_sids: for src_sid in target_sids: res += self.current_app.config['JACKDAW_GRAPH_DICT'][ graphid].shortest_paths(src_sid, dst_sid) kerb_count = 0 for node in res.nodes: if node in target_sids: kerb_count += 1 del target_sids[ node] #disposing the found ndoe, to avoid dupes return kerb_count
def query_path_da(graphid, format='vis'): if graphid not in graphs: return 'Graph Not Found', 404 da_sids = {} #searching for domain admin SID for node in graphs[graphid].get_node(): if node.id == graphs[graphid].domain_sid + '-512': da_sids[node.id] = 1 if len(da_sids) == 0: return 'No domain administrator group found', 404 res = GraphData() for sid in da_sids: res += graphs[graphid].all_shortest_paths(None, sid) #print(res) return res.to_dict(format=format)
def shortest_paths(self, src_sid=None, dst_sid=None, ignore_notfound=False, exclude=[]): nv = GraphData() try: if src_sid is None and dst_sid is None: raise Exception('src_sid or dst_sid must be set') elif src_sid is None and dst_sid is not None: dst = self.__resolve_sid_to_id(dst_sid) if dst is None: raise Exception('SID not found!') res = shortest_path(self.graph, target=dst) for k in res: self.__result_path_add(nv, res[k], exclude=exclude) elif src_sid is not None and dst_sid is not None: dst = self.__resolve_sid_to_id(dst_sid) if dst is None: raise Exception('SID not found!') src = self.__resolve_sid_to_id(src_sid) if src is None: raise Exception('SID not found!') try: res = shortest_path(self.graph, src, dst) self.__result_path_add(nv, res, exclude=exclude) except nx.exception.NetworkXNoPath: pass elif src_sid is not None and dst_sid is None: src = self.__resolve_sid_to_id(src_sid) if src is None: raise Exception('SID not found!') try: res = shortest_path(self.graph, src) for k in res: self.__result_path_add(nv, res[k], exclude=exclude) except nx.exception.NetworkXNoPath: pass else: raise Exception('Not implemented!') return nv except nx.exception.NodeNotFound: if ignore_notfound is True: return nv raise
def query_path_fromowned(graphid, format='vis'): if graphid not in current_app.config['JACKDAW_GRAPH_DICT']: load(graphid) target_sids = {} for res in current_app.db.session.query(EdgeLookup.oid)\ .filter_by(ad_id = current_app.config['JACKDAW_GRAPH_DICT'][graphid].domain_id)\ .filter(EdgeLookup.oid == ADObjProps.oid)\ .filter(ADObjProps.ad_id == current_app.config['JACKDAW_GRAPH_DICT'][graphid].domain_id)\ .filter(ADObjProps.prop == 'OWNED')\ .all(): target_sids[res[0]] = 0 res = GraphData() for src_sid in target_sids: res += current_app.config['JACKDAW_GRAPH_DICT'][ graphid].shortest_paths(src=src_sid) return res.to_dict(format=format)
def query_path_dcsync(graphid, format='vis'): if graphid not in current_app.config['JACKDAW_GRAPH_DICT']: load(graphid) target_sids = {} da_sids = {current_app.config['JACKDAW_GRAPH_DICT'][graphid].domain_sid: 0} for res in current_app.db.session.query(EdgeLookup.oid)\ .filter_by(ad_id = current_app.config['JACKDAW_GRAPH_DICT'][graphid].domain_id)\ .filter(EdgeLookup.id == Edge.src)\ .filter(EdgeLookup.oid != None)\ .filter(or_(Edge.label == 'GetChanges', Edge.label == 'GetChangesAll'))\ .all(): target_sids[res[0]] = 0 res = GraphData() for dst_sid in da_sids: for src_sid in target_sids: res += current_app.config['JACKDAW_GRAPH_DICT'][ graphid].shortest_paths(src_sid, dst_sid) return res.to_dict(format=format)
async def do_pathda(self, cmd): if self.graph_id not in self.graphs: self.loadgraph(self.graph_id) da_sids = {} for res in self.db_session.query(Group).filter_by(ad_id = self.graphs[self.graph_id].domain_id).filter(Group.objectSid.like('%-512')).all(): da_sids[res.objectSid] = 0 if len(da_sids) == 0: return 'No domain administrator group found', 404 res = GraphData() for sid in da_sids: res += self.graphs[self.graph_id].shortest_paths(None, sid) await self.send_result(cmd, res)
def shortest_paths(self, src_sid=None, dst_sid=None): nv = GraphData() if src_sid is None and dst_sid is None: raise Exception('src_sid or dst_sid must be set') elif src_sid is None and dst_sid is not None: dst = self.__resolve_sid_to_id(dst_sid) if dst is None: raise Exception('SID not found!') total = self.dbsession.query(func.count( EdgeLookup.id)).filter_by(ad_id=self.domain_id).filter( EdgeLookup.oid != self.domain_sid + '-513').scalar() q = self.dbsession.query( EdgeLookup.id).filter_by(ad_id=self.domain_id).filter( EdgeLookup.oid != self.domain_sid + '-513') for nodeid in tqdm(windowed_query(q, EdgeLookup.id, 1000), desc='running', total=total): for i, res in enumerate(shortest_path(self.graph, nodeid, dst)): if res == []: continue if i % 2 == 0: self.__result_path_add(nv, res) elif src_sid is not None and dst_sid is not None: dst = self.__resolve_sid_to_id(dst_sid) if dst is None: raise Exception('SID not found!') src = self.__resolve_sid_to_id(src_sid) if src is None: raise Exception('SID not found!') for i, res in enumerate(shortest_path(self.graph, src, dst)): if res == []: continue if i % 2 == 0: self.__result_path_add(nv, res) else: raise Exception('Not implemented!') return nv
def get_dcsync(self): try: network = GraphData() forest_sids = [] groups = [] for adid in self.adids: adinfo = self.dbsession.query(ADInfo).get(adid) forest_sids.append(adinfo.objectSid) for forest_sid in forest_sids: self.add_node(network, self.resolve_sid_to_id(forest_sid)) for sid, otype in self.get_edges_onelevel( forest_sid, 'GetChanges', 'in'): if otype == 'group': groups.append(sid) if network.node_present(sid) is False: rid = self.resolve_sid_to_id(sid) self.add_node(network, rid) network.add_edge(forest_sid, sid, label='GetChanges') for sid, otype in self.get_edges_onelevel( forest_sid, 'GetChangesAll', 'in'): if otype == 'group': groups.append(sid) if network.node_present(sid) is False: rid = self.resolve_sid_to_id(sid) self.add_node(network, rid) network.add_edge(forest_sid, sid, label='GetChangesAll') for group_sid in groups: network += self.get_members(group_sid, 1) return network except Exception as e: import traceback traceback.print_exc() print(e) raise e
def all_shortest_paths(self, src_sid=None, dst_sid=None): nv = GraphData() if src_sid is None and dst_sid is None: raise Exception('src_sid or dst_sid must be set') elif src_sid is None and dst_sid is not None: dst = self.__resolve_sid_to_id(dst_sid) if dst is None: raise Exception('SID not found!') total = self.dbsession.query(func.count( EdgeLookup.id)).filter_by(ad_id=self.domain_id).filter( EdgeLookup.oid != self.domain_sid + '-513').scalar() q = self.dbsession.query( EdgeLookup.id).filter_by(ad_id=self.domain_id).filter( EdgeLookup.oid != self.domain_sid + '-513') for nodeid in tqdm(windowed_query(q, EdgeLookup.id, 1000), desc='running', total=total): for path in all_shortest_paths(self.graph, nodeid[0], dst): print(path) self.__result_path_add(nv, path) elif src_sid is not None and dst_sid is not None: print(1) print(src_sid) print(dst_sid) src = self.__resolve_sid_to_id(src_sid) if src is None: raise Exception('SID not found!') dst = self.__resolve_sid_to_id(dst_sid) if dst is None: raise Exception('SID not found!') print(src) print(dst) for path in all_shortest_paths(self.graph, src, dst): print(path) self.__result_path_add(nv, path) return nv
def __graph_distance_da(self, domainid, graphid): da_sids = {} for res in self.current_app.db.session.query(Group).filter_by( ad_id=self.current_app.config['JACKDAW_GRAPH_DICT'] [graphid].domain_id).filter(Group.objectSid.like('%-512')).all(): da_sids[res.objectSid] = 0 if len(da_sids) == 0: raise Exception('No domain admins found!') res = GraphData() for sid in da_sids: res += current_app.config['JACKDAW_GRAPH_DICT'][ graphid].shortest_paths(None, sid) distances = {} for node in res.nodes: if res.nodes[node].mindistance not in distances: distances[res.nodes[node].mindistance] = 0 distances[res.nodes[node].mindistance] += 1 #print('%s (%s)' % (res.nodes[node].name, res.nodes[node].mindistance)) return distances
async def do_pathda(self, cmd): try: if cmd.graphid not in self.graphs: _, err = await self.loadgraph(cmd.graphid) if err is not None: await self.send_error(cmd, 'Failed to load graph cache!') return da_sids = {} for domainid in self.graphs[cmd.graphid].adids: for res in self.db_session.query(Group).filter_by( ad_id=domainid).filter( Group.objectSid.like('%-512')).all(): da_sids[res.objectSid] = 0 if len(da_sids) == 0: continue res = GraphData() for sid in da_sids: res += self.graphs[cmd.graphid].shortest_paths(None, sid) edgeres = NestOpEdgeBuffRes() edgeres.token = cmd.token for edgeidx in res.edges: edgeres.edges.append( NestOpEdgeRes.from_graphedge(cmd, domainid, cmd.graphid, res.edges[edgeidx])) await self.websocket.send(edgeres.to_json()) await self.send_ok(cmd) except Exception as e: traceback.print_exc() await self.send_error(cmd, 'Error happened!') return False, e
def shortest_paths(self, src_sid=None, dst_sid=None, ignore_notfound=False, exclude=[], pathonly=False, maxhops=None): logger.info('shortest_paths called!') nv = GraphData() if pathonly is True: nv = [] try: if src_sid is None and dst_sid is None: raise Exception('src_sid or dst_sid must be set') res = None if self.use_cache is True: res = self.read_cachefile(src_sid, dst_sid) if src_sid is None and dst_sid is not None: dst = self.__resolve_sid_to_id(dst_sid) if dst is None: raise Exception('SID not found!') if res is None: res = shortest_path(self.graph, target=dst) if self.use_cache is True: self.write_cachefile(src_sid, dst_sid, res) for k in res: self.__result_path_add(nv, res[k][:maxhops], exclude=exclude, pathonly=pathonly) elif src_sid is not None and dst_sid is not None: dst = self.__resolve_sid_to_id(dst_sid) if dst is None: raise Exception('SID not found!') src = self.__resolve_sid_to_id(src_sid) if src is None: raise Exception('SID not found!') try: if res is None: res = shortest_path(self.graph, src, dst) if self.use_cache is True: self.write_cachefile(src_sid, dst_sid, res) self.__result_path_add(nv, res, exclude=exclude, pathonly=pathonly) except nx.exception.NetworkXNoPath: pass elif src_sid is not None and dst_sid is None: src = self.__resolve_sid_to_id(src_sid) if src is None: raise Exception('SID not found!') try: if res is None: res = shortest_path(self.graph, src) if self.use_cache is True: self.write_cachefile(src_sid, dst_sid, res) for k in res: self.__result_path_add(nv, res[k][:maxhops], exclude=exclude, pathonly=pathonly) except nx.exception.NetworkXNoPath: pass else: raise Exception('Not implemented!') logger.info('shortest_paths finished OK!') return nv except nx.exception.NodeNotFound: logger.info('shortest_paths finished ERR!') if ignore_notfound is True: return nv raise
#src_sid = 'S-1-5-21-796845957-1547161642-839522115-1286' dst_sid = 'S-1-5-21-796845957-1547161642-839522115-512' da_sids = {} #target_sids = {} # #for res in session.query(ADUser.objectSid)\ # .filter_by(ad_id = ad_id)\ # .filter(ADUser.servicePrincipalName != None).all(): # # target_sids[res[0]] = 0 # for res in session.query(Group).filter_by(ad_id=ad_id).filter( Group.objectSid.like('%-512')).all(): da_sids[res.objectSid] = 0 if len(da_sids) == 0: raise Exception('No DA!') res = GraphData() for sid in da_sids: res += a.shortest_paths(None, sid) #res = GraphData() #for src_sid in target_sids: # res += a.shortest_paths(src_sid, dst_sid) # #print(pprint.pprint(res.to_dict())) # print('src: %s dst: %s' % (src_sid, dst_sid)) # # input()
def shortest_paths(self, src_sid = None, dst_sid = None, ignore_notfound = False, exclude = [], pathonly = False, maxhops = None, all_shortest = False): logger.info('shortest_paths called!') nv = GraphData() if pathonly is True: nv = [] try: if src_sid is None and dst_sid is None: raise Exception('src_sid or dst_sid must be set') res = None if src_sid is None and dst_sid is not None: dst = self.resolve_sid_to_id(dst_sid) if dst is None: raise Exception('SID not found!') if res is None: if all_shortest is True: paths = self.graph.get_all_shortest_paths(dst, mode=igraph.IN) else: paths = self.graph.get_shortest_paths(dst, mode=igraph.IN) res = [] for path in paths: if len(path) == 0: continue res.append(path[::-1]) for path in res: self.result_path_add(nv, path[:maxhops], exclude = exclude, pathonly = pathonly) elif src_sid is not None and dst_sid is not None: dst = self.resolve_sid_to_id(dst_sid) if dst is None: raise Exception('SID not found!') src = self.resolve_sid_to_id(src_sid) if src is None: raise Exception('SID not found!') try: if res is None: if all_shortest is True: paths = self.graph.get_all_shortest_paths(src, to=dst, mode=igraph.OUT) else: paths = self.graph.get_shortest_paths(src, to=dst, mode=igraph.OUT) res = [] for path in paths: if len(path) == 0: continue res.append(path) for path in res: self.result_path_add(nv, path, exclude = exclude, pathonly = pathonly) except Exception as e: raise e #pass elif src_sid is not None and dst_sid is None: src = self.resolve_sid_to_id(src_sid) if src is None: raise Exception('SID not found!') try: if res is None: if all_shortest is True: paths = self.graph.get_all_shortest_paths(src, mode=igraph.OUT) else: paths = self.graph.get_shortest_paths(src, mode=igraph.OUT) res = [] for path in paths: if len(path) == 0: continue res.append(path) for path in res: self.result_path_add(nv, path[:maxhops], exclude = exclude, pathonly = pathonly) except Exception as e: raise e #pass else: raise Exception('Not implemented!') logger.info('shortest_paths finished OK!') return nv except Exception as e: logger.info('shortest_paths finished ERR!') traceback.print_exc() if ignore_notfound is True: return nv raise
def all_shortest_paths(self, src_sid=None, dst_sid=None): nv = GraphData() if not src_sid and not dst_sid: raise Exception('Either source or destination MUST be specified') elif src_sid is not None and dst_sid is not None: src = self.__resolve_sid_to_id(src_sid) if src is None: raise Exception('SID not found!') dst = self.__resolve_sid_to_id(dst_sid) if dst is None: raise Exception('SID not found!') for path in nx.all_shortest_paths(self.graph, src, dst): self.__result_path_add(nv, path) elif not src_sid and dst_sid: try: dst = self.__resolve_sid_to_id(dst_sid) if dst is None: raise Exception('SID not found!') #for each node we calculate the shortest path to the destination node, silently skip the ones who do not have path to dst inqueue = mp.Queue() outqueue = mp.Queue() procno = mp.cpu_count() logger.debug('[DST_CALC] Starting processes') procs = [ mp.Process(target=short_worker, args=(inqueue, outqueue, self.graph, dst_sid)) for i in range(procno) ] for proc in procs: proc.daemon = True proc.start() logger.debug('[DST_CALC] Starting generator thread') node_gen_th = threading.Thread(target=short_node_gen, args=(self.graph, inqueue, dst_sid, procno)) node_gen_th.daemon = True node_gen_th.start() p_cnt = 0 while True: path = outqueue.get() if path is None: procno -= 1 logger.debug('[DST_CALC] Proc X - Finished!') if procno == 0: break continue self.__result_path_add(nv, path) p_cnt += 1 logger.debug('[DST_CALC] Found %s paths to dst node %s' % (p_cnt, dst_sid)) logger.debug('[DST_CALC] joining processes') for proc in procs: proc.join() logger.debug('[DST_CALC] Finished!') except: logger.exception('[DST_CALC]') else: raise Exception('Working on it') return nv
async def do_pathowned(self, cmd): try: if cmd.graphid not in self.graphs: _, err = await self.loadgraph(cmd.graphid) if err is not None: await self.send_error(cmd, 'Failed to load graph cache!') return target_sids = {} for domainid in self.graphs[cmd.graphid].adids: for res in self.db_session.query(EdgeLookup.oid)\ .filter_by(ad_id = domainid)\ .filter(EdgeLookup.oid == ADObjProps.oid)\ .filter(ADObjProps.graph_id == cmd.graphid)\ .filter(ADObjProps.prop == 'OWNED')\ .all(): target_sids[res[0]] = 0 if cmd.dst.upper() == 'DA': da_sids = {} for domainid in self.graphs[cmd.graphid].adids: for qres in self.db_session.query(Group).filter_by( ad_id=domainid).filter( Group.objectSid.like('%-512')).all(): da_sids[qres.objectSid] = 0 if len(da_sids) == 0: continue res = GraphData() for dst_sid in da_sids: for src_sid in target_sids: res += self.graphs[cmd.graphid].shortest_paths( src_sid, dst_sid) elif cmd.dst.upper() == 'ANY': res = GraphData() for sid in target_sids: res += self.graphs[cmd.graphid].shortest_paths(sid, None) elif cmd.dst.upper() == 'HVT': hvt_targets = {} for domainid in self.graphs[cmd.graphid].adids: for res in self.db_session.query(EdgeLookup.oid)\ .filter_by(ad_id = domainid)\ .filter(EdgeLookup.oid == ADObjProps.oid)\ .filter(ADObjProps.graph_id == self.graphid)\ .filter(ADObjProps.prop == 'HVT')\ .all(): hvt_targets[res[0]] = 0 res = GraphData() for sid in target_sids: for dst in hvt_targets: res += self.graphs[cmd.graphid].shortest_paths( sid, dst) edgeres = NestOpEdgeBuffRes() edgeres.token = cmd.token for edgeidx in res.edges: edgeres.edges.append( NestOpEdgeRes.from_graphedge(cmd, domainid, cmd.graphid, res.edges[edgeidx])) await self.websocket.send(edgeres.to_json()) await self.send_ok(cmd) except Exception as e: traceback.print_exc() await self.send_error(cmd, 'Error happened!') return False, e