示例#1
0
    def _packet_handler(self, pkt):
        if pkt.haslayer(DHCP):
            # self.logger.error(pkt[DHCP].command())
            params = {}
            # dhcp request
            # options = dict(pkt[DHCP].options)
            # if options.get('message-type', 0) == 3 and options.get('requested_addr', None):
            for entry in pkt[DHCP].options:
                if entry[0] == "message-type":
                    params['message-type'] = entry[1]
                elif entry[0] == "vendor_class_id":
                    # self.logger.info("%s %s", entry[0], entry[1])
                    params['dhcp_vendor'] = entry[1]
                elif entry[0] == 'requested_addr':
                    params['ip'] = entry[1]
                elif entry[0] == 'hostname':
                    params['hostname'] = entry[1]
                elif entry[0] == "client_id":
                    # client_id value is hardware type (0x01) and mac address
                    params['mac'] = ":".join(
                        hexstr(entry[1], onlyhex=True).split(" ")[-6:])
                elif entry[0] == 'param_req_list':
                    # DHCP fingerprint in fingerbank format
                    params['dhcp_fingerprint'] = ",".join([
                        str(int(num, 16))
                        for num in hexstr(entry[1], onlyhex=True).split(" ")
                    ])

            if params.get('message-type', 0) == 3 and params.get('ip', None):
                insert_or_update_fingerprint(self.conn, self.logger, **params)
示例#2
0
    def _handle_dhcp(self, pkt):
        # self.logger.error(pkt[DHCP].command())
        params = {}
        params['mac'] = str(":".join(hexstr(pkt[BOOTP].chaddr, onlyhex=True).split(" ")[:6])).lower()

        for entry in pkt[DHCP].options:
            if entry[0] == "message-type":
                params['message-type'] = entry[1]
            elif entry[0] == "vendor_class_id":
                # self.logger.info("%s %s", entry[0], entry[1])
                params['dhcp_vendor'] = entry[1]
            elif entry[0] == 'requested_addr':
                params['ip'] = entry[1]
            elif entry[0] == 'hostname':
                params['hostname'] = entry[1]
            elif entry[0] == 'param_req_list':
                # DHCP fingerprint in fingerbank format
                params['dhcp_fingerprint'] = ",".join([str(int(num, 16)) for num in hexstr(entry[1], onlyhex=True).split(" ")])

        if params.get('message-type', 0) == 3 and check_preconditions(params.get('ip', None), params.get('mac', None)):
            try:
                insert_or_update_fingerprint(self.conn, **params)
                self.logger.debug("registered dhcp: ip: {}, mac: {}".format(params.get('ip', None), params.get('mac', None)))
            except TypeError as te:
                self.logger.error(insert_or_update_fingerprint.__name__ + " needs keyword-only argument ip")
            except sqlite3.Error as sqle:
                self.logger.exception(sqle)
            except ValueError as ve:
                self.logger.exception(ve)
示例#3
0
    def run(self):
        try:
            self.conn = sqlite3.connect(self.dbfile)
            with self.conn:
                c = self.conn.cursor()
                while True:
                    try:
                        c.execute(self._QUERY)
                        devices = list(sum(c.fetchall(), ()))

                        if devices:
                            ans, unans = arping(devices, iface=None, verbose=0)
                            for device in ans:
                                if check_preconditions(device[1][ARP].psrc,
                                                       device[1][ARP].hwsrc):
                                    insert_or_update_fingerprint(
                                        self.conn,
                                        ip=device[1][ARP].psrc,
                                        mac=device[1][ARP].hwsrc)

                        self.logger.info("checked no mode devices: " +
                                         str(devices))

                        time.sleep(self._SLEEP)
                    except sqlite3.Error as sqle:
                        self.logger.error("a database error occurred")
                        self.logger.exception(sqle)
        except sqlite3.Error as sqle:
            self.logger.error(
                "Failed to connect to sqlite database at path %s" %
                (self.dbfile, ))
            self.logger.exception(sqle)
            raise DaemonError()
示例#4
0
    def _handle_ssdp(self, pkt):
        parser = HttpParser()
        params = {}
        user_agents = []
        id = None

        if not all(pkt.haslayer(layer) for layer in [Ether, IP, UDP]):
            self.logger.debug("packet does not contain all required layers")
            self.logger.debug(pkt.command())
            return

        params['mac'] = pkt[Ether].src
        params['ip'] = pkt[IP].src

        if check_preconditions(params.get('ip', None), params.get('mac', None)):
            try:
                id = insert_or_update_fingerprint(self.conn, **params)
                self.logger.debug("registered ssdp: ip: {}, mac: {}".format(params.get('ip', None), params.get('mac', None)))
            except TypeError as te:
                self.logger.error(insert_or_update_fingerprint.__name__ + " needs keyword-only argument ip")
            except sqlite3.Error as sqle:
                self.logger.exception(sqle)

        if id is None:
            return

        try:
            if parser.execute(pkt[UDP].payload.load, len(pkt[UDP].payload.load)) != len(pkt[UDP].payload.load):
                self.logger.warning("error while parsing HTTP payload of ssdp packet")
                return
        except AttributeError:
            self.logger.warning("received UDP packet without payload")

        headers = parser.get_headers()
        if "user-agent" in headers:
            # e.g. chrome appends user agent to ssdp:discover
            user_agents.append((headers['user-agent'], False))

        if "server" in headers:
            user_agents.append((headers['server'], False))

        if "location" in headers:
            req = url.Request(headers['location'])
            host = ""
            ip = None
            try:
                ip = socket.gethostbyname_ex(req.get_host().split(":")[0])
            except ValueError:
                self.logger.warning("malformed location value")
            except socket.error:
                self.logger.warning("Unable to get ip of host")
            else:
                # only allow locations inside private networks
                if IPAddress(ip[2][0]).is_private():
                    try:
                        xml_content = url.urlopen(req).read()
                        spec = xmltodict.parse(xml_content)
                        user_agents.append((spec['root']['device']['friendlyName'], True))
                    except url.URLError as urle:
                        self.logger.warning("Unable to get content of url " + headers['location'])
                        self.logger.warning(urle)
                    except xml.parsers.expat.ExpatError:
                        self.logger.error("Unable to parse upnp xml from url " + headers['location'])
                    except KeyError:
                        self.logger.error("xml does not contain required friendlyName from url " + headers['location'])
                    except BadStatusLine:
                        self.logger.warning("Server responded with bad status line for url " + headers['location'])
                    except socket.error as e:
                        if e.errno != errno.ECONNRESET:
                            raise
                        self.logger.warning("Connection reset by peer connecting to url " + headers['location'])
                    else:
                        try:
                            user_agents.append((spec['root']['device']['modelDescription'], True))
                        except KeyError:
                            # modelDescription is not mandatory, only recommended
                            pass

        for agent, model in user_agents:
            insert_useragent(self.conn, agent, id, model)