Ejemplo n.º 1
0
    def find_one(cls,
                 connection_id=None,
                 endpoint=None,
                 scope=None,
                 gateway_to=None):
        """Find a `Connection` by its id, endpoint or if it can be used as a gateway to an :class:`Endpoint`

        Args:
            connection_id (int): the `Connection` id to search
            endpoint (:class:`Endpoint`): the `Connection` endpoint to search
            gateway_to (:class:`Endpoint`): the Endpoint to which you want to find a gateway
            scope (bool): whether to include only in scope Connections (`True`), out of scope Connections (`False`) or both (`None`)

        Returns:
            A single `Connection` or `None`.
        """

        if gateway_to is not None:
            if gateway_to.distance is not None and gateway_to.distance == 0:
                return None
            try:
                closest_host = Host.find_one(prev_hop_to=gateway_to)
            except NoPathError as exc:
                raise exc
            if closest_host is None:
                return None
            return cls.find_one(endpoint=closest_host.closest_endpoint,
                                scope=True)

        cursor = Db.get().cursor()
        if connection_id is not None:
            req = cursor.execute(
                'SELECT endpoint, user, cred FROM connections WHERE id=?',
                (connection_id, ))
        elif endpoint is not None:
            req = cursor.execute(
                'SELECT endpoint, user, cred FROM connections WHERE endpoint=? ORDER BY root ASC',
                (endpoint.id, ))
        else:
            cursor.close()
            return None
        if scope is None:
            row = cursor.fetchone()
            cursor.close()
            if row is None:
                return None
            return Connection(Endpoint.find_one(endpoint_id=row[0]),
                              User.find_one(user_id=row[1]),
                              Creds.find_one(creds_id=row[2]))
        for row in req:
            conn = Connection(Endpoint.find_one(endpoint_id=row[0]),
                              User.find_one(user_id=row[1]),
                              Creds.find_one(creds_id=row[2]))
            if scope == conn.scope:
                cursor.close()
                return conn
        cursor.close()
        return None
Ejemplo n.º 2
0
    def creds_add(self, creds_type, stmt):
        """Add :class:`Creds` to the workspace

        Args:
            creds_type (str): The `Creds` ' object type
            stmt (`argparse.Namespace`): the rest of the command be parsed by the object
        """

        content = Extensions.auths[creds_type].fromStatement(stmt)
        new_creds = Creds(creds_type, content)
        new_creds.save()
        return new_creds.id
Ejemplo n.º 3
0
    def from_target(cls, arg):
        if '@' in arg and ':' in arg:
            auth, sep, endpoint = arg.partition('@')
            endpoint = Endpoint.find_one(ip_port=endpoint)
            if endpoint is None:
                raise ValueError("Supplied endpoint isn't in workspace")
            user, sep, cred = auth.partition(":")
            if sep == "":
                raise ValueError("No credentials supplied")
            user = User.find_one(name=user)
            if user is None:
                raise ValueError("Supplied user isn't in workspace")
            if cred[0] == "#":
                cred = cred[1:]
            cred = Creds.find_one(creds_id=cred)
            if cred is None:
                raise ValueError("Supplied credentials aren't in workspace")
            return Connection(endpoint, user, cred)

        if ':' not in arg:
            arg = arg + ':22'
        endpoint = Endpoint.find_one(ip_port=arg)
        if endpoint is None:
            raise ValueError("Supplied endpoint isn't in workspace")
        connection = cls.find_one(endpoint=endpoint)
        if connection is None:
            raise ValueError("No working connection for supplied endpoint")
        return connection
Ejemplo n.º 4
0
    def creds_edit(self, creds_id):
        """Edit a :class:`Creds` ' properties

        Args:
            creds_id (str): The `Creds` ' id
        """

        if creds_id[0] == '#':
            creds_id = creds_id[1:]
        creds = Creds.find_one(creds_id=creds_id)
        if creds is None:
            print("Specified creds not found")
            return
        creds.edit()
Ejemplo n.º 5
0
    def creds_del(self, creds_id):
        """Delete a :class:`Creds` ' from the workspace

        Args:
            creds_id (str): The `Creds` ' id
        """

        if creds_id[0] == '#':
            creds_id = creds_id[1:]
        creds = Creds.find_one(creds_id=creds_id)
        if creds is None:
            print("Specified creds not found")
            return False
        if self.options["creds"] == creds:
            self.set_option("creds", None)
        self.unstore(creds.delete())
        return True
Ejemplo n.º 6
0
    def enum_run(self, target=None):
        if target is not None:
            if '@' not in target:
                host = Host.find_one(name=target)
                if host is not None:
                    conn = Connection.find_one(endpoint=host.closest_endpoint)
                    if conn is not None:
                        return [conn]
                raise ValueError("Supplied value doesn't match a known host or a connection string")

            auth, sep, endpoint = target.partition('@')
            if endpoint == "*":
                endpoint = None
            elif endpoint[0] == "!":
                tag = Tag(endpoint[1:])
                endpoints = tag.endpoints
            else:
                endpoint = Endpoint.find_one(ip_port=endpoint)
                if endpoint is None:
                    raise ValueError("Supplied endpoint isn't in workspace")

            user, sep, cred = auth.partition(":")
            if sep == "":
                raise ValueError("No credentials supplied")
            if user == "*":
                user = None
            else:
                user = User.find_one(name=user)
                if user is None:
                    raise ValueError("Supplied user isn't in workspace")
            if cred == "*":
                cred = None
            else:
                if cred[0] == "#":
                    cred = cred[1:]
                cred = Creds.find_one(creds_id=cred)
                if cred is None:
                    raise ValueError("Supplied credentials aren't in workspace")
        else:
            user = self.options["user"]
            endpoint = self.options["endpoint"]
            cred = self.options["creds"]

        return Connection.find_all(endpoint=endpoint, user=user, creds=cred)
Ejemplo n.º 7
0
 def get_objects(self, local=False, hosts=False, connections=False, endpoints=False, \
         users=False, creds=False, tunnels=False, paths=False, scope=None, tags=None):
     ret = []
     if local:
         ret.append("local")
     if hosts:
         ret = ret + Host.find_all(scope=scope)
     if connections:
         ret = ret + Connection.find_all(scope=scope)
     if endpoints:
         ret = ret + Endpoint.find_all(scope=scope)
     if users:
         ret = ret + User.find_all(scope=scope)
     if creds:
         ret = ret + Creds.find_all(scope=scope)
     if tunnels:
         ret = ret + list(self.tunnels.values())
     if paths:
         ret = ret + Path.find_all()
     if tags:
         ret = ret + Tag.find_all()
     return ret
Ejemplo n.º 8
0
 def identify_object(self, target):
     if target[0] == "#":
         creds_id = target[1:]
     else:
         creds_id = target
     creds = Creds.find_one(creds_id=creds_id)
     if creds is not None:
         return creds
     user = User.find_one(name=target)
     if user is not None:
         return user
     try:
         dst = Endpoint.find_one(ip_port=target)
         if dst is not None:
             return dst
     except:
         pass
     host = Host.find_one(name=target)
     if host is not None:
         return host
     print("Could not identify object.")
     return None
Ejemplo n.º 9
0
    def enum_connect(self, target=None, force=False, unprobed=False):
        if target is not None:
            if '@' not in target:
                host = Host.find_one(name=target)
                if host is not None:
                    conn = Connection.find_one(endpoint=host.closest_endpoint)
                    if conn is not None:
                        return [conn]
                raise ValueError("Supplied value doesn't match a known host or a connection string")

            auth, sep, endpoint = target.partition('@')
            if endpoint == "*":
                endpoints = Endpoint.find_all(scope=True)
            elif endpoint[0] == "!":
                tag = Tag(endpoint[1:])
                endpoints = tag.endpoints
            else:
                endpoint = Endpoint.find_one(ip_port=endpoint)
                if endpoint is None:
                    raise ValueError("Supplied endpoint isn't in workspace")
                endpoints = [endpoint]

            user, sep, cred = auth.partition(":")
            if sep == "":
                raise ValueError("No credentials supplied")
            if user == "*":
                users = User.find_all(scope=True)
            else:
                user = User.find_one(name=user)
                if user is None:
                    raise ValueError("Supplied user isn't in workspace")
                users = [user]
            if cred == "*":
                creds = Creds.find_all(scope=True)
            else:
                if cred[0] == "#":
                    cred = cred[1:]
                cred = Creds.find_one(creds_id=cred)
                if cred is None:
                    raise ValueError("Supplied credentials aren't in workspace")
                creds = [cred]
            if len(endpoints)*len(users)*len(creds) == 1:
                return [Connection(endpoints[0], users[0], creds[0])]
        else:
            user = self.options["user"]
            if user is None:
                users = User.find_all(scope=True)
            else:
                users = [user]
            endpoint = self.options["endpoint"]
            if isinstance(endpoint, Tag):
                endpoints = endpoint.endpoints
            elif endpoint is None:
                endpoints = Endpoint.find_all(scope=True)
            else:
                endpoints = [endpoint]
            cred = self.options["creds"]
            if cred is None:
                creds = Creds.find_all(scope=True)
            else:
                creds = [cred]
            if len(endpoints)*len(users)*len(creds) == 1:
                return [Connection(endpoints[0], users[0], creds[0])]

        ret = []
        for endpoint in endpoints:
            if not unprobed and not endpoint.reachable:
                continue
            for user in users:
                if len(creds) != 1:
                    working_connections = Connection.find_all(endpoint=endpoint, user=user)
                    if not force and working_connections:
                        print("Connection already found with user "+str(user)+" on endpoint "+str(endpoint)+", creds bruteforcing is disabled. Specify creds or use --force.")
                        continue
                for cred in creds:
                    conn = Connection(endpoint, user, cred)
                    if force:
                        ret.append(conn)
                    else:
                        if conn.id is None:
                            ret.append(conn)
        return ret
Ejemplo n.º 10
0
    def set_option(self, option, value):
        """Set an option for the `Workspace`

        Args:
            option (str): the option to set
            value (str): the new value
        """

        if option == 'connection':
            if value is None:
                self.options['endpoint'] = None
                self.options['user'] = None
                self.options['creds'] = None

                print("endpoint => "+str(self.options['endpoint']))
                print("user => "+str(self.options['user']))
                print("creds => "+str(self.options['creds']))

            elif '@' not in value or ':' not in value:
                return
            connection = Connection.from_target(value)
            if connection is None:
                return
            self.options['endpoint'] = connection.endpoint
            self.options['user'] = connection.user
            self.options['creds'] = connection.creds

            print("endpoint => "+str(self.options['endpoint']))
            print("user => "+str(self.options['user']))
            print("creds => "+str(self.options['creds']))
            return

        if not option in list(self.options.keys()):
            raise ValueError(option+" isn't a valid option.")

        if value is not None:
            value = value.strip()
            if option == "endpoint":
                if value[0] == "!":
                    value = Tag(value[1:])
                else:
                    endpoint = Endpoint.find_one(ip_port=value)
                    if endpoint is None:
                        raise ValueError
                    value = endpoint
            elif option == "user":
                user = User.find_one(name=value)
                if user is None:
                    raise ValueError
                value = user
            elif option == "creds":
                if value[0] == '#':
                    creds_id = value[1:]
                else:
                    creds_id = value
                creds = Creds.find_one(creds_id=creds_id)
                if creds is None:
                    raise ValueError
                value = creds
            elif option == "payload":
                value = Extensions.payloads[value]
            self.options[option] = value
        else:
            self.options[option] = None
        print(option+" => "+str(self.options[option]))
Ejemplo n.º 11
0
    def find_all(cls, endpoint=None, user=None, creds=None, scope=None):
        """Find all `Connection` matching the criteria

        If two or more arguments are specified, the returned Connections must match each ("AND")

        Args:
            endpoint (:class:`Endpoint` or :class:`Tag`): the `Connection` endpoint to search or a :class:`Tag` of endpoints to search
            user (:class:`User`): the `Connection` user to search
            creds (:class:`Creds`): the `Connection` creds to search
            scope (bool): whether to include only in scope Connections (`True`), out of scope Connections (`False`) or both (`None`)

        Returns:
            A list of matching `Connection`.
        """

        ret = []
        cursor = Db.get().cursor()

        query = 'SELECT endpoint, user, cred FROM connections'
        params = []
        first = True
        if endpoint is not None and not isinstance(endpoint, Tag):
            if first:
                query = query + ' WHERE '
                first = False
            else:
                query = query + ' AND '
            query = query + 'endpoint=?'
            params.append(endpoint.id)
        elif endpoint is not None and isinstance(endpoint, Tag):
            if first:
                query = query + ' WHERE ('
                first = False
            else:
                query = query + ' AND ('
            first_endpoint = True
            for end in endpoint.endpoints:
                if not first_endpoint:
                    query = query + ' OR '
                else:
                    first_endpoint = False
                query = query + 'endpoint=?'
                params.append(end.id)
            query = query + ' )'
        if user is not None:
            if first:
                query = query + ' WHERE '
                first = False
            else:
                query = query + ' AND '
            query = query + 'user=?'
            params.append(user.id)
        if creds is not None:
            if first:
                query = query + ' WHERE '
                first = False
            else:
                query = query + ' AND '
            query = query + 'cred=?'
            params.append(creds.id)

        req = cursor.execute(query, tuple(params))

        for row in req:
            conn = Connection(Endpoint.find_one(endpoint_id=row[0]),
                              User.find_one(user_id=row[1]),
                              Creds.find_one(creds_id=row[2]))
            if scope is None or conn.scope == scope:
                ret.append(conn)
        cursor.close()
        return ret
Ejemplo n.º 12
0
    def run(cls, stmt, workspace):
        outfile = getattr(stmt, 'output')
        findings = getattr(stmt, 'findings', False)
        dotcode = 'digraph compromission_graph {\nnode [shape=plain,fontname="monospace"];\nrankdir="LR";\n'
        for endpoint in workspace.get_objects(endpoints=True, scope=True):
            label = "<table cellborder='1' cellspacing='0'><tr><td>" + str(
                endpoint) + "</td></tr>"
            if endpoint.host is not None:
                label = label + '<tr><td>' + str(endpoint.host) + '</td></tr>'
            if findings:
                foundEndpoints = Endpoint.find_all(found=endpoint, scope=True)
                foundUsers = User.find_all(found=endpoint, scope=True)
                foundCreds = Creds.find_all(found=endpoint, scope=True)

                if foundEndpoints or foundUsers or foundCreds:
                    label = label + "<tr><td><table cellborder='1' cellspacing='0'><tr><td colspan='2'>Findings</td></tr>"

                    if foundEndpoints:
                        label = label + '<tr><td>Endpoints</td><td>'
                        first = True
                        for foundEndpoint in foundEndpoints:
                            if not first:
                                label = label + '<br />'
                            else:
                                first = False
                            label = label + str(foundEndpoint)
                        label = label + '</td></tr>'

                    if foundUsers:
                        label = label + '<tr><td>Users</td><td>'
                        first = True
                        for user in foundUsers:
                            if not first:
                                label = label + '<br />'
                            else:
                                first = False
                            label = label + str(user)
                        label = label + '</td></tr>'

                    if foundCreds:
                        label = label + '<tr><td>Creds</td><td>'
                        first = True
                        for cred in foundCreds:
                            if not first:
                                label = label + '<br />'
                            else:
                                first = False
                            label = label + str(cred)
                        label = label + '</td></tr>'
                    label = label + "</table></td></tr>"
            label = label + "</table>"

            dotcode = dotcode + 'node_' + str(
                endpoint.id) + ' [label=<' + label + '>]\n'
            if endpoint.found is None:
                dotcode = dotcode + '"local" -> "node_' + str(
                    endpoint.id) + '"\n'
            else:
                dotcode = dotcode + '"node_' + str(
                    endpoint.found.id) + '" -> "node_' + str(
                        endpoint.id) + '"\n'
        dotcode = dotcode + '}'
        with open(outfile, "w") as f:
            f.write(dotcode)
        print("Export saved as " + outfile)
        return True