def __init__(self): self.sessions = {} self.ttylogs = {} # FIXME figure out what needs to be done here regarding self.re_sessionlog = re.compile( r'.*HoneyPotSSHTransport,([0-9]+),[:a-f0-9.]+$') # cowrie.session.connect is special since it kicks off new logging session, # and is not handled here self.events = { 'cowrie.login.success': self.handleLoginSucceeded, 'cowrie.login.failed': self.handleLoginFailed, 'cowrie.log.open': self.handleTTYLogOpened, 'cowrie.command.success': self.handleCommand, 'cowrie.command.failed': self.handleUnknownCommand, 'cowrie.session.file_download': self.handleFileDownload, 'cowrie.command.input': self.handleInput, 'cowrie.client.version': self.handleClientVersion, 'cowrie.client.size': self.handleTerminalSize, 'cowrie.session.closed': self._connectionLost, 'cowrie.log.closed': self.handleTTYLogClosed, } self.reported_ssh_port = None if CONFIG.has_option('honeypot', 'reported_ssh_port'): self.reported_ssh_port = CONFIG.getint('honeypot', 'reported_ssh_port') self.report_public_ip = False if CONFIG.has_option('honeypot', 'report_public_ip'): if CONFIG.getboolean('honeypot', 'report_public_ip') == True: self.report_public_ip = True import urllib self.public_ip = urllib.urlopen('http://myip.threatstream.com').readline() self.start()
def start(self): """ """ log.msg("WARNING: Beta version of new hpfeeds enabled. This will become hpfeeds in a future release.") if CONFIG.has_option('output_hpfeeds', 'channel'): self.channel = CONFIG.get('output_hpfeeds', 'channel') if CONFIG.has_option('output_hpfeeds', 'endpoint'): endpoint = CONFIG.get('output_hpfeeds', 'endpoint') else: server = CONFIG.get('output_hpfeeds', 'server') port = CONFIG.getint('output_hpfeeds', 'port') if CONFIG.has_option('output_hpfeeds', 'tlscert'): with open(CONFIG.get('output_hpfeeds', 'tlscert')) as fp: authority = ssl.Certificate.loadPEM(fp.read()) options = ssl.optionsForClientTLS(server, authority) endpoint = endpoints.SSL4ClientEndpoint(reactor, server, port, options) else: endpoint = endpoints.HostnameEndpoint(reactor, server, port) ident = CONFIG.get('output_hpfeeds', 'identifier') secret = CONFIG.get('output_hpfeeds', 'secret') self.meta = {} self.client = ClientSessionService(endpoint, ident, secret) self.client.startService()
def checkUserPass(self, theusername, thepassword, ip): # UserDB is the default auth_class authname = auth.UserDB # Is the auth_class defined in the config file? if CONFIG.has_option('honeypot', 'auth_class'): authclass = CONFIG.get('honeypot', 'auth_class') authmodule = "cowrie.core.auth" # Check if authclass exists in this module if hasattr(modules[authmodule], authclass): authname = getattr(modules[authmodule], authclass) else: log.msg('auth_class: %s not found in %s' % (authclass, authmodule)) theauth = authname() if theauth.checklogin(theusername, thepassword, ip): log.msg(eventid='cowrie.login.success', format='login attempt [%(username)s/%(password)s] succeeded', username=theusername, password=thepassword) return True else: log.msg(eventid='cowrie.login.failed', format='login attempt [%(username)s/%(password)s] failed', username=theusername, password=thepassword) return False
def connectionMade(self): pt = self.getProtoTransport() self.realClientIP = pt.transport.getPeer().host self.realClientPort = pt.transport.getPeer().port self.logintime = time.time() log.msg(eventid='cowrie.session.params', arch=self.user.server.arch) try: timeout = CONFIG.getint('honeypot', 'interactive_timeout') except Exception: timeout = 180 self.setTimeout(timeout) # Source IP of client in user visible reports (can be fake or real) try: self.clientIP = CONFIG.get('honeypot', 'fake_addr') except Exception: self.clientIP = self.realClientIP # Source IP of server in user visible reports (can be fake or real) if CONFIG.has_option('honeypot', 'internet_facing_ip'): self.kippoIP = CONFIG.get('honeypot', 'internet_facing_ip') else: try: s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.connect(("8.8.8.8", 80)) self.kippoIP = s.getsockname()[0] except Exception: self.kippoIP = '192.168.0.1' finally: s.close()
def checkUserPass(self, theusername, thepassword, ip): # UserDB is the default auth_class authname = auth.UserDB # Is the auth_class defined in the config file? if CONFIG.has_option('honeypot', 'auth_class'): authclass = CONFIG.get('honeypot', 'auth_class') authmodule = "cowrie.core.auth" # Check if authclass exists in this module if hasattr(modules[authmodule], authclass): authname = getattr(modules[authmodule], authclass) else: log.msg('auth_class: %s not found in %s' % (authclass, authmodule)) theauth = authname() if theauth.checklogin(theusername, thepassword, ip): log.msg( eventid='cowrie.login.success', format='login attempt [%(username)s/%(password)s] succeeded', username=theusername, password=thepassword) return True else: log.msg(eventid='cowrie.login.failed', format='login attempt [%(username)s/%(password)s] failed', username=theusername, password=thepassword) return False
def download(self, url, fakeoutfile, outputfile, *args, **kwargs): try: parsed = compat.urllib_parse.urlparse(url) scheme = parsed.scheme host = parsed.hostname.decode('utf8') port = parsed.port or (443 if scheme == 'https' else 80) if scheme != b'http' and scheme != b'https': raise NotImplementedError except Exception: self.errorWrite('curl: (1) Protocol "{}" not supported or disabled in libcurl\n'.format(scheme)) self.exit() return None factory = HTTPProgressDownloader( self, fakeoutfile, url, outputfile, *args, **kwargs) out_addr = None if CONFIG.has_option('honeypot', 'out_addr'): out_addr = (CONFIG.get('honeypot', 'out_addr'), 0) if scheme == 'https': contextFactory = ssl.ClientContextFactory() contextFactory.method = SSL.SSLv23_METHOD reactor.connectSSL(host, port, factory, contextFactory, bindAddress=out_addr) else: # Can only be http self.connection = reactor.connectTCP( host, port, factory, bindAddress=out_addr) return factory.deferred
def makeTftpRetrieval(self): """ """ progresshook = Progress(self).progresshook if CONFIG.has_option('honeypot', 'download_limit_size'): self.limit_size = CONFIG.getint('honeypot', 'download_limit_size') self.artifactFile = Artifact(self.file_to_get) tclient = None url = '' try: tclient = tftpy.TftpClient(self.hostname, int(self.port)) # tftpy can't handle unicode string as filename # so we have to convert unicode type to str type tclient.download(str(self.file_to_get), self.artifactFile, progresshook) url = 'tftp://%s/%s' % (self.hostname, self.file_to_get.strip('/')) self.file_to_get = self.fs.resolve_path(self.file_to_get, self.protocol.cwd) if hasattr(tclient.context, 'metrics'): self.fs.mkfile(self.file_to_get, 0, 0, tclient.context.metrics.bytes, 33188) else: self.fs.mkfile(self.file_to_get, 0, 0, 0, 33188) except tftpy.TftpException: if tclient and tclient.context and not tclient.context.fileobj.closed: tclient.context.fileobj.close() if url: # log to cowrie.log log.msg( format= 'Downloaded URL (%(url)s) with SHA-256 %(shasum)s to %(outfile)s', url=url, outfile=self.artifactFile.shasumFilename, shasum=self.artifactFile.shasum) self.protocol.logDispatch( eventid='cowrie.session.file_download', format= 'Downloaded URL (%(url)s) with SHA-256 %(shasum)s to %(outfile)s', url=url, outfile=self.artifactFile.shasumFilename, shasum=self.artifactFile.shasum) # Update the honeyfs to point to downloaded file self.fs.update_realfile(self.fs.getfile(self.file_to_get), self.artifactFile.shasumFilename) self.fs.chown(self.file_to_get, self.protocol.user.uid, self.protocol.user.gid)
def run(self, application, jidstr, password, muc, server): self.xmppclient = XMPPClient(JID(jidstr), password) if CONFIG.has_option('output_xmpp', 'debug') and \ CONFIG.getboolean('output_xmpp', 'debug') is True: self.xmppclient.logTraffic = True # DEBUG HERE (user, host, resource) = jid.parse(jidstr) self.muc = XMPPLoggerProtocol(muc, server, user + '-' + resource) self.muc.setHandlerParent(self.xmppclient) self.xmppclient.setServiceParent(application) self.anonymous = True self.xmppclient.startService()
def run(self, application, jidstr, password, muc, server): self.xmppclient = XMPPClient(JID(jidstr), password) if CONFIG.has_option('output_xmpp', 'debug') and \ CONFIG.getboolean('output_xmpp', 'debug') is True: self.xmppclient.logTraffic = True # DEBUG HERE (user, host, resource) = jid.parse(jidstr) self.muc = XMPPLoggerProtocol( muc, server, user + '-' + resource) self.muc.setHandlerParent(self.xmppclient) self.xmppclient.setServiceParent(application) self.anonymous = True self.xmppclient.startService()
def download(self, url, fakeoutfile, outputfile, *args, **kwargs): """ url - URL to download fakeoutfile - file in guest's fs that attacker wants content to be downloaded to outputfile - file in host's fs that will hold content of the downloaded file """ try: parsed = compat.urllib_parse.urlparse(url) scheme = parsed.scheme host = parsed.hostname port = parsed.port or (443 if scheme == b'https' else 80) path = parsed.path or '/' if scheme != b'http' and scheme != b'https': raise NotImplementedError if not host: return None except: self.errorWrite('%s: Unsupported scheme.\n' % (url, )) return None if not self.quiet: self.errorWrite( '--%s-- %s\n' % (time.strftime('%Y-%m-%d %H:%M:%S'), url.decode('utf8'))) self.errorWrite('Connecting to %s:%d... connected.\n' % (host.decode('utf8'), port)) self.errorWrite('HTTP request sent, awaiting response... ') factory = HTTPProgressDownloader(self, fakeoutfile, url, outputfile, *args, **kwargs) out_addr = None if CONFIG.has_option('honeypot', 'out_addr'): out_addr = (CONFIG.get('honeypot', 'out_addr'), 0) if scheme == b'https': contextFactory = ssl.ClientContextFactory() contextFactory.method = SSL.SSLv23_METHOD self.connection = reactor.connectSSL(host, port, factory, contextFactory, bindAddress=out_addr) elif scheme == b'http': self.connection = reactor.connectTCP(host, port, factory, bindAddress=out_addr) else: raise NotImplementedError return factory.deferred
def __init__(self): self.sessions = {} self.ttylogs = {} # FIXME figure out what needs to be done here regarding # HoneyPotTransport renamed to HoneyPotSSHTransport #:* Handles ipv6 self.re_sessionlog = re.compile( r'.*HoneyPotSSHTransport,([0-9]+),[:a-f0-9.]+$') # cowrie.session.connect is special since it kicks off new logging session, # and is not handled here self.events = { 'cowrie.login.success': self.handleLoginSucceeded, 'cowrie.login.failed': self.handleLoginFailed, 'cowrie.log.open': self.handleTTYLogOpened, 'cowrie.command.success': self.handleCommand, 'cowrie.command.failed': self.handleUnknownCommand, 'cowrie.session.file_download': self.handleFileDownload, 'cowrie.command.input': self.handleInput, 'cowrie.client.version': self.handleClientVersion, 'cowrie.client.size': self.handleTerminalSize, 'cowrie.session.closed': self._connectionLost, 'cowrie.log.closed': self.handleTTYLogClosed, } self.reported_ssh_port = None if CONFIG.has_option('honeypot', 'reported_ssh_port'): self.reported_ssh_port = CONFIG.getint('honeypot', 'reported_ssh_port') self.report_public_ip = False if CONFIG.has_option('honeypot', 'report_public_ip'): if CONFIG.getboolean('honeypot', 'report_public_ip') == True: self.report_public_ip = True import urllib self.public_ip = urllib.urlopen( 'http://myip.threatstream.com').readline() self.start()
def makeTftpRetrieval(self): """ """ progresshook = Progress(self).progresshook if CONFIG.has_option('honeypot', 'download_limit_size'): self.limit_size = CONFIG.getint('honeypot', 'download_limit_size') self.artifactFile = Artifact(self.file_to_get) tclient = None url = '' try: tclient = tftpy.TftpClient(self.hostname, int(self.port)) # tftpy can't handle unicode string as filename # so we have to convert unicode type to str type tclient.download(str(self.file_to_get), self.artifactFile, progresshook) url = 'tftp://%s/%s' % (self.hostname, self.file_to_get.strip('/')) self.file_to_get = self.fs.resolve_path(self.file_to_get, self.protocol.cwd) if hasattr(tclient.context, 'metrics'): self.fs.mkfile(self.file_to_get, 0, 0, tclient.context.metrics.bytes, 33188) else: self.fs.mkfile(self.file_to_get, 0, 0, 0, 33188) except tftpy.TftpException: if tclient and tclient.context and not tclient.context.fileobj.closed: tclient.context.fileobj.close() if url: # log to cowrie.log log.msg(format='Downloaded URL (%(url)s) with SHA-256 %(shasum)s to %(outfile)s', url=url, outfile=self.artifactFile.shasumFilename, shasum=self.artifactFile.shasum) self.protocol.logDispatch(eventid='cowrie.session.file_download', format='Downloaded URL (%(url)s) with SHA-256 %(shasum)s to %(outfile)s', url=url, outfile=self.artifactFile.shasumFilename, shasum=self.artifactFile.shasum, destfile=self.file_to_get) # Update the honeyfs to point to downloaded file self.fs.update_realfile(self.fs.getfile(self.file_to_get), self.artifactFile.shasumFilename) self.fs.chown(self.file_to_get, self.protocol.user.uid, self.protocol.user.gid)
def run(self, application, jidstr, password, muc, channels, anon=True): self.xmppclient = XMPPClient(JID(jidstr), password) if CONFIG.has_option('database_xmpp', 'debug') and CONFIG.getboolean( 'database_xmpp', 'debug'): self.xmppclient.logTraffic = True # DEBUG HERE (user, host, resource) = jid.parse(jidstr) self.muc = XMPPLoggerProtocol(muc, list(channels.keys()), user + '-' + resource) self.muc.setHandlerParent(self.xmppclient) self.xmppclient.setServiceParent(application) self.signals = {} for channel in channels: for signal in channels[channel]: self.signals[signal] = channel self.anonymous = True self.xmppclient.startService()
def __init__(self): # Default values self.mintry, self.maxtry, self.maxcache = 2, 5, 10 # Are there auth_class parameters? if CONFIG.has_option('honeypot', 'auth_class_parameters'): parameters = CONFIG.get('honeypot', 'auth_class_parameters') parlist = parameters.split(',') if len(parlist) == 3: self.mintry = int(parlist[0]) self.maxtry = int(parlist[1]) self.maxcache = int(parlist[2]) if self.maxtry < self.mintry: self.maxtry = self.mintry + 1 log.msg("maxtry < mintry, adjusting maxtry to: {}".format(self.maxtry)) self.uservar = {} self.uservar_file = '{}/auth_random.json'.format(CONFIG.get('honeypot', 'state_path')) self.loadvars()
def __init__(self): # Default values self.mintry, self.maxtry, self.maxcache = 2, 5, 10 # Are there auth_class parameters? if CONFIG.has_option('honeypot', 'auth_class_parameters'): parameters = CONFIG.get('honeypot', 'auth_class_parameters') parlist = parameters.split(',') if len(parlist) == 3: self.mintry = int(parlist[0]) self.maxtry = int(parlist[1]) self.maxcache = int(parlist[2]) if self.maxtry < self.mintry: self.maxtry = self.mintry + 1 log.msg('maxtry < mintry, adjusting maxtry to: %d' % (self.maxtry,)) self.uservar = {} self.uservar_file = '%s/uservar.json' % CONFIG.get('honeypot', 'data_path') self.loadvars()
def download(self, url, fakeoutfile, outputfile, *args, **kwargs): """ url - URL to download fakeoutfile - file in guest's fs that attacker wants content to be downloaded to outputfile - file in host's fs that will hold content of the downloaded file """ try: parsed = compat.urllib_parse.urlparse(url) scheme = parsed.scheme host = parsed.hostname port = parsed.port or (443 if scheme == b'https' else 80) path = parsed.path or '/' if scheme != b'http' and scheme != b'https': raise NotImplementedError if not host: return None except: self.errorWrite('%s: Unsupported scheme.\n' % (url,)) return None if not self.quiet: self.errorWrite('--%s-- %s\n' % (time.strftime('%Y-%m-%d %H:%M:%S'), url.decode('utf8'))) self.errorWrite('Connecting to %s:%d... connected.\n' % (host.decode('utf8'), port)) self.errorWrite('HTTP request sent, awaiting response... ') factory = HTTPProgressDownloader(self, fakeoutfile, url, outputfile, *args, **kwargs) out_addr = None if CONFIG.has_option('honeypot', 'out_addr'): out_addr = (CONFIG.get('honeypot', 'out_addr'), 0) if scheme == b'https': contextFactory = ssl.ClientContextFactory() contextFactory.method = SSL.SSLv23_METHOD self.connection = reactor.connectSSL(host, port, factory, contextFactory, bindAddress=out_addr) elif scheme == b'http': self.connection = reactor.connectTCP(host, port, factory, bindAddress=out_addr) else: raise NotImplementedError return factory.deferred
def download(self, url, fakeoutfile, outputfile, *args, **kwargs): """ """ try: parsed = compat.urllib_parse.urlparse(url) scheme = parsed.scheme host = parsed.hostname port = parsed.port or (443 if scheme == 'https' else 80) path = parsed.path or '/' if scheme != b'http' and scheme != b'https': raise NotImplementedError except: self.errorWrite( 'curl: (1) Protocol "{}" not supported or disabled in libcurl\n' .format(scheme)) self.exit() return None factory = HTTPProgressDownloader(self, fakeoutfile, url, outputfile, *args, **kwargs) out_addr = None if CONFIG.has_option('honeypot', 'out_addr'): out_addr = (CONFIG.get('honeypot', 'out_addr'), 0) if scheme == 'https': contextFactory = ssl.ClientContextFactory() contextFactory.method = SSL.SSLv23_METHOD reactor.connectSSL(host, port, factory, contextFactory, bindAddress=out_addr) else: # Can only be http self.connection = reactor.connectTCP(host, port, factory, bindAddress=out_addr) return factory.deferred
def ftp_download(self): out_addr = ('', 0) if CONFIG.has_option('honeypot', 'out_addr'): out_addr = (CONFIG.get('honeypot', 'out_addr'), 0) ftp = FTP(source_address=out_addr) # connect if self.verbose: self.write('Connecting to %s\n' % self.host) # TODO: add its IP address after the host try: ftp.connect(host=self.host, port=self.port, timeout=30) except Exception as e: log.msg('FTP connect failed: host=%s, port=%s, err=%s' % (self.host, self.port, str(e))) self.write( 'ftpget: can\'t connect to remote host: Connection refused\n') return False # login if self.verbose: self.write('ftpget: cmd (null) (null)\n') if self.username: self.write('ftpget: cmd USER %s\n' % self.username) else: self.write('ftpget: cmd USER anonymous\n') if self.password: self.write('ftpget: cmd PASS %s\n' % self.password) else: self.write('ftpget: cmd PASS busybox@\n') try: ftp.login(user=self.username, passwd=self.password) except Exception as e: log.msg('FTP login failed: user=%s, passwd=%s, err=%s' % (self.username, self.password, str(e))) self.write('ftpget: unexpected server response to USER: %s\n' % str(e)) try: ftp.quit() except socket.timeout: pass return False # download if self.verbose: self.write('ftpget: cmd TYPE I (null)\n') self.write('ftpget: cmd PASV (null)\n') self.write('ftpget: cmd SIZE %s\n' % self.remote_path) self.write('ftpget: cmd RETR %s\n' % self.remote_path) try: ftp.cwd(self.remote_dir) ftp.retrbinary('RETR %s' % self.remote_file, self.artifactFile.write) except Exception as e: log.msg('FTP retrieval failed: %s' % str(e)) self.write('ftpget: unexpected server response to USER: %s\n' % str(e)) try: ftp.quit() except socket.timeout: pass return False # quit if self.verbose: self.write('ftpget: cmd (null) (null)\n') self.write('ftpget: cmd QUIT (null)\n') try: ftp.quit() except socket.timeout: pass return True
def getSensor(self): if CONFIG.has_option('honeypot', 'sensor_name'): return CONFIG.get('honeypot', 'sensor_name') return None
def makeTftpRetrieval(self): """ """ progresshook = Progress(self).progresshook if CONFIG.has_option('honeypot', 'download_limit_size'): self.limit_size = CONFIG.getint('honeypot', 'download_limit_size') self.download_path = CONFIG.get('honeypot', 'download_path') tmp_fname = '%s_%s_%s_%s' % \ (time.strftime('%Y%m%d%H%M%S'), self.protocol.getProtoTransport().transportId, self.protocol.terminal.transport.session.id, re.sub('[^A-Za-z0-9]', '_', self.file_to_get)) self.safeoutfile = os.path.join(self.download_path, tmp_fname) tclient = None try: tclient = tftpy.TftpClient(self.hostname, int(self.port)) tclient.download(self.file_to_get, self.safeoutfile, progresshook) url = 'tftp://%s/%s' % (self.hostname, self.file_to_get.strip('/')) self.file_to_get = self.fs.resolve_path(self.file_to_get, self.protocol.cwd) if hasattr(tclient.context, 'metrics'): self.fs.mkfile(self.file_to_get, 0, 0, tclient.context.metrics.bytes, 33188) else: self.fs.mkfile(self.file_to_get, 0, 0, 0, 33188) except tftpy.TftpException as err: if tclient and tclient.context and not tclient.context.fileobj.closed: tclient.context.fileobj.close() if os.path.exists(self.safeoutfile): if os.path.getsize(self.safeoutfile) == 0: os.remove(self.safeoutfile) self.safeoutfile = None return with open(self.safeoutfile, 'rb') as f: #shasum = hashlib.sha256(f.read()).hexdigest() shasum = hashlib.md5(f.read()).hexdigest() hash_path = os.path.join(self.download_path, shasum) # If we have content already, delete temp file if not os.path.exists(hash_path): os.rename(self.safeoutfile, hash_path) else: os.remove(self.safeoutfile) log.msg("Not storing duplicate content " + shasum) self.protocol.logDispatch( eventid='cowrie.session.file_download', format= 'Downloaded tftpFile (%(url)s) with SHA-256 %(shasum)s to %(outfile)s', url=url, outfile=hash_path, shasum=shasum) # Link friendly name to hash # os.symlink(shasum, self.safeoutfile) self.safeoutfile = None # Update the honeyfs to point to downloaded file self.fs.update_realfile(self.fs.getfile(self.file_to_get), hash_path) self.fs.chown(self.file_to_get, self.protocol.user.uid, self.protocol.user.gid) self.exit()
if (CONFIG.has_option('output_influx', 'username') and CONFIG.has_option('output_influx', 'password')): username = CONFIG.get('output_influx', 'username') password = CONFIG.get('output_influx', 'password') self.client.switch_user(username, password) try: dbname = CONIFG.get('output_influx', 'database_name') else: dbname = 'cowrie' retention_policy_duration_default = '12w' retention_policy_name = dbname + "_retention_policy" if CONFIG.has_option('output_influx', 'retention_policy_duration'): retention_policy_duration = CONFIG.get( 'output_influx', 'retention_policy_duration') match = re.search('^\d+[dhmw]{1}$', retention_policy_duration) if not match: log.err(("output_influx: invalid retention policy." "Using default '{}'..").format( retention_policy_duration)) retention_policy_duration = retention_policy_duration_default else: retention_policy_duration = retention_policy_duration_default database_list = self.client.get_list_database() dblist = [str(elem['name']) for elem in database_list]
def start(self): try: optlist, args = getopt.getopt(self.args, 'cqO:P:', 'header=') except getopt.GetoptError: self.errorWrite('Unrecognized option\n') self.exit() return if len(args): url = args[0].strip() else: self.errorWrite('wget: missing URL\n') self.errorWrite('Usage: wget [OPTION]... [URL]...\n\n') self.errorWrite('Try `wget --help\' for more options.\n') self.exit() return outfile = None self.quiet = False for opt in optlist: if opt[0] == '-O': outfile = opt[1] if opt[0] == '-q': self.quiet = True # for some reason getopt doesn't recognize "-O -" # use try..except for the case if passed command is malformed try: if not outfile: if '-O' in args: outfile = args[args.index('-O') + 1] except Exception: pass if '://' not in url: url = 'http://%s' % url urldata = compat.urllib_parse.urlparse(url) url = url.encode('utf8') if outfile is None: outfile = urldata.path.split('/')[-1] if not len(outfile.strip()) or not urldata.path.count('/'): outfile = 'index.html' if outfile != '-': outfile = self.fs.resolve_path(outfile, self.protocol.cwd) path = os.path.dirname(outfile) if not path or not self.fs.exists(path) or not self.fs.isdir(path): self.errorWrite( 'wget: %s: Cannot open: No such file or directory\n' % outfile) self.exit() return self.url = url self.limit_size = 0 if CONFIG.has_option('honeypot', 'download_limit_size'): self.limit_size = CONFIG.getint('honeypot', 'download_limit_size') self.downloadPath = CONFIG.get('honeypot', 'download_path') self.artifactFile = Artifact(outfile) # HTTPDownloader will close() the file object so need to preserve the name d = self.download(url, outfile, self.artifactFile) if d: d.addCallback(self.success, outfile) d.addErrback(self.error, url) else: self.exit()
def start(self): """ """ try: optlist, args = getopt.getopt(self.args, 'sho:O', ['help', 'manual', 'silent']) except getopt.GetoptError as err: # TODO: should be 'unknown' instead of 'not recognized' self.write("curl: {}\n".format(err)) self.write( "curl: try 'curl --help' or 'curl --manual' for more information\n" ) self.exit() return for opt in optlist: if opt[0] == '-h' or opt[0] == '--help': self.curl_help() return elif opt[0] == '-s' or opt[0] == '--silent': self.silent = True if len(args): if args[0] is not None: url = str(args[0]).strip() else: self.write( "curl: try 'curl --help' or 'curl --manual' for more information\n" ) self.exit() return if '://' not in url: url = 'http://' + url urldata = compat.urllib_parse.urlparse(url) outfile = None for opt in optlist: if opt[0] == '-o': outfile = opt[1] if opt[0] == '-O': outfile = urldata.path.split('/')[-1] if outfile is None or not len( outfile.strip()) or not urldata.path.count('/'): self.write('curl: Remote file name has no length!\n') self.exit() return if outfile: outfile = self.fs.resolve_path(outfile, self.protocol.cwd) path = os.path.dirname(outfile) if not path or \ not self.fs.exists(path) or \ not self.fs.isdir(path): self.write('curl: %s: Cannot open: No such file or directory\n' % \ (outfile,)) self.exit() return url = url.encode('ascii') self.url = url self.limit_size = 0 if CONFIG.has_option('honeypot', 'download_limit_size'): self.limit_size = CONFIG.getint('honeypot', 'download_limit_size') self.download_path = CONFIG.get('honeypot', 'download_path') if not hasattr(self, 'safeoutfile'): tmp_fname = '%s_%s_%s_%s' % \ (time.strftime('%Y%m%d%H%M%S'), self.protocol.getProtoTransport().transportId, self.protocol.terminal.transport.session.id, re.sub('[^A-Za-z0-9]', '_', url.decode('ascii'))) self.safeoutfile = os.path.join(self.download_path, tmp_fname) self.deferred = self.download(url, outfile, self.safeoutfile) if self.deferred: self.deferred.addCallback(self.success, outfile) self.deferred.addErrback(self.error, url)
def makeService(self, options): """ Construct a TCPServer from a factory defined in Cowrie. """ if options["help"] is True: print("""Usage: twistd [options] cowrie [-h] Options: -h, --help print this help message. Makes a Cowrie SSH/Telnet honeypot. """) sys.exit(1) if os.name == 'posix' and os.getuid() == 0: print('ERROR: You must not run cowrie as root!') sys.exit(1) log.msg("Python Version {}".format(str(sys.version).replace('\n', ''))) log.msg("Twisted Version {}.{}.{}".format(__version__.major, __version__.minor, __version__.micro)) # ssh is enabled by default try: enableSSH = CONFIG.getboolean('ssh', 'enabled') except (configparser.NoSectionError, configparser.NoOptionError): enableSSH = True # telnet is disabled by default try: enableTelnet = CONFIG.getboolean('telnet', 'enabled') except (configparser.NoSectionError, configparser.NoOptionError): enableTelnet = False if enableTelnet is False and enableSSH is False: print('ERROR: You must at least enable SSH or Telnet') sys.exit(1) # Load db loggers self.dbloggers = [] for x in CONFIG.sections(): if not x.startswith('database_'): continue engine = x.split('_')[1] try: dblogger = __import__('cowrie.dblog.{}'.format(engine), globals(), locals(), ['dblog']).DBLogger() log.addObserver(dblogger.emit) self.dbloggers.append(dblogger) log.msg("Loaded dblog engine: {}".format(engine)) except: log.err() log.msg("Failed to load dblog engine: {}".format(engine)) # Load output modules self.output_plugins = [] for x in CONFIG.sections(): if not x.startswith('output_'): continue if CONFIG.getboolean(x, 'enabled') is False: continue engine = x.split('_')[1] try: output = __import__('cowrie.output.{}'.format(engine), globals(), locals(), ['output']).Output() log.addObserver(output.emit) self.output_plugins.append(output) log.msg("Loaded output engine: {}".format(engine)) except ImportError as e: log.err("Failed to load output engine: {} due to ImportError: {}".format(engine, e)) log.msg("Please install the dependencies for {} listed in requirements-output.txt".format(engine)) except Exception: log.err() log.msg("Failed to load output engine: {}".format(engine)) topService = service.MultiService() application = service.Application('cowrie') topService.setServiceParent(application) if enableSSH: factory = cowrie.ssh.factory.CowrieSSHFactory() factory.tac = self factory.portal = portal.Portal(core.realm.HoneyPotRealm()) factory.portal.registerChecker( core.checkers.HoneypotPublicKeyChecker()) factory.portal.registerChecker( core.checkers.HoneypotPasswordChecker()) if CONFIG.has_option('honeypot', 'auth_none_enabled') and \ CONFIG.getboolean('honeypot', 'auth_none_enabled') is True: factory.portal.registerChecker( core.checkers.HoneypotNoneChecker()) if CONFIG.has_section('ssh'): listen_endpoints = get_endpoints_from_section(CONFIG, 'ssh', 2222) else: listen_endpoints = get_endpoints_from_section(CONFIG, 'honeypot', 2222) create_endpoint_services(reactor, topService, listen_endpoints, factory) if enableTelnet: f = cowrie.telnet.transport.HoneyPotTelnetFactory() f.tac = self f.portal = portal.Portal(core.realm.HoneyPotRealm()) f.portal.registerChecker(core.checkers.HoneypotPasswordChecker()) listen_endpoints = get_endpoints_from_section(CONFIG, 'telnet', 2223) create_endpoint_services(reactor, topService, listen_endpoints, f) return topService
def ftp_download(self): out_addr = ('', 0) if CONFIG.has_option('honeypot', 'out_addr'): out_addr = (CONFIG.get('honeypot', 'out_addr'), 0) ftp = FTP(source_address=out_addr) # connect if self.verbose: self.write('Connecting to %s\n' % self.host) # TODO: add its IP address after the host try: ftp.connect(host=self.host, port=self.port, timeout=30) except Exception as e: log.msg('FTP connect failed: host=%s, port=%s, err=%s' % (self.host, self.port, str(e))) self.write('ftpget: can\'t connect to remote host: Connection refused\n') return False # login if self.verbose: self.write('ftpget: cmd (null) (null)\n') if self.username: self.write('ftpget: cmd USER %s\n' % self.username) else: self.write('ftpget: cmd USER anonymous\n') if self.password: self.write('ftpget: cmd PASS %s\n' % self.password) else: self.write('ftpget: cmd PASS busybox@\n') try: ftp.login(user=self.username, passwd=self.password) except Exception as e: log.msg('FTP login failed: user=%s, passwd=%s, err=%s' % (self.username, self.password, str(e))) self.write('ftpget: unexpected server response to USER: %s\n' % str(e)) try: ftp.quit() except socket.timeout: pass return False # download if self.verbose: self.write('ftpget: cmd TYPE I (null)\n') self.write('ftpget: cmd PASV (null)\n') self.write('ftpget: cmd SIZE %s\n' % self.remote_path) self.write('ftpget: cmd RETR %s\n' % self.remote_path) try: ftp.cwd(self.remote_dir) ftp.retrbinary('RETR %s' % self.remote_file, self.artifactFile.write) except Exception as e: log.msg('FTP retrieval failed: %s' % str(e)) self.write('ftpget: unexpected server response to USER: %s\n' % str(e)) try: ftp.quit() except socket.timeout: pass return False # quit if self.verbose: self.write('ftpget: cmd (null) (null)\n') self.write('ftpget: cmd QUIT (null)\n') try: ftp.quit() except socket.timeout: pass return True
def makeService(self, options): """ Construct a TCPServer from a factory defined in Cowrie. """ if options["help"] is True: print("""Usage: twistd [options] cowrie [-h] Options: -h, --help print this help message. Makes a Cowrie SSH/Telnet honeypot. """) sys.exit(1) if os.name == 'posix' and os.getuid() == 0: print('ERROR: You must not run cowrie as root!') sys.exit(1) log.msg("Python Version {}".format(str(sys.version).replace('\n', ''))) log.msg("Twisted Version {}.{}.{}".format(__version__.major, __version__.minor, __version__.micro)) # ssh is enabled by default try: enableSSH = CONFIG.getboolean('ssh', 'enabled') except (configparser.NoSectionError, configparser.NoOptionError): enableSSH = True # telnet is disabled by default try: enableTelnet = CONFIG.getboolean('telnet', 'enabled') except (configparser.NoSectionError, configparser.NoOptionError): enableTelnet = False if enableTelnet is False and enableSSH is False: print('ERROR: You must at least enable SSH or Telnet') sys.exit(1) # Load db loggers self.dbloggers = [] for x in CONFIG.sections(): if not x.startswith('database_'): continue engine = x.split('_')[1] try: dblogger = __import__('cowrie.dblog.{}'.format(engine), globals(), locals(), ['dblog']).DBLogger() log.addObserver(dblogger.emit) self.dbloggers.append(dblogger) log.msg("Loaded dblog engine: {}".format(engine)) except Exception: log.err() log.msg("Failed to load dblog engine: {}".format(engine)) # Load output modules self.output_plugins = [] for x in CONFIG.sections(): if not x.startswith('output_'): continue if CONFIG.getboolean(x, 'enabled') is False: continue engine = x.split('_')[1] try: output = __import__('cowrie.output.{}'.format(engine), globals(), locals(), ['output']).Output() log.addObserver(output.emit) self.output_plugins.append(output) log.msg("Loaded output engine: {}".format(engine)) except ImportError as e: log.err( "Failed to load output engine: {} due to ImportError: {}". format(engine, e)) log.msg( "Please install the dependencies for {} listed in requirements-output.txt" .format(engine)) except Exception: log.err() log.msg("Failed to load output engine: {}".format(engine)) topService = service.MultiService() application = service.Application('cowrie') topService.setServiceParent(application) if enableSSH: factory = cowrie.ssh.factory.CowrieSSHFactory() factory.tac = self factory.portal = portal.Portal(core.realm.HoneyPotRealm()) factory.portal.registerChecker( core.checkers.HoneypotPublicKeyChecker()) factory.portal.registerChecker( core.checkers.HoneypotPasswordChecker()) if CONFIG.has_option('honeypot', 'auth_none_enabled') and \ CONFIG.getboolean('honeypot', 'auth_none_enabled') is True: factory.portal.registerChecker( core.checkers.HoneypotNoneChecker()) if CONFIG.has_section('ssh'): listen_endpoints = get_endpoints_from_section( CONFIG, 'ssh', 2222) else: listen_endpoints = get_endpoints_from_section( CONFIG, 'honeypot', 2222) create_endpoint_services(reactor, topService, listen_endpoints, factory) if enableTelnet: f = cowrie.telnet.transport.HoneyPotTelnetFactory() f.tac = self f.portal = portal.Portal(core.realm.HoneyPotRealm()) f.portal.registerChecker(core.checkers.HoneypotPasswordChecker()) listen_endpoints = get_endpoints_from_section( CONFIG, 'telnet', 2223) create_endpoint_services(reactor, topService, listen_endpoints, f) return topService
def start(self): try: optlist, args = getopt.getopt(self.args, 'sho:O', ['help', 'manual', 'silent']) except getopt.GetoptError as err: # TODO: should be 'unknown' instead of 'not recognized' self.write("curl: {}\n".format(err)) self.write("curl: try 'curl --help' or 'curl --manual' for more information\n") self.exit() return for opt in optlist: if opt[0] == '-h' or opt[0] == '--help': self.curl_help() return elif opt[0] == '-s' or opt[0] == '--silent': self.silent = True if len(args): if args[0] is not None: url = str(args[0]).strip() else: self.write("curl: try 'curl --help' or 'curl --manual' for more information\n") self.exit() return if '://' not in url: url = 'http://' + url urldata = compat.urllib_parse.urlparse(url) outfile = None for opt in optlist: if opt[0] == '-o': outfile = opt[1] if opt[0] == '-O': outfile = urldata.path.split('/')[-1] if outfile is None or not len(outfile.strip()) or not urldata.path.count('/'): self.write('curl: Remote file name has no length!\n') self.exit() return if outfile: outfile = self.fs.resolve_path(outfile, self.protocol.cwd) path = os.path.dirname(outfile) if not path or \ not self.fs.exists(path) or \ not self.fs.isdir(path): self.write('curl: %s: Cannot open: No such file or directory\n' % outfile) self.exit() return url = url.encode('ascii') self.url = url self.limit_size = 0 if CONFIG.has_option('honeypot', 'download_limit_size'): self.limit_size = CONFIG.getint('honeypot', 'download_limit_size') self.download_path = CONFIG.get('honeypot', 'download_path') if not hasattr(self, 'safeoutfile'): tmp_fname = '%s_%s_%s_%s' % \ (time.strftime('%Y%m%d%H%M%S'), self.protocol.getProtoTransport().transportId, self.protocol.terminal.transport.session.id, re.sub('[^A-Za-z0-9]', '_', url.decode('ascii'))) self.safeoutfile = os.path.join(self.download_path, tmp_fname) self.deferred = self.download(url, outfile, self.safeoutfile) if self.deferred: self.deferred.addCallback(self.success, outfile) self.deferred.addErrback(self.error, url)
def start(self): """ """ try: optlist, args = getopt.getopt(self.args, 'cqO:P:', 'header=') except getopt.GetoptError as err: self.errorWrite('Unrecognized option\n') self.exit() return if len(args): url = args[0].strip() else: self.errorWrite('wget: missing URL\n') self.errorWrite('Usage: wget [OPTION]... [URL]...\n\n') self.errorWrite('Try `wget --help\' for more options.\n') self.exit() return outfile = None self.quiet = False for opt in optlist: if opt[0] == '-O': outfile = opt[1] if opt[0] == '-q': self.quiet = True # for some reason getopt doesn't recognize "-O -" # use try..except for the case if passed command is malformed try: if not outfile: if '-O' in args: outfile = args[args.index('-O') + 1] except: pass if '://' not in url: url = 'http://%s' % url urldata = compat.urllib_parse.urlparse(url) url = url.encode('utf8') if outfile is None: outfile = urldata.path.split('/')[-1] if not len(outfile.strip()) or not urldata.path.count('/'): outfile = 'index.html' if outfile != '-': outfile = self.fs.resolve_path(outfile, self.protocol.cwd) path = os.path.dirname(outfile) if not path or not self.fs.exists(path) or not self.fs.isdir(path): self.errorWrite('wget: %s: Cannot open: No such file or directory\n' % outfile) self.exit() return self.url = url self.limit_size = 0 if CONFIG.has_option('honeypot', 'download_limit_size'): self.limit_size = CONFIG.getint('honeypot', 'download_limit_size') self.downloadPath = CONFIG.get('honeypot', 'download_path') self.artifactFile = Artifact(outfile) # HTTPDownloader will close() the file object so need to preserve the name d = self.download(url, outfile, self.artifactFile) if d: d.addCallback(self.success, outfile) d.addErrback(self.error, url) else: self.exit()
def start(self): try: host = CONFIG.get('output_influx', 'host') except Exception: host = '' try: port = CONFIG.getint('output_influx', 'port') except Exception: port = 8086 try: ssl = CONFIG.getboolean('output_influx', 'ssl') except Exception: ssl = False self.client = None try: self.client = InfluxDBClient(host=host, port=port, ssl=ssl, verify_ssl=ssl) except InfluxDBClientError as e: log.err("output_influx: I/O error({0}): '{1}'".format( e.errno, e.strerror)) return if self.client is None: log.err("output_influx: cannot instantiate client!") return if (CONFIG.has_option('output_influx', 'username') and CONFIG.has_option('output_influx', 'password')): username = CONFIG.get('output_influx', 'username') password = CONFIG.get('output_influx', 'password', raw=True) self.client.switch_user(username, password) try: dbname = CONFIG.get('output_influx', 'database_name') except Exception: dbname = 'cowrie' retention_policy_duration_default = '12w' retention_policy_name = dbname + "_retention_policy" if CONFIG.has_option('output_influx', 'retention_policy_duration'): retention_policy_duration = CONFIG.get( 'output_influx', 'retention_policy_duration') match = re.search(r'^\d+[dhmw]{1}$', retention_policy_duration) if not match: log.err(("output_influx: invalid retention policy." "Using default '{}'..").format( retention_policy_duration)) retention_policy_duration = retention_policy_duration_default else: retention_policy_duration = retention_policy_duration_default database_list = self.client.get_list_database() dblist = [str(elem['name']) for elem in database_list] if dbname not in dblist: self.client.create_database(dbname) self.client.create_retention_policy( retention_policy_name, retention_policy_duration, 1, database=dbname, default=True) else: retention_policies_list = self.client.get_list_retention_policies( database=dbname) rplist = [str(elem['name']) for elem in retention_policies_list] if retention_policy_name not in rplist: self.client.create_retention_policy( retention_policy_name, retention_policy_duration, 1, database=dbname, default=True) else: self.client.alter_retention_policy( retention_policy_name, database=dbname, duration=retention_policy_duration, replication=1, default=True) self.client.switch_database(dbname)
def start(self): """ """ try: host = CONFIG.get('output_influx', 'host') except: host = '' try: port = CONFIG.getint('output_influx', 'port') except: port = 8086 self.client = None try: self.client = InfluxDBClient(host=host, port=port) except InfluxDBClientError as e: log.err("output_influx: I/O error({0}): '{1}'".format( e.errno, e.strerror)) return if self.client is None: log.err("output_influx: cannot instantiate client!") return if (CONFIG.has_option('output_influx', 'username') and CONFIG.has_option('output_influx', 'password')): username = CONFIG.get('output_influx', 'username') password = CONFIG.get('output_influx', 'password', raw=True) self.client.switch_user(username, password) try: dbname = CONFIG.get('output_influx', 'database_name') except: dbname = 'cowrie' retention_policy_duration_default = '12w' retention_policy_name = dbname + "_retention_policy" if CONFIG.has_option('output_influx', 'retention_policy_duration'): retention_policy_duration = CONFIG.get( 'output_influx', 'retention_policy_duration') match = re.search('^\d+[dhmw]{1}$', retention_policy_duration) if not match: log.err( ("output_influx: invalid retention policy." "Using default '{}'..").format(retention_policy_duration)) retention_policy_duration = retention_policy_duration_default else: retention_policy_duration = retention_policy_duration_default database_list = self.client.get_list_database() dblist = [str(elem['name']) for elem in database_list] if dbname not in dblist: self.client.create_database(dbname) self.client.create_retention_policy(retention_policy_name, retention_policy_duration, 1, database=dbname, default=True) else: retention_policies_list = self.client.get_list_retention_policies( database=dbname) rplist = [str(elem['name']) for elem in retention_policies_list] if retention_policy_name not in rplist: self.client.create_retention_policy(retention_policy_name, retention_policy_duration, 1, database=dbname, default=True) else: self.client.alter_retention_policy( retention_policy_name, database=dbname, duration=retention_policy_duration, replication=1, default=True) self.client.switch_database(dbname)