Exemple #1
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
Exemple #2
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
Exemple #3
0
 def path_find_existing(self, dst, as_ip=False):
     if dst in [host.name for host in Host.find_all()]:
         host = Host.find_one(name=dst)
         dst = host.closest_endpoint
     else:
         try:
             dst = Endpoint.find_one(ip_port=dst)
         except:
             print("Please specify a valid endpoint in the IP:PORT form")
             return
     if dst is None:
         print("The endpoint provided doesn't exist in this workspace")
         return
     if Path.direct(dst):
         print("The destination should be reachable from the host")
         return
     try:
         chain = Path.get(dst)
     except NoPathError:
         print("No path could be found to the destination")
         return
     if chain[0] is None:
         chain[0] = "local"
     if as_ip:
         print(" > ".join(str(link.closest_endpoint) \
                 if isinstance(link, Host) else str(link) for link in chain))
     else:
         print(" > ".join(str(link) for link in chain))
Exemple #4
0
 def __init__(self, name):
     from baboossh import Endpoint
     self.name = name
     self.endpoints = []
     cursor = Db.get().cursor()
     for row in cursor.execute('SELECT endpoint FROM tags WHERE name=?',
                               (self.name, )):
         self.endpoints.append(Endpoint.find_one(endpoint_id=row[0]))
Exemple #5
0
    def endpoint_add(self, ipaddr, port):
        """Add an :class:`Endpoint` to the workspace

        Args:
            ipaddr (str): the `Endpoint` 's IP address
            ipaddr (str): the `Endpoint` 's port
        """

        Endpoint(ipaddr, port).save()
Exemple #6
0
 def endpoints(self):
     """Returns a `List` of the `Host` 's :class:`Endpoint` s"""
     from baboossh import Endpoint
     endpoints = []
     cursor = Db.get().cursor()
     for row in cursor.execute(
             'SELECT ip, port FROM endpoints WHERE host=?', (self.id, )):
         endpoints.append(Endpoint(row[0], row[1]))
     cursor.close()
     return endpoints
Exemple #7
0
    def closest_endpoint(self):
        """Returns the `Host` 's closest :class:`Endpoint`"""

        cursor = Db.get().cursor()
        cursor.execute(
            'SELECT ip, port FROM endpoints WHERE host=? ORDER BY distance DESC',
            (self.id, ))
        row = cursor.fetchone()
        cursor.close()
        from baboossh import Endpoint
        return Endpoint(row[0], row[1])
Exemple #8
0
    def enum_probe(self, target=None, again=False):
        if target is not None:
            if target == "*":
                endpoints = Endpoint.find_all(scope=True)
            elif target[0] == "!":
                tag = Tag(target[1:])
                endpoints = tag.endpoints
            else:
                endpoint = Endpoint.find_one(ip_port=target)
                if endpoint is None:
                    raise ValueError("Supplied endpoint isn't in workspace")
                return [endpoint]
        elif self.options["endpoint"] is not None:
            if isinstance(self.options["endpoint"], Tag):
                return self.options["endpoint"].endpoints
            return [self.options["endpoint"]]
        else:
            endpoints = Endpoint.find_all(scope=True)

        if not again:
            endpoints = [endpoint for endpoint in endpoints if not endpoint.reachable]

        return endpoints
Exemple #9
0
 def __init__(self, creds_type, creds_content):
     self.creds_type = creds_type
     self.creds_content = creds_content
     self.obj = Extensions.auths[creds_type](creds_content)
     self.id = None
     self.scope = True
     self.found = None
     cursor = Db.get().cursor()
     cursor.execute('SELECT id, scope, found FROM creds WHERE type=? AND identifier=?', (self.creds_type, self.obj.identifier))
     saved_creds = cursor.fetchone()
     cursor.close()
     if saved_creds is not None:
         self.id = saved_creds[0]
         self.scope = saved_creds[1] != 0
         if saved_creds[2] is not None:
             from baboossh import Endpoint
             self.found = Endpoint.find_one(endpoint_id=saved_creds[2])
Exemple #10
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)
Exemple #11
0
    def endpoint_untag(self, endpoint, tagname):
        """Remove a :class:`Tag` from an :class:`Endpoint`

        Args:
            endpoint (str): the `Endpoint` 's string (ip:port)
            tagname (str): the :class:`Tag` name
        """

        if tagname[0] == "!":
            tagname = tagname[1:]
        try:
            endpoint = Endpoint.find_one(ip_port=endpoint)
        except ValueError:
            print("Could not find endpoint.")
            return False
        if endpoint is None:
            print("Could not find endpoint.")
            return False
        endpoint.untag(tagname)
        return True
Exemple #12
0
 def path_add(self, src, dst):
     if src.lower() != "local":
         if src not in [host.name for host in Host.find_all()]:
             print("Not a known Host name.")
             return
         src = Host.find_one(name=src)
         if src is None:
             print("The source Host provided doesn't exist in this workspace")
             return
     else:
         src = None
     try:
         dst = Endpoint.find_one(ip_port=dst)
     except:
         print("Please specify valid destination endpoint in the IP:PORT form")
     if dst is None:
         print("The destination endpoint provided doesn't exist in this workspace")
         return
     path = Path(src, dst)
     path.save()
     print("Path saved")
Exemple #13
0
    def find_one(cls, path_id=None):
        """Find an path by its id

        Args:
            pathId (int): the path id to search

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

        if path_id is None:
            return None
        cursor = Db.get().cursor()
        cursor.execute('''SELECT src, dst FROM paths WHERE id=?''',
                       (path_id, ))
        row = cursor.fetchone()
        cursor.close()
        if row is None:
            return None
        return Path(Host.find_one(host_id=row[0]),
                    Endpoint.find_one(endpoint_id=row[1]))
Exemple #14
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
Exemple #15
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
Exemple #16
0
    def find_all(cls, src=None, dst=None):
        """Find all Paths

        Args:
            src (:class:`.Host` or `None`): the Host to use as source, `"Local"` if `(int)0`
            dst (:class:`.Endpoint`): the Endpoint to use as destination

        Returns:
            A list of all `Path` s in the :class:`.Workspace`
        """

        if src is not None and src == 0:
            src_id = 0
        elif src is not None:
            src_id = src.id
        ret = []
        cursor = Db.get().cursor()
        if src is None:
            if dst is None:
                req = cursor.execute('SELECT src, dst FROM paths')
            else:
                req = cursor.execute('SELECT src, dst FROM paths WHERE dst=?',
                                     (dst.id, ))
        else:
            if dst is None:
                req = cursor.execute('SELECT src, dst FROM paths WHERE src=?',
                                     (src_id, ))
            else:
                req = cursor.execute('SELECT src, dst FROM paths WHERE src=? AND dst=?', \
                        (src_id, dst.id))
        for row in req:
            ret.append(
                Path(Host.find_one(host_id=row[0]),
                     Endpoint.find_one(endpoint_id=row[1])))
        cursor.close()
        return ret
Exemple #17
0
    def endpoint_del(self, endpoint):
        """Remove an :class:`Endpoint` from the workspace

        Args:
            endpoint (str): the `Endpoint` 's string (ip:port)
        """

        if endpoint[0] == "!":
            tag = Tag(endpoint[1:])
            for endpoint in tag.endpoints:
                self.unstore(endpoint.delete())
            return True
        try:
            endpoint = Endpoint.find_one(ip_port=endpoint)
        except ValueError:
            print("Could not find endpoint.")
            return False
        if endpoint is None:
            print("Could not find endpoint.")
            return False
        if self.options["endpoint"] == endpoint:
            self.set_option("endpoint", None)
        self.unstore(endpoint.delete())
        return True
Exemple #18
0
 def path_del(self, src, dst):
     if str(src).lower() != "local":
         if src not in [host.name for host in Host.find_all()]:
             print("Not a known Host name.")
             return False
         src = Host.find_one(name=src)
         if src is None:
             print("The source Host provided doesn't exist in this workspace")
             return False
     else:
         src = None
     try:
         dst = Endpoint.find_one(ip_port=dst)
     except:
         print("Please specify valid destination endpoint in the IP:PORT form")
     if dst is None:
         print("The destination endpoint provided doesn't exist in this workspace")
         return False
     path = Path(src, dst)
     if path.id is None:
         print("The specified Path doesn't exist in this workspace.")
         return False
     self.unstore(path.delete())
     return True
Exemple #19
0
 def endpoint_search(self, field, val, show_all=False, add_tag=None):
     endpoints = Endpoint.search(field, val, show_all)
     if add_tag is not None:
         for endpoint in endpoints:
             endpoint.tag(add_tag)
     return endpoints
Exemple #20
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
    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
Exemple #22
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]))
Exemple #23
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