Ejemplo n.º 1
0
 def __init__(self, dumpIO, factory):
     """
     :param dumpIO: An instance of squinnie.dio.DumpIO for loading the data
     """
     self.m_dumpIO = dumpIO
     self.m_ll_data = CategoryLoader("sysvipc", self.m_dumpIO)
     self.m_daw_factory = factory
Ejemplo n.º 2
0
 def __init__(self, dumpIO, uid_gid=None):
     """
     :param dumpIO: An instance of squinnie.dio.DumpIO for loading the data
     :dict uid_gid: contains inode: data entries of found user namespaces
     """
     self.m_dumpIO = dumpIO
     self.m_ll_data = CategoryLoader("userdata", self.m_dumpIO)
     self.m_data = self.m_ll_data.getData()
     if uid_gid:
         # load additional uid/gid-mappings from inside user namespaces
         for inode, ns_data in uid_gid.items():
             if not ns_data['uid'] and not ns_data['gid']:
                 # no uid-/gid-mappings inside this user-namespace
                 continue
             # mapping-lists contain the following structure:
             # ID-inside-ns  ID-outside-ns   length
             # however, there can be multiple entries, we only care
             # about the first one and the offset of the parent ids.
             uid_offset = int(ns_data['uid'][0][1])
             gid_offset = int(ns_data['gid'][0][1])
             for offset, key in [(uid_offset, 'uids'),
                                 (gid_offset, 'gids')]:
                 for mapping in ns_data[key].items():
                     value = int(mapping[0]) + offset
                     if not value in self.m_data[key]:
                         # adding the ids to the ones we already know
                         self.m_data[key][value] = "{}(user-ns)".format(
                             mapping[1])
                     else:
                         error = """Overlapping {}: {} already exists!
                         This could be caused by misconfigured
                         uid/gid mapping on scanning target!""".format(
                             key, value)
                         raise ValueError(error)
Ejemplo n.º 3
0
class NetworkingWrapper(object):
    """
    This class abstracts all info about network connections including unix sockets.
    """

    PROTOCOLS = ["tcp", "tcp6", "udp", "udp6", "unix", "netlink", "packet"]

    def __init__(self, dumpIO):
        """
        :param dumpIO: An instance of squinnie.dio.DumpIO for loading the data
        """
        self.m_dumpIO = dumpIO
        self.m_ll_protos = CategoryLoader("networking", self.m_dumpIO)

    def getProtocols(self):
        """Returns a list of all currently possible protocols."""
        return self.PROTOCOLS

    def getProtocolData(self, protocol):
        """Returns the data for a specific protocol."""
        return self.m_ll_protos.getData()[protocol]

    def getDataForAllProtocols(self):
        """Returns the data for all protocols"""
        return self.m_ll_protos.getData()
Ejemplo n.º 4
0
 def __init__(self, dumpIO):
     """
     :param dumpIO: An instance of squinnie.dio.DumpIO
     """
     self.m_dumpIO = dumpIO
     self.m_data = CategoryLoader("namespaces", self.m_dumpIO)
     self.m_data_deep = CategoryLoader("namespaces_deep", self.m_dumpIO)
Ejemplo n.º 5
0
class SystemData(object):
    """This class abstracts the SysVIPC communications."""
    def __init__(self, dumpIO):
        """
        :param dumpIO: An instance of squinnie.dio.DumpIO for loading the data
        """
        self.m_dumpIO = dumpIO
        self.m_ll_data = CategoryLoader("systemdata", self.m_dumpIO)

    def getSysconfData(self):
        """
        Returns all sysconfig values/
        """
        return self.m_ll_data.getData()['sysconf']

    def getSystemUptime(self):
        """
        Returns the uptime of the system at the time of scanning in seconds.
        """
        return float(self.m_ll_data.getData()['uptime'])

    def getMountinfo(self):
        """
        Returns information about all mounted filesystems.
        """
        return self.m_ll_data.getData()['mounts']

    def getProcessUptime(self, ticks):
        """
        Returns the time a process has been running for in seconds.
        :param ticks: The ticks as given in /proc/<pid>/stat
        :return: The runtime in seconds.
        """
        # the tick count in stat is the time in ticks the process has been started
        # so, at first, we need to convert the ticks to seconds:
        seconds_at_start = float(ticks) / float(
            self.getSysconfData()['SC_CLK_TCK'])

        # so now, we need to substract the starttime from the uptime to get the actual runtime
        return self.getSystemUptime() - seconds_at_start

    def getShmData(self):
        """
        Returns the shm data as dict array with inode and names.
        :return:
        """
        return self.m_ll_data.getData()['shm']

    def getNameForShmInode(self, inode):
        """
        Returns the name of a shm or semaphore in /dev/shm by inode.
        :param inode: The inode to search for.
        :return: The name as a string.
        """
        for item in self.getShmData():
            if item['inode'] == int(inode):
                return item['name']
        return None
Ejemplo n.º 6
0
 def __init__(self, dumpIO, factory):
     """
     :param dumpIO: An instance of squinnie.dio.DumpIO for loading the data
     """
     self.m_dumpIO = dumpIO
     self.m_data = {}
     self.m_ll_proc = CategoryLoader("proc_data", self.m_dumpIO)
     # self.m_ll_children = CategoryLoader("children", self.m_dumpIO)
     self.m_ll_parents = CategoryLoader("parents", self.m_dumpIO)
     self.m_daw_factory = factory
     self.m_socket_connection_cache = SocketCache()
     self.m_shm_cache = ShmCache()
Ejemplo n.º 7
0
class NetworkInterfaceWrapper(object):
    """
    This class abstracts all information about network interfaces
    """

    def __init__(self, dumpIO):
        """
        :param dumpIO: An instance of squinnie.dio.DumpIO
        """
        self.m_dumpIO = dumpIO
        self.m_data = CategoryLoader("nwifaces", self.m_dumpIO)

    def getAllNwIfaceData(self):
        return self.m_data.getData()
Ejemplo n.º 8
0
class NamespaceWrapper(object):
    """
    This class abstracts all information about available namespaces.
    """
    def __init__(self, dumpIO):
        """
        :param dumpIO: An instance of squinnie.dio.DumpIO
        """
        self.m_dumpIO = dumpIO
        self.m_data = CategoryLoader("namespaces", self.m_dumpIO)
        self.m_data_deep = CategoryLoader("namespaces_deep", self.m_dumpIO)

    def getNamespaceUidGid(self):
        result = None
        data = self.m_data_deep.getData()
        if 'user' in data:
            result = data['user']
        return result

    def getAllNamespaceData(self):
        return self.m_data.getData()

    def getAllDeepNsData(self):
        return self.m_data_deep.getData()
Ejemplo n.º 9
0
class SysVIPC(object):
    """This class abstracts the SysVIPC communications."""

    # this is the name of the key which contains the id name for each protocol
    IDKEYS = {'shm': 'shmid', 'msg': 'msqid', 'sem': 'semid'}

    def __init__(self, dumpIO, factory):
        """
        :param dumpIO: An instance of squinnie.dio.DumpIO for loading the data
        """
        self.m_dumpIO = dumpIO
        self.m_ll_data = CategoryLoader("sysvipc", self.m_dumpIO)
        self.m_daw_factory = factory

    def getSysVIpcData(self):
        """Return the raw sysv ipc data."""
        return self.m_ll_data.getData()

    def getFormattedData(self):
        """
        Returns the data formatted for printing as a table with the columns:
        type\perms\user\group\key\id\ctime\cpid\otime\opid
        """
        data = []
        authmgr = self.m_daw_factory.getAccountWrapper()

        for category, ccons in self.getSysVIpcData().items():
            for cdata in ccons:
                data.append([
                    category, cdata['perms'][-3:],
                    authmgr.getNameForUid(cdata['uid'], ''),
                    authmgr.getNameForGid(cdata['gid'], ''), cdata['key'],
                    cdata[self.IDKEYS[category]],
                    self._formatTimestamp(cdata['ctime']),
                    cdata['cpid'] if 'cpid' in cdata else '',
                    self._formatTimestamp(cdata['atime'] if 'atime' in
                                          cdata else cdata.get('otime', '')),
                    cdata['lpid'] if 'lpid' in cdata else ''
                ])

        return data

    @staticmethod
    def _formatTimestamp(ts):
        """Makes a timestamp human-readable."""
        return datetime.datetime.fromtimestamp(
            int(ts)).strftime('%Y-%m-%d %H:%M:%S') if ts else ''
Ejemplo n.º 10
0
 def __init__(self, dumpIO):
     """
     :param dumpIO: An instance of squinnie.dio.DumpIO for loading the data
     """
     self.m_dumpIO = dumpIO
     self.m_ll_data = CategoryLoader("systemdata", self.m_dumpIO)
Ejemplo n.º 11
0
class AccountWrapper(object):
    """
    This class abstracts all data about users and groups. So far this data is unfortunately only the mapping of the
    uid/gid to a name, which does not allow any more metadata (for example home directories).
    """
    def __init__(self, dumpIO, uid_gid=None):
        """
        :param dumpIO: An instance of squinnie.dio.DumpIO for loading the data
        :dict uid_gid: contains inode: data entries of found user namespaces
        """
        self.m_dumpIO = dumpIO
        self.m_ll_data = CategoryLoader("userdata", self.m_dumpIO)
        self.m_data = self.m_ll_data.getData()
        if uid_gid:
            # load additional uid/gid-mappings from inside user namespaces
            for inode, ns_data in uid_gid.items():
                if not ns_data['uid'] and not ns_data['gid']:
                    # no uid-/gid-mappings inside this user-namespace
                    continue
                # mapping-lists contain the following structure:
                # ID-inside-ns  ID-outside-ns   length
                # however, there can be multiple entries, we only care
                # about the first one and the offset of the parent ids.
                uid_offset = int(ns_data['uid'][0][1])
                gid_offset = int(ns_data['gid'][0][1])
                for offset, key in [(uid_offset, 'uids'),
                                    (gid_offset, 'gids')]:
                    for mapping in ns_data[key].items():
                        value = int(mapping[0]) + offset
                        if not value in self.m_data[key]:
                            # adding the ids to the ones we already know
                            self.m_data[key][value] = "{}(user-ns)".format(
                                mapping[1])
                        else:
                            error = """Overlapping {}: {} already exists!
                            This could be caused by misconfigured
                            uid/gid mapping on scanning target!""".format(
                                key, value)
                            raise ValueError(error)

    def getNameForUid(self, uid, default=None):
        """Returns the name of the user for a specific uid."""
        data = self.m_data['uids']
        return data[int(uid)] if int(uid) in data else default

    def getNameForGid(self, gid, default=None):
        """Returns the name of the group for a specific group id."""
        data = self.m_data['gids']
        return data[int(gid)] if int(gid) in data else default

    def getGidForName(self, name):
        """Returns the GID for an account or None if it can't be resolved."""
        # this lookup is quite inefficient, but so far its only used once per execution and one shouldn't over-optimize.
        data = self.m_data['gids']
        for gid, gname in data.items():
            if gname == name:
                return gid
        return None

    def getUidForName(self, name):
        """Returns the GID for an account or None if it can't be resolved."""
        # this lookup is quite inefficient, but so far its only used once per execution and one shouldn't over-optimize.
        data = self.m_data['uids']
        for uid, uname in data.items():
            if uname == name:
                return uid
        return None
Ejemplo n.º 12
0
 def __init__(self, dumpIO):
     """
     :param dumpIO: An instance of squinnie.dio.DumpIO for loading the data
     """
     self.m_dumpIO = dumpIO
     self.m_ll_protos = CategoryLoader("networking", self.m_dumpIO)
Ejemplo n.º 13
0
class ProcessData(object):

    def __init__(self, dumpIO, factory):
        """
        :param dumpIO: An instance of squinnie.dio.DumpIO for loading the data
        """
        self.m_dumpIO = dumpIO
        self.m_data = {}
        self.m_ll_proc = CategoryLoader("proc_data", self.m_dumpIO)
        # self.m_ll_children = CategoryLoader("children", self.m_dumpIO)
        self.m_ll_parents = CategoryLoader("parents", self.m_dumpIO)
        self.m_daw_factory = factory
        self.m_socket_connection_cache = SocketCache()
        self.m_shm_cache = ShmCache()

    def getProcData(self):
        """Return general process data."""
        return self.m_ll_proc.getData()

    def getParents(self):
        """Return the parents of each process"""
        return self.m_ll_parents.getData()

    # def getChildren(self):
    #     """Return the children of each process"""
    #     return self.m_ll_children.getData()

    def getProcessCount(self):
        """Returns the number of recorded processes for the scanned host"""
        return len(self.getProcData())

    def getAllPids(self):
        """Returns all process ids found on the scanned host"""
        return self.getProcData().keys()

    def getProcessInfo(self, pid):
        """Get the data for a specific process"""
        return self.getProcData()[pid]

    def processHasUid(self, pid, uid):
        """This method checks whether a process contains the given UID."""
        return uid in self.getProcData()[pid]["Uid"]

    def processHasGid(self, pid, gid):
        """This method checks whether a process contains the given GID."""
        return gid in self.getProcData()[pid]["Gid"]

    def getChildrenForPid(self, searched_pid):
        """Returns all children for a given pid."""
        return [pid for pid, parent in self.getParents().items() if searched_pid == parent]

    def getFileDescriptorsForPid(self, pid):
        """Returns an instance of FileHandlerWrapper for a given process."""
        data = self.getProcessInfo(pid)
        return FdWrapper(pid, data['open_files'], data['Uid'], data['Gid'], self.m_daw_factory)

    def getEndpointsForPipe(self, id):
        """Returns the endpoints for a pipe."""
        self.m_socket_connection_cache.buildIfNecessary(self.getProcData)
        return self.m_socket_connection_cache.getEndpointsForPipe(id)

    def getEndpointsForSocket(self, id):
        """Returns the endpoints for a socket."""
        self.m_socket_connection_cache.buildIfNecessary(self.getProcData)
        return self.m_socket_connection_cache.getEndpointsForSocket(id)

    def getEndpointsForQueue(self, id):
        """Returns the endpoints for a queue."""
        self.m_socket_connection_cache.buildIfNecessary(self.getProcData)
        return self.m_socket_connection_cache.getEndpointsForQueue(id)

    def getOtherPointOfPipe(self, pipe_id, pid):
        """Returns the first endpoint of a pipe which does not have the given pid."""
        self.m_socket_connection_cache.buildIfNecessary(self.getProcData)
        return self.m_socket_connection_cache.getOtherPointOfPipe(pipe_id, pid)

    def getThreadsForPid(self, pid):
        return self.getProcData()[pid]['threads']

    def getRuntimeOfProcess(self, pid):
        return self.m_daw_factory.getSystemDataWrapper().getProcessUptime(self.getProcessInfo(pid)['starttime'])

    def getShmsForPid(self, pid):
        """
        Returns all shm entries a pid has.
        :param pid: The pid to search for.
        :return:
        """
        self.m_shm_cache.buildIfNecessary(self.getProcData,
                                          lambda: self.m_daw_factory.getSystemDataWrapper().getShmData())
        return self.m_shm_cache.getShmsForPid(pid)