예제 #1
0
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)
예제 #2
0
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)
예제 #3
0
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)
예제 #4
0
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)
예제 #5
0
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)
예제 #6
0
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)
예제 #7
0
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)
예제 #8
0
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)
예제 #9
0
    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
예제 #10
0
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')
예제 #11
0
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)
예제 #12
0
파일: operator.py 프로젝트: skelsec/jackdaw
    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
예제 #13
0
	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
예제 #14
0
파일: operator.py 프로젝트: skelsec/jackdaw
    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
예제 #15
0
    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
예제 #16
0
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)
예제 #17
0
    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
예제 #18
0
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)
예제 #19
0
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)
예제 #20
0
	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)
예제 #21
0
    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
예제 #22
0
    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
예제 #23
0
    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
예제 #24
0
    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
예제 #25
0
파일: operator.py 프로젝트: skelsec/jackdaw
    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
예제 #26
0
    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
예제 #27
0
#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()
예제 #28
0
	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
예제 #29
0
    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
예제 #30
0
파일: operator.py 프로젝트: skelsec/jackdaw
    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