def handle_incident(self, icd): logger.debug("storing file") p = icd.path # ToDo: use sha1 or sha256 md5 = md5file(p) # ToDo: use sys.path.join() n = os.path.join(self.download_dir, md5) i = incident("dionaea.download.complete.hash") i.file = n i.url = icd.url if hasattr(icd, 'con'): i.con = icd.con i.md5hash = md5 i.report() try: os.stat(n) i = incident("dionaea.download.complete.again") logger.debug("file %s already existed" % md5) except OSError: logger.debug("saving new file %s to %s" % (md5, n)) os.link(p, n) i = incident("dionaea.download.complete.unique") i.file = n if hasattr(icd, 'con'): i.con = icd.con i.url = icd.url i.md5hash = md5 i.report()
def handle_incident(self, icd): logger.debug("storing file") p = icd.path md5 = md5file(p) n = g_dionaea.config()["downloads"]["dir"] + "/" + md5 i = incident("dionaea.download.complete.hash") i.file = n i.url = icd.url if hasattr(icd, "con"): i.con = icd.con i.md5hash = md5 i.report() try: f = os.stat(n) i = incident("dionaea.download.complete.again") logger.debug("file %s already existed" % md5) except OSError: logger.debug("saving new file %s to %s" % (md5, n)) os.link(p, n) i = incident("dionaea.download.complete.unique") i.file = n if hasattr(icd, "con"): i.con = icd.con i.url = icd.url i.md5hash = md5 i.report()
def handle_incident(self, icd): logger.debug("storing file") p = icd.path md5 = md5file(p) n = g_dionaea.config()['downloads']['dir'] + '/' + md5 i = incident("dionaea.download.complete.hash") i.file = n i.url = icd.url if hasattr(icd, 'con'): i.con = icd.con i.md5hash = md5 i.report() try: f = os.stat(n) i = incident("dionaea.download.complete.again") logger.debug("file %s already existed" % md5) except OSError: logger.debug("saving new file %s to %s" % (md5, n)) os.link(p, n) i = incident("dionaea.download.complete.unique") i.file = n if hasattr(icd, 'con'): i.con = icd.con i.url = icd.url i.md5hash = md5 i.report()
def _handle_ABC(self, msg): handler_name = msg.method.decode("utf-8").upper() # check if Call-ID header exist if not msg.header_exist(b"call-id"): return # Get Call-Id and check if there's already a SipSession call_id = msg.headers.get(b"call-id").value # ToDo: remove? we don't use it # cseq = msg.headers.get(b"cseq").get_raw() # Find SipSession and delete it if call_id not in g_call_ids or g_call_ids[call_id] is None: logger.warn( "{!s} request does not match any existing SIP session".format( handler_name)) icd = incident("dionaea.modules.python.sip.command") icd.con = self msg_to_icd(msg, d=icd) icd.report() self.send( msg.create_response( rfc3261.CALL_TRANSACTION_DOSE_NOT_EXIST).dumps()) return try: g_call_ids[call_id].handle_msg_in(msg) except AuthenticationError: logger.warn( "Authentication failed for {!s} request".format(handler_name))
def handle_incident(self, icd): if icd.origin == 'dionaea.connection.tcp.pending': con = icd.con lhost = con.local.host rhost = con.remote.host # avoid connecting yourself if False and is_local_addr(rhost): logger.warn("avoid self connect") return # throttle incoming SYN's # else port scans will consume *many* sockets # and things go wild&bad now = int(time()) nmt = now % self.throttle_window if self.window[nmt][0] != now: # logger.debug("New Tick") # we got a new tick for i in range(self.throttle_window): # for all other ticks # check the tick is 'up2date' # replace outdated ticks with 0 nmx = (now - i) % self.throttle_window if self.window[nmx][0] != now - i: # logger.debug("Reset window {:d} (was {:d}".format(i,self.window[nmx][1])) self.window[nmx] = [now - i, 0] total = sum([x[1] for x in self.window]) if total > self.throttle_total: logger.warn("throttle total %i %s" % (total, rhost)) icd.nfaction = self.throttle_nfaction return if self.window[nmt][1] > self.throttle_slot: logger.warn("throttle slot %i %s" % (self.window[nmt][1], rhost)) icd.nfaction = self.throttle_nfaction return # finally, start a service on the port m = nfqmirrord('tcp') m.timeouts.listen = self.mirror_server_timeout_listen m.timeouts.idle = self.mirror_client_timeout_idle m.timeouts.sustain = self.mirror_client_timeout_sustain m.bind(lhost, con.local.port) if m.listen() != True: m.close() return logger.info("doing nfq on port %i" % con.local.port) self.window[nmt] = [now, self.window[nmt][1] + 1] i = incident('dionaea.connection.link') i.parent = con i.child = m i.report()
def handle_established(self): self.processors() self.timeouts.sustain = 60 self._in.accounting.limit = 200 * 1024 self._out.accounting.limit = 200 * 1024 if is_local_addr(self.remote.host) == False: self.peer = nfqmirrorc(self) # problem: # the parent connection just got accepted # we are in the established callback for this connection # this connection did not report its dionaea.connection.tcp.accept incident yet # therefore this connection is not 'known' to logsql yet # but we want to associate the incoming mirror connection with the outgoing mirror connection # therefore we claim this is an 'early' link # so logsql can notice this connection has a parent, but the parent is not known yet # once the parent is known, we logsql will update the parent record # for this connection i = incident('dionaea.connection.link.early') i.parent = self i.child = self.peer i.report() else: logger.warning("closing local connection from %s" % self.remote.host) self.close()
def detect_shellshock(connection, data, report_incidents=True): """ Try to find Shellshock attacks, included download commands and URLs. :param connection: The connection object :param data: Data to analyse :param report_incidents: :return: List of urls or None """ from dionaea.core import incident regex = re.compile(b"\(\)\s*\t*\{.*;\s*\}\s*;") if not regex.search(data): return None logger.debug("Shellshock attack found") urls = [] regex = re.compile( b"(wget|curl).+(?P<url>(http|ftp|https)://([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:/~+#-]*[\w@?^=%&/~+#-])?)" ) for m in regex.finditer(data): logger.debug("Found download command with url %s", m.group("url")) urls.append(m.group("url")) if report_incidents: i = incident("dionaea.download.offer") i.con = connection i.url = m.group("url") i.report() return urls
def handle_incident_dionaea_modules_python_virustotal_get_file_report(self, icd): f = open(icd.path, mode='r') j = json.load(f) cookie = icd._userdata vtr = self.cookies[cookie] if j['response_code'] == -2: logger.warn("api throttle") self.cursor.execute("""UPDATE backlogfiles SET status = ? WHERE backlogfile = ?""", (vtr.status, vtr.backlogfile)) self.dbh.commit() elif j['response_code'] == -1: logger.warn("something is wrong with your virustotal api key") elif j['response_code'] == 0: # file unknown # mark for submit if vtr.status == 'new': self.cursor.execute("""UPDATE backlogfiles SET status = 'submit', lastcheck_time = strftime("%s",'now') WHERE backlogfile = ?""", (vtr.backlogfile,)) elif vtr.status == 'query': self.cursor.execute("""UPDATE backlogfiles SET lastcheck_time = strftime("%s",'now') WHERE backlogfile = ?""", (vtr.backlogfile,)) self.dbh.commit() elif j['response_code'] == 1: # file known # self.cursor.execute("""UPDATE backlogfiles SET status = 'comment', lastcheck_time = strftime("%s",'now') WHERE backlogfile = ?""", (vtr.backlogfile,)) self.cursor.execute("""DELETE FROM backlogfiles WHERE backlogfile = ?""", (vtr.backlogfile,) ) self.dbh.commit() logger.debug("report {}".format(j) ) date = j['scan_date'] i = incident("dionaea.modules.python.virustotal.report") i.md5hash = vtr.md5hash i.path = icd.path i.report() else: logger.warn("virustotal reported {}".format(j)) del self.cookies[cookie]
def handle_incident(self, icd): logger.debug("submitting file") for name, to in self.tos.items(): urls = to.get("urls") if urls is None or len(urls) == 0: logger.warn("your configuration lacks urls to submit to %s", name) continue for url in urls: i = incident("dionaea.upload.request") i._url = url # copy all values for this url field_values = to.get("field_values") if field_values is None: field_values = {} for k, v in field_values.items(): i.set(k, v) file_fieldname = to.get("file_fieldname") if file_fieldname is not None: i.set("file://%s" % file_fieldname, icd.file) i.report()
def handle_established(self): self.processors() self.timeouts.sustain = 60 self._in.accounting.limit = 200*1024 self._out.accounting.limit = 200*1024 if is_local_addr(self.remote.host) == False: self.peer=nfqmirrorc(self) # problem: # the parent connection just got accepted # we are in the established callback for this connection # this connection did not report its dionaea.connection.tcp.accept incident yet # therefore this connection is not 'known' to logsql yet # but we want to associate the incoming mirror connection with the outgoing mirror connection # therefore we claim this is an 'early' link # so logsql can notice this connection has a parent, but the parent is not known yet # once the parent is known, we logsql will update the parent record # for this connection i = incident('dionaea.connection.link.early') i.parent = self i.child = self.peer i.report() else: logger.warning("closing local connection from %s" % self.remote.host) self.close()
def processcmd(self, cmd, args): logger.debug("cmd '%s'" % cmd) l = [i.decode() for i in args] i = incident("dionaea.modules.python.ftp.command") i.con = self i.command = cmd i.arguments = l i.report() cmd = cmd.upper() if self.state == self.UNAUTH: if cmd != b'USER': self.reply("not_logged_in") return self.ftp_USER(*l) elif self.state == self.INAUTH: if cmd != b'PASS': self.reply("bad_cmd_seq_pass_after_user") return self.ftp_PASS(*l) else: method = getattr(self, "ftp_" + cmd.decode(), None) if method is not None: msg = method(*l) if isinstance(msg, str): self.error( "Returning messages is deprecated please report so we can fix it" ) self.sendline(msg) else: self.reply("cmd_not_implmntd", command=cmd.decode())
def download(self, con, host, port, filename, url): logger.info("Connecting to %s to download" % host) logger.info(" filename -> %s" % filename) if 'blksize' in self.options: size = self.options['blksize'] if size < MIN_BLKSIZE or size > MAX_BLKSIZE: raise TftpException("Invalid blksize: %d" % size) else: self.options['blksize'] = DEF_BLKSIZE self.filename = filename self.port = port self.con = con self.url = url if con != None: self.bind(con.local.host, 0) self.con.ref() self.connect(host,0) if con != None: i = incident("dionaea.connection.link") i.parent = con i.child = self i.report()
def _handle_ABC(self, msg): handler_name = msg.method.decode("utf-8").upper() # check if Call-ID header exist if not msg.header_exist(b"call-id"): return # Get Call-Id and check if there's already a SipSession call_id = msg.headers.get(b"call-id").value # ToDo: remove? we don't use it # cseq = msg.headers.get(b"cseq").get_raw() # Find SipSession and delete it if call_id not in g_call_ids or g_call_ids[call_id] is None: logger.warn("{!s} request does not match any existing SIP session".format(handler_name)) icd = incident("dionaea.modules.python.sip.command") icd.con = self msg_to_icd(msg,d=icd) icd.report() self.send(msg.create_response(rfc3261.CALL_TRANSACTION_DOSE_NOT_EXIST).dumps()) return try: g_call_ids[call_id].handle_msg_in(msg) except AuthenticationError: logger.warn("Authentication failed for {!s} request".format(handler_name))
def handle_POST(self): """ Handle the POST method. Send the head and the file. But ignore the POST params. Use the bistreams for a better analysis. """ if self.fp_tmp is not None: self.fp_tmp.seek(0) # at least this information are needed for # cgi.FieldStorage() to parse the content tmp_environ = { 'REQUEST_METHOD': 'POST', 'CONTENT_LENGTH': self.content_length, 'CONTENT_TYPE': self.content_type } if sys.version_info[1] >= 8: self.request_form = cgi.FieldStorage( fp=self.fp_tmp, environ=tmp_environ, max_num_fields=self.get_max_num_fields) else: logger.warning( "max_num_fields is only supported with Python >= 3.8") self.request_form = cgi.FieldStorage(fp=self.fp_tmp, environ=tmp_environ) for field_name in self.request_form.keys(): # dump only files if self.request_form[field_name].filename is None: continue fp_post = self.request_form[field_name].file data = fp_post.read(4096) # don't handle empty files if len(data) == 0: continue fp_tmp = tempfile.NamedTemporaryFile( delete=False, dir=self.download_dir, prefix='http-', suffix=self.download_suffix) while data != b'': fp_tmp.write(data) data = fp_post.read(4096) icd = incident("dionaea.download.complete") icd.path = fp_tmp.name icd.con = self # We need the url for logging icd.url = "" fp_tmp.close() icd.report() os.unlink(fp_tmp.name) os.unlink(self.fp_tmp.name) x = self.send_head() if x: self.copyfile(x)
def download(self, con, host, port, filename, url): logger.info("Connecting to %s to download" % host) logger.info(" filename -> %s" % filename) if 'blksize' in self.options: size = self.options['blksize'] if size < MIN_BLKSIZE or size > MAX_BLKSIZE: raise TftpException("Invalid blksize: %d" % size) else: self.options['blksize'] = DEF_BLKSIZE self.filename = filename self.port = port self.con = con self.url = url if con != None: self.bind(con.local.host, 0) self.con.ref() self.connect(host, 0) if con != None: i = incident("dionaea.connection.link") i.parent = con i.child = self i.report()
def handle_io_in(self, data): if self.state == self.IDLE: p = packets.PPTP_StartControlConnection_Request(data) p.show() if p.Length == 0: logger.warn("Bad PPTP Packet, Length = 0") return len(data) i = incident("dionaea.modules.python.pptp.connect") i.con = self logger.debug("pptp remote hostname: %s", p.HostName) i.firmware_revision = p.FirmwareRevision i.max_channels = p.MaxChannels i.protocol_version = p.ProtocolVersion i.remote_hostname = p.HostName i.vendor_name = p.VendorName i.report() self.state = self.ESTABLISHED r = packets.PPTP_StartControlConnection_Reply() r.FirmwareRevision = self.firmware_revision r.HostName = self.hostname r.VendorName = self.vendor_name r.show() self.send(r.build()) return len(data) elif self.state == self.ESTABLISHED: p = packets.BaseControllMessage(data) if p.MessageType == 0x01: return self._handle_controll_message(p.ControlMessageType, data) logger.warning("Wrong message type %d", p.MessageType) return len(data) return len(data)
def handle_incident_dionaea_modules_python_mwserv_result(self, icd): fh = open(icd.path, mode="rb") c = fh.read() logger.info("mwserv result: {0}".format(c)) cookie = icd._userdata mr = self.cookies[cookie] # does backend want us to upload? if b'UNKNOWN' in c: i = incident("dionaea.upload.request") i._url = self.backendurl + 'nepenthes/submit' i.sha512 = mr.sha512h i.maintainer = self.maintainer i.guid = self.guid i.secret = self.secret i.set('file://data', mr.filepath) i.saddr = mr.saddr i.sport = mr.sport i.daddr = mr.daddr i.dport = mr.dport i.url = mr.download_url i._callback = "dionaea.modules.python.mwserv.uploadresult" i._userdata = cookie i.report() else: del self.cookies[cookie]
def connection_insert(self, icd, connection_type): con = icd.con if (con.protocol != 'pcap'): cookies = str(uuid.uuid4()) logger.info( "MyCERT Sensor: connection_type: %s, con_protocol: %s" % (connection_type, con.protocol)) i = incident('dionaea.upload.request') i._url = self.connection_url i.sensorid = self.sensorid # i.connection_type = connection_type i.protocol = con.protocol i.transport = con.transport i.hostname = con.remote.hostname i.src_ip = con.remote.host i.src_port = str(con.remote.port) i.dst_ip = con.local.host i.dst_port = str(con.local.port) i.timestamp = str( time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())) i.hash = cookies i._callback = "dionaea.modules.python.mycertsensor.connection_result" i._userdata = cookies self.cookies[cookies] = con self.connection[con] = cookies i.report()
def handle_incident_dionaea_download_complete_unique(self, icd): cookie = str(uuid.uuid4()) i = incident("dionaea.upload.request") i._url = self.backendurl + 'nepenthes/submit' i.sha512 = sha512file(icd.file) i.maintainer = self.maintainer i.guid = self.guid i.secret = self.secret mr = mwserv_report(i.sha512, icd.file) if hasattr(icd, 'con'): i.saddr = icd.con.remote.host i.sport = str(icd.con.remote.port) i.daddr = icd.con.local.host i.dport = str(icd.con.local.port) mr.saddr, mr.sport, mr.daddr, mr.dport = i.saddr, i.sport, i.daddr, i.dport if hasattr(icd, 'url'): i.url = icd.url mr.download_url = icd.url i._callback = "dionaea.modules.python.mwserv.result" i._userdata = cookie self.cookies[cookie] = mr i.report()
def handle_io_in(self, data): fmt = "IIB20s40sB30s30sBBBhHi" if len(data) != calcsize(fmt): return 0 values = unpack(fmt, data) names = [ "magic", "id", "type", "genre", "detail", "dist", "link", "tos", "fw", "nat", "real", "score", "mflags", "uptime" ] icd = incident(origin='dionaea.modules.python.p0f') for i in range(len(values)): s = values[i] if type(s) == bytes: if s.find(b'\x00'): s = s[:s.find(b'\x00')] try: s = s.decode("ascii") except UnicodeDecodeError: logger.warning("Unable to decode p0f information %s=%r", i, s, exc_info=True) icd.set(names[i], s) elif type(s) == int: icd.set(names[i], str(s)) icd.set('con', self.con) icd.report() self.close() return len(data)
def processcmd(self, cmd, args): logger.debug("cmd '%s'" % cmd) l = [i.decode() for i in args] i = incident("dionaea.modules.python.ftp.command") i.con = self i.command = cmd i.arguments = l i.report() cmd = cmd.upper() if self.state == self.UNAUTH: if cmd != b'USER': self.reply("not_logged_in") return self.ftp_USER(*l) elif self.state == self.INAUTH: if cmd != b'PASS': self.reply("bad_cmd_seq_pass_after_user") return self.ftp_PASS(*l) else: method = getattr(self, "ftp_" + cmd.decode(), None) if method is not None: msg = method(*l) if isinstance(msg, str): self.error("Returning messages is deprecated please report so we can fix it") self.sendline(msg) else: self.reply("cmd_not_implmntd", command=cmd.decode())
def _heartbeat(self, events, data): logger.info("mwserv _heartbeat") i = incident("dionaea.upload.request") i._url = self.backendurl + 'heartbeat' i.maintainer = self.maintainer i.guid = self.guid i.secret = self.secret i.software = self.software i._callback = "dionaea.modules.python.mwserv.heartbeatresult" i.report()
def get_file_report(self, backlogfile, md5_hash, path, status): cookie = str(uuid.uuid4()) self.cookies[cookie] = vtreport(backlogfile, md5_hash, path, status) i = incident("dionaea.upload.request") i._url = "https://www.virustotal.com/vtapi/v2/file/report" i.resource = md5_hash i.apikey = self.apikey i._callback = "dionaea.modules.python.virustotal.get_file_report" i._userdata = cookie i.report()
def handle_established(self): logger.debug("{!s} handle_established".format(self)) self.timeouts.idle = 10 self.timeouts.sustain = 120 self.processors() # fake a connection entry i = incident("dionaea.connection.udp.connect") i.con = self i.report()
def scan_file(self, backlogfile, md5_hash, path, status): cookie = str(uuid.uuid4()) self.cookies[cookie] = vtreport(backlogfile, md5_hash, path, status) i = incident("dionaea.upload.request") i._url = "https://www.virustotal.com/vtapi/v2/file/scan" i.apikey = self.apikey i.set('file://file', path) i._callback = "dionaea.modules.python.virustotal_scan_file" i._userdata = cookie i.report()
def handle_established(self): logger.debug("{:s} handle_established".format(self)) self.timeouts.idle = 10 self.timeouts.sustain = 120 self.processors() # fake a connection entry i = incident("dionaea.connection.udp.connect") i.con = self i.report()
def make_comment(self, backlogfile, md5_hash, path, status): cookie = str(uuid.uuid4()) self.cookies[cookie] = vtreport(backlogfile, md5_hash, path, status) i = incident("dionaea.upload.request") i._url = "https://www.virustotal.com/vtapi/v2/comments/put" i.apikey = self.apikey i.resource = md5_hash i.comment = "This sample was captured in the wild and uploaded by the dionaea honeypot.\n#honeypot #malware #networkworm" i._callback = "dionaea.modules.python.virustotal_make_comment" i._userdata = cookie i.report()
def handle_OPTIONS(self, msg): logger.debug("{!s} handle_OPTIONS".format(self)) icd = incident("dionaea.modules.python.sip.command") icd.con = self msg_to_icd(msg,d=icd) icd.report() res = msg.create_response(rfc3261.OK) res.headers.append(rfc3261.Header(name="Accept", value="application/sdp")) res.headers.append(rfc3261.Header(name="Accept-Language", value="en")) self.send(res.dumps())
def handle_unknown(self, msg): logger.debug("{!s} unknown".format(self)) logger.warn("Unknown SIP header: {}".format(repr(msg.method)[:128])) icd = incident("dionaea.modules.python.sip.command") icd.con = self msg_to_icd(msg, d=icd) icd.report() res = msg.create_response(rfc3261.NOT_IMPLEMENTED) res.dumps() self.send(res.dumps())
def handle_incident_dionaea_download_complete_hash(self, icd): logger.info("MyCERT Sensor: handle_incident_dionaea_download_complete_hash") i = incident("dionaea.upload.request") i._url = self.artifact_url.format(id=self.sensorid, connection_id=str(self.connection[icd.con])) i.type = "fileupload" i.md5 = icd.md5hash i.metadata = json.dumps({ 'url': icd.url, 'md5': icd.md5hash, 'timestamp': str(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())) }) i.set('file://' + self.mwsconfig['file_fieldname'], icd.file) i.report()
def submitArtifact(self, connection_id, jenis, metadata): url = self.artifact_url.format(id=self.sensorid, connection_id=connection_id) logger.info("MyCERT Sensor: Submit Artifact url=%s, jenis=%s,connection_id=%s" % (url, jenis, connection_id)) i = incident('dionaea.upload.request') i._url = url i.type = jenis i.metadata = metadata i._callback = "dionaea.modules.python.mycertsensor.artifact_result" i._userdata = json.dumps({ 'connection_id': connection_id, 'jenis': jenis, 'metadata': json.loads(metadata) }) i.report()
def makeport(self): self.datalistener = FTPData(ftp=self) try: portrange = g_dionaea.config()["modules"]["python"]["ftp"]["active-ports"] (minport, maxport) = portrange.split("-") minport = int(minport) maxport = int(maxport) except: minport = 62001 maxport = 63000 try: # for NAT setups host = g_dionaea.config()["modules"]["python"]["ftp"]["active-host"] if host == "0.0.0.0": host = self.ctrl.local.host logger.info("datalisten host %s", host) else: import socket host = socket.gethostbyname(host) logger.info("resolved host %s", host) except: host = self.ctrl.local.host logger.info("except datalisten host %s", self.ctrl.local.host) # NAT, use a port range which is forwarded to your honeypot ports = list( filter( lambda port: ((port >> 4) & 0xf) != 0, range(minport, maxport) ) ) random.shuffle(ports) port = None for port in ports: self.datalistener.bind(self.ctrl.local.host, port) if self.datalistener.listen() == True: port = self.datalistener.local.port i = incident("dionaea.connection.link") i.parent = self.ctrl i.child = self.datalistener i.report() break hbytes = host.split(".") pbytes = [repr(port // 256), repr(port % 256)] bytes = hbytes + pbytes port = ",".join(bytes) logger.debug("PORT CMD %s", port) return port
def handle_disconnect(self): logger.debug("received %i bytes" % (self._in.accounting.bytes)) if hasattr(self, 'fileobj') and self.fileobj != None: # print(type(self.file)) # print(self.file) self.fileobj.close() icd = incident("dionaea.download.complete") icd.path = self.fileobj.name icd.con = self.ftp.con icd.url = self.ftp.url icd.report() self.fileobj.unlink(self.fileobj.name) self.ftp.dataconn = None self.ftp.datadone() return False
def handle_disconnect(self): logger.debug("received %i bytes", self._in.accounting.bytes) if hasattr(self, "fileobj")and self.fileobj is not None: # print(type(self.file)) # print(self.file) self.fileobj.close() icd = incident("dionaea.download.complete") icd.path = self.fileobj.name icd.con = self.ftp.con icd.url = self.ftp.url icd.report() self.fileobj.unlink(self.fileobj.name) self.ftp.dataconn = None self.ftp.datadone() return False
def makeport(self): self.datalistener = ftpdata(ftp=self) try: portrange = g_dionaea.config( )['modules']['python']['ftp']['active-ports'] (minport, maxport) = portrange.split('-') minport = int(minport) maxport = int(maxport) except: minport = 62001 maxport = 63000 try: # for NAT setups host = g_dionaea.config( )['modules']['python']['ftp']['active-host'] if host == '0.0.0.0': host = self.ctrl.local.host logger.info("datalisten host %s" % host) else: import socket host = socket.gethostbyname(host) logger.info("resolved host %s" % host) except: host = self.ctrl.local.host logger.info("except datalisten host %s" % self.ctrl.local.host) ports = list( filter(lambda port: ((port >> 4) & 0xf) != 0, range(minport, maxport)) ) # NAT, use a port range which is forwarded to your honeypot random.shuffle(ports) port = None for port in ports: self.datalistener.bind(self.ctrl.local.host, port) if self.datalistener.listen() == True: port = self.datalistener.local.port i = incident("dionaea.connection.link") i.parent = self.ctrl i.child = self.datalistener i.report() break hbytes = host.split('.') pbytes = [repr(port // 256), repr(port % 256)] bytes = hbytes + pbytes port = ','.join(bytes) logger.debug("PORT CMD %s" % (port)) return port
def ftp_PASS(self, password): if not password: self.reply("syntax_error_pass_requires_arg") return i = incident("dionaea.modules.python.ftp.login") i.con = self i.username = self.user i.password = password i.report() self.state = self.AUTHED if self.user == "anonymous": self.reply("guest_logged_in_proceed") else: self.reply("usr_logged_in_proceed")
def handle_POST(self): """ Handle the POST method. Send the head and the file. But ignore the POST params. Use the bistreams for a better analysis. """ if self.fp_tmp is None: self.fp_tmp.seek(0) form = cgi.FieldStorage(fp=self.fp_tmp, environ=self.env) for field_name in form.keys(): # dump only files if form[field_name].filename is None: continue fp_post = form[field_name].file data = fp_post.read(4096) # don't handle empty files if len(data) == 0: continue fp_tmp = tempfile.NamedTemporaryFile( delete=False, dir=self.download_dir, prefix='http-', suffix=self.download_suffix ) while data != b'': fp_tmp.write(data) data = fp_post.read(4096) icd = incident("dionaea.download.complete") icd.path = fp_tmp.name icd.con = self # We need the url for logging icd.url = "" fp_tmp.close() icd.report() os.unlink(fp_tmp.name) os.unlink(self.fp_tmp.name) x = self.send_head() if x: self.copyfile(x)
def handle_POST(self): """ Handle the POST method. Send the head and the file. But ignore the POST params. Use the bistreams for a better analysis. """ if self.fp_tmp is not None: self.fp_tmp.seek(0) form = cgi.FieldStorage(fp=self.fp_tmp, environ=self.env) for field_name in form.keys(): # dump only files if form[field_name].filename is None: continue fp_post = form[field_name].file data = fp_post.read(4096) # don't handle empty files if len(data) == 0: continue fp_tmp = tempfile.NamedTemporaryFile( delete=False, dir=self.download_dir, prefix='http-', suffix=self.download_suffix ) while data != b'': fp_tmp.write(data) data = fp_post.read(4096) icd = incident("dionaea.download.complete") icd.path = fp_tmp.name icd.con = self # We need the url for logging icd.url = "" fp_tmp.close() icd.report() os.unlink(fp_tmp.name) os.unlink(self.fp_tmp.name) x = self.send_head() if x: self.copyfile(x)
def handle_msg_in(self, msg): self._timers["idle"].reset() self._msg_stack.append(("in", msg)) icd = incident("dionaea.modules.python.sip.command") icd.con = self msg_to_icd(msg, d=icd) icd.report() handler_name = msg.method.decode("utf-8").upper() try: func = getattr(self, "handle_" + handler_name, None) except: func = None if func is not None and callable(func) == True: func(msg)
def handle_msg_in(self, msg): self._timers["idle"].reset() self._msg_stack.append(("in", msg)) icd = incident("dionaea.modules.python.sip.command") icd.con = self msg_to_icd(msg,d=icd) icd.report() handler_name = msg.method.decode("utf-8").upper() try: func = getattr(self, "handle_" + handler_name, None) except: func = None if func is not None and callable(func) == True: func(msg)
def __init__(self, proto, call_id, session, invite_message): logger.debug("{!s} __init__".format(self)) logger.debug("SipCall {} session {} ".format(self, session)) connection.__init__(self, proto) # Store incoming information of the remote host self.__session = session self.__state = SipCall.SESSION_SETUP self.__msg = invite_message # list of messages self._msg_stack = [] self.__call_id = invite_message.headers.get(b"call-id").value self._call_id = call_id self._rtp_streams = {} self.local.host = self.__session.local.host self.local.port = self.__session.local.port self.remote.host = self.__session.remote.host self.remote.port = self.__session.remote.port user = self.__msg.headers.get(b"to").get_raw().uri.user self._user = g_sipconfig.get_user_by_username( self.__session.personality, user ) # fake a connection entry i = incident("dionaea.connection.udp.connect") i.con = self i.report() global _SipCall_sustain_timeout # Global timers self._timers = { "idle": pyev.Timer(60.0, 60.0, g_default_loop, self.__handle_timeout_idle), "invite_handler": pyev.Timer(5.0, 0.0, g_default_loop, self.__handle_invite), } self._timers["idle"].start()
def handle_INVITE(self, msg): logger.debug("{!s} handle_INVITE".format(self)) global g_sipconfig global g_call_ids # Read Call-ID field and create new SipCall instance on first INVITE # request received (remote host might send more than one because of time # outs or because he wants to flood the honeypot) #logger.debug("Currently active sessions: {}".format(self._callids)) if not msg.header_exist(b"call-id"): return call_id = msg.headers.get(b"call-id").value if call_id in g_call_ids and g_call_ids[call_id] == None: logger.warn("SIP session with Call-ID {} already exists".format(call_id[:128])) # ToDo: error return # Establish a new SIP Call new_call = SipCall( self.transport, call_id, self, msg ) # Store session object in sessions dictionary g_call_ids[call_id] = new_call i = incident("dionaea.connection.link") i.parent = self i.child = new_call i.report() try: r = new_call.handle_msg_in(msg) except AuthenticationError: logger.warn("Authentication failed, not creating SIP session") new_call.close() del new_call
def cmd_TFTP(self, args): logger.debug("TFTP %s" % (args) ) if len(args) != 4: logger.debug("invalid number of args") return "foo","error, invalid number of args" if args[0] == '-i' and args[2].lower() == 'get': host = args[1] file = args[3] # logger.debug("TFTP %s %s" % (host, file)) i = incident("dionaea.download.offer") url = 'tftp://' + host + '/' + file i.url = url if isinstance(self, connection): i.con = self elif hasattr(self, 'con') and isinstance(self.con, connection): i.con = self.con i.report() return "downloading",None return None,None
def handle_incident(self, icd): logger.debug("do shell") con = icd.con c = remoteshell() i = incident("dionaea.connection.link") i.parent = icd.con i.child = c if icd.origin == "dionaea.service.shell.listen": if c.bind(con.local.host,icd.get('port')) == True and c.listen() == True: i.report() else: c.close() # con.unref() elif icd.origin == "dionaea.service.shell.connect": c.bind(con.local.host,0) c.connect(icd.get('host'), icd.get('port')) i.report() else: c.close()
def handle_incident_dionaea_download_complete_unique(self, icd): cookie = str(uuid.uuid4()) i = incident("dionaea.upload.request") i._url = self.backendurl i.sha512 = sha512file(icd.file) i.md5 = md5file(icd.file) i.email = self.email i.user = self.user i.set('pass', self.passwd) mr = submithttp_report(i.sha512, i.md5, icd.file) if hasattr(icd, 'con'): i.source_host = str( struct.unpack('!I', socket.inet_aton(icd.con.remote.host))[0] ) i.source_port = str(icd.con.remote.port) i.target_host = str( struct.unpack('!I', socket.inet_aton(icd.con.local.host))[0] ) i.target_port = str(icd.con.local.port) mr.saddr, mr.sport, mr.daddr, mr.dport = i.source_host, i.source_port, i.target_host, i.target_port if hasattr(icd, 'url'): i.url = icd.url i.trigger = icd.url try: i.filename = urlparse(icd.url).path.split('/')[-1] mr.filename = i.filename except: pass mr.download_url = icd.url i.filetype = filetype(icd.file) mr.filetype = i.filetype i._callback = "dionaea.modules.python.submithttp.result" i._userdata = cookie self.cookies[cookie] = mr i.report()
def handle_io_in(self, data): fmt = "IIB20s40sB30s30sBBBhHi" if len(data) != calcsize(fmt): return 0 values = unpack(fmt, data) names=["magic","id","type","genre","detail","dist","link", "tos","fw","nat","real","score","mflags","uptime"] icd = incident(origin='dionaea.modules.python.p0f') for i in range(len(values)): s = values[i] if type(s) == bytes: if s.find(b'\x00'): s = s[:s.find(b'\x00')] icd.set(names[i], s) elif type(s) == int: icd.set(names[i], str(s)) icd.set('con',self.con) icd.report() self.close() return len(data)
def handle_incident_dionaea_download_complete(self, icd): url_levels = self.connection_url_levels.get(icd.con) if not isinstance(url_levels, dict): url_levels = {} # Store dict pointer in list, so others can use it self.connection_url_levels[icd.con] = url_levels next_level = url_levels.get(icd.url, 0) + 1 if next_level > 1: # ToDo: use config value return fp = open(icd.path, "rb") # ToDo: check size data = fp.read() fp.close() urls = None # use the url list of the first handler that matches for handler in self.handlers: urls = handler.run(data) if urls is not None: break if urls is None: return for url in set(urls): if url in url_levels: # don't download a file multiple times continue if len(url_levels) > self.max_subdownloads: logger.warning("Max number of subdownloads reached") break url_levels[url] = next_level i = incident("dionaea.download.offer") i.con = icd.con i.url = url i.report()
def _report_raw_data(self, data): """ Create temporary file and report incident :param bytes data: File data """ fp_tmp = tempfile.NamedTemporaryFile( delete=False, dir=self.download_dir, prefix='mysql-', suffix=self.download_suffix ) fp_tmp.write(data) icd = incident("dionaea.download.complete") icd.path = fp_tmp.name icd.con = self # We need the url for logging icd.url = "" fp_tmp.close() icd.report() os.unlink(fp_tmp.name)