def __init__(self): self.host = CONFIG.get(self.RETHINK_DB_SEGMENT, 'host') self.port = CONFIG.getint(self.RETHINK_DB_SEGMENT, 'port') self.db = CONFIG.get(self.RETHINK_DB_SEGMENT, 'db') self.table = CONFIG.get(self.RETHINK_DB_SEGMENT, 'table') self.password = CONFIG.get(self.RETHINK_DB_SEGMENT, 'password', raw=True) cowrie.core.output.Output.__init__(self)
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 __init__(self): """ """ facilityString = CONFIG.get('output_localsyslog', 'facility') self.format = CONFIG.get('output_localsyslog', 'format') self.facility = vars(syslog)['LOG_' + facilityString] self.syslog = twisted.python.syslog.SyslogObserver(prefix='cowrie', facility=self.facility) cowrie.core.output.Output.__init__(self)
def start(self): server = CONFIG.get('output_hpfeeds', 'server') port = CONFIG.getint('output_hpfeeds', 'port') ident = CONFIG.get('output_hpfeeds', 'identifier') secret = CONFIG.get('output_hpfeeds', 'secret') debug = CONFIG.getboolean('output_hpfeeds', 'debug') self.client = hpclient(server, port, ident, secret, debug) self.meta = {}
def __init__(self): self.apiKey = CONFIG.get('output_virustotal', 'api_key') self.debug = CONFIG.getboolean('output_virustotal', 'debug', fallback=False) self.upload = CONFIG.getboolean('output_virustotal', 'upload', fallback=True) self.comment = CONFIG.getboolean('output_virustotal', 'comment', fallback=True) self.scan_file = CONFIG.getboolean('output_virustotal', 'scan_file', fallback=True) self.scan_url = CONFIG.getboolean('output_virustotal', 'scan_url', fallback=False) self.commenttext = CONFIG.get('output_virustotal', 'commenttext', fallback=COMMENT) cowrie.core.output.Output.__init__(self)
def __init__(self): """ """ self.host = CONFIG.get('output_elasticsearch', 'host') self.port = CONFIG.get('output_elasticsearch', 'port') self.index = CONFIG.get('output_elasticsearch', 'index') self.type = CONFIG.get('output_elasticsearch', 'type') self.pipeline = CONFIG.get('output_elasticsearch', 'pipeline') cowrie.core.output.Output.__init__(self)
def start(self): server = CONFIG.get('output_xmpp', 'server') user = CONFIG.get('output_xmpp', 'user') password = CONFIG.get('output_xmpp', 'password') muc = CONFIG.get('output_xmpp', 'muc') resource = ''.join([choice(string.ascii_letters) for i in range(8)]) jid = user + '/' + resource application = service.Application('honeypot') self.run(application, jid, password, JID(None, [muc, server, None]), server)
def __init__(self, *args, **kw): """ Initialize logging """ self.ttylogPath = CONFIG.get('honeypot', 'log_path') self.downloadPath = CONFIG.get('honeypot', 'download_path') self.ttylogEnabled = CONFIG.getboolean('honeypot', 'ttylog', fallback=True) self.bytesReceivedLimit = CONFIG.getint('honeypot', 'download_limit_size', fallback=0) channel.SSHChannel.__init__(self, *args, **kw)
def __init__(self, realm): self.hostname = CONFIG.get('honeypot', 'hostname') try: arches = [arch.strip() for arch in CONFIG.get('shell', 'arch').split(',')] self.arch = random.choice(arches) except NoOptionError: self.arch = 'linux-x64-lsb' log.msg("Initialized emulated server as architecture: {}".format(self.arch))
def __init__(self, realm): self.hostname = CONFIG.get('honeypot', 'hostname') try: self.arch = random.choice(CONFIG.get('shell', 'arch').split(',')) # TODO trim whitespace except NoOptionError: self.arch = 'linux-x64-lsb' log.msg("Initialized emulated server as architecture: {}".format(self.arch))
def __init__(self): """ Initializing the class """ self.index = CONFIG.get('output_splunklegacy', 'index') self.username = CONFIG.get('output_splunklegacy', 'username') self.password = CONFIG.get('output_splunklegacy', 'password', raw=True) self.host = CONFIG.get('output_splunklegacy', 'host') self.port = CONFIG.getint('output_splunklegacy', 'port') cowrie.core.output.Output.__init__(self)
def __init__(self): self.auth_key = CONFIG.get('output_dshield', 'auth_key') self.userid = CONFIG.get('output_dshield', 'userid') self.batch_size = CONFIG.getint('output_dshield', 'batch_size') try: self.debug = CONFIG.getboolean('output_dshield', 'debug') except: self.debug = False cowrie.core.output.Output.__init__(self)
def __init__(self): self.user = CONFIG.get('output_csirtg', 'username') or USERNAME self.feed = CONFIG.get('output_csirtg', 'feed') or FEED self.token = CONFIG.get('output_csirtg', 'token') or TOKEN try: self.description = CONFIG.get('output_csirtg', 'description') except Exception: self.description = DESCRIPTION self.context = {} self.client = Client(token=self.token) cowrie.core.output.Output.__init__(self)
def startFactory(self): # For use by the uptime command self.starttime = time.time() # Load/create keys rsaPubKeyString, rsaPrivKeyString = cowriekeys.getRSAKeys() dsaPubKeyString, dsaPrivKeyString = cowriekeys.getDSAKeys() self.publicKeys = { b'ssh-rsa': keys.Key.fromString(data=rsaPubKeyString), b'ssh-dss': keys.Key.fromString(data=dsaPubKeyString) } self.privateKeys = { b'ssh-rsa': keys.Key.fromString(data=rsaPrivKeyString), b'ssh-dss': keys.Key.fromString(data=dsaPrivKeyString) } _modulis = '/etc/ssh/moduli', '/private/etc/moduli' for _moduli in _modulis: try: self.primes = primes.parseModuliFile(_moduli) break except IOError: pass try: self.ourVersionString = CONFIG.get('ssh', 'version') except NoOptionError: self.ourVersionString = 'SSH-2.0-OpenSSH_6.0p1 Debian-4+deb7u2' factory.SSHFactory.startFactory(self) log.msg("Ready to accept SSH connections")
def hardware_platform(): """ """ try: return CONFIG.get('shell', 'hardware_platform') except NoOptionError: return 'x86_64'
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 kernel_name(): """ """ try: return CONFIG.get('shell', 'kernel_name') except NoOptionError: return 'Linux'
def kernel_version(): """ """ try: return CONFIG.get('shell', 'kernel_version') except NoOptionError: return '3.2.0-4-amd64'
def kernel_build_string(): """ """ try: return CONFIG.get('shell', 'kernel_build_string') except NoOptionError: return '#1 SMP Debian 3.2.68-1+deb7u1'
def operating_system(): """ """ try: return CONFIG.get('shell', 'operating_system') except NoOptionError: return 'GNU/Linux'
def __init__(self): cowrie.core.output.Output.__init__(self) fn = CONFIG.get('output_jsonlog', 'logfile') self.epoch_timestamp = CONFIG.getboolean('output_jsonlog', 'epoch_timestamp', fallback=False) dirs = os.path.dirname(fn) base = os.path.basename(fn) self.outfile = cowrie.python.logfile.CowrieDailyLogFile(base, dirs, defaultMode=0o664)
def __init__(self): addr = CONFIG.get('output_socketlog', 'address') self.host = addr.split(':')[0] self.port = int(addr.split(':')[1]) self.timeout = CONFIG.getint('output_socketlog', 'timeout') cowrie.core.output.Output.__init__(self)
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 requestAvatar(self, avatarId, mind, *interfaces): """ """ try: backend = CONFIG.get('honeypot', 'backend') except: backend = 'shell' if backend == 'shell': if conchinterfaces.IConchUser in interfaces: serv = shellserver.CowrieServer(self) user = shellavatar.CowrieUser(avatarId, serv) return interfaces[0], user, user.logout elif ITelnetProtocol in interfaces: serv = shellserver.CowrieServer(self) user = session.HoneyPotTelnetSession(avatarId, serv) return interfaces[0], user, user.logout raise NotImplementedError("No supported interfaces found.") elif backend == 'proxy': if conchinterfaces.IConchUser in interfaces: serv = proxyserver.CowrieServer(self) user = proxyavatar.CowrieUser(avatarId, serv) return interfaces[0], user, user.logout elif ITelnetProtocol in interfaces: raise NotImplementedError("Telnet not yet supported for proxy mode.") log.msg('No supported interfaces found.') raise NotImplementedError("No supported interfaces found.") else: raise NotImplementedError("No supported backend found.")
def getCommand(self, cmd, paths): if not len(cmd.strip()): return None path = None if cmd in self.commands: return self.commands[cmd] if cmd[0] in ('.', '/'): path = self.fs.resolve_path(cmd, self.cwd) if not self.fs.exists(path): return None else: for i in [ '%s/%s' % (self.fs.resolve_path(x, self.cwd), cmd) for x in paths ]: if self.fs.exists(i): path = i break txt = os.path.normpath('{}/txtcmds/{}'.format(CONFIG.get('honeypot', 'share_path'), path)) if os.path.exists(txt) and os.path.isfile(txt): return self.txtcmd(txt) if path in self.commands: return self.commands[path] log.msg("Can't find command {}".format(path)) return None
def __init__(self, *args, **kw): """ Initialize logging """ self.ttylogPath = CONFIG.get('honeypot', 'log_path') self.downloadPath = CONFIG.get('honeypot', 'download_path') try: self.ttylogEnabled = CONFIG.getboolean('honeypot', 'ttylog') except NoOptionError: self.ttylogEnabled = True try: self.bytesReceivedLimit = CONFIG.getint('honeypot', 'download_limit_size') except NoOptionError: self.bytesReceivedLimit = 0 channel.SSHChannel.__init__(self, *args, **kw)
def __init__(self): self.arch = 'linux-x64-lsb' self.hostname = "unitTest" self.pckl = pickle.load( open(CONFIG.get('honeypot', 'filesystem_file'), 'rb')) self.fs = fs.HoneyPotFilesystem(copy.deepcopy(self.pckl), 'arch') self.process = None
def logger(): try: dir = CONFIG.get("honeypot", "log_path") except NoOptionError: dir = "log" logfile = CowrieDailyLogFile("cowrie.log", dir) return textFileLogObserver(logfile, timeFormat='%Y-%m-%dT%H:%M:%S.%f%z')
def initFileSystem(self): """ Do this so we can trigger it later. Not all sessions need file system """ self.fs = fs.HoneyPotFilesystem(copy.deepcopy(fs.PICKLE), self.arch) try: self.process = self.getCommandOutput(CONFIG.get('shell', 'processes'))['command']['ps'] except NoOptionError: self.process = None
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 close(self, fd): """ """ if not fd: return True if self.tempfiles[fd] is not None: shasum = hashlib.sha256(open(self.tempfiles[fd], 'rb').read()).hexdigest() shasumfile = CONFIG.get('honeypot', 'download_path') + "/" + shasum if (os.path.exists(shasumfile)): os.remove(self.tempfiles[fd]) else: os.rename(self.tempfiles[fd], shasumfile) self.update_realfile(self.getfile(self.filenames[fd]), shasumfile) log.msg(format='SFTP Uploaded file \"%(filename)s\" to %(outfile)s', eventid='cowrie.session.file_upload', filename=os.path.basename(self.filenames[fd]), outfile=shasumfile, shasum=shasum) del self.tempfiles[fd] del self.filenames[fd] return os.close(fd)
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.decode('utf8') port = parsed.port or (443 if scheme == b'https' else 80) if scheme != b'http' and scheme != b'https': raise NotImplementedError if not host: return None except Exception: 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, 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 file_contents(self, target): """ Retrieve the content of a file in the honeyfs It follows links. It tries A_REALFILE first and then tries honeyfs directory Then return the executable header for executables """ path = self.resolve_path(target, os.path.dirname(target)) if not path or not self.exists(path): raise FileNotFound f = self.getfile(path) if f[A_TYPE] == T_DIR: raise IsADirectoryError elif f[A_TYPE] == T_FILE and f[A_REALFILE]: return open(f[A_REALFILE], 'rb').read() elif f[A_TYPE] == T_FILE and f[A_SIZE] == 0: # Zero-byte file lacking A_REALFILE backing: probably empty. # (The exceptions to this are some system files in /proc and /sys, # but it's likely better to return nothing than suspiciously fail.) return '' elif f[A_TYPE] == T_FILE and f[A_MODE] & stat.S_IXUSR: return open(CONFIG.get('honeypot', 'share_path') + '/arch/' + self.arch, 'rb').read()
def start(self): try: optlist, args = getopt.getopt( self.args, '46bCDdhklnrStUuvZzI:i:O:P:p:q:s:T:V:w:X:x:') except getopt.GetoptError: self.help() self.exit() return if not args or len(args) < 2: self.help() self.exit() return host = args[0] port = args[1] address = dottedQuadToNum(host) for net in local_networks: if addressInNetwork(address, net): self.exit() return if not re.match('[\d]+', port): self.errorWrite('nc: port number invalid: {}\n'.format(port)) self.exit() return out_addr = None try: out_addr = (CONFIG.get('honeypot', 'out_addr'), 0) except Exception: out_addr = ('0.0.0.0', 0) self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.s.bind(out_addr) self.s.connect((host, int(port))) self.recv_data()
def generate_file(self, outfile): data = "" # TODO: make sure it is written to temp file, not downloads 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]', '_', outfile)) safeoutfile = os.path.join(CONFIG.get('honeypot', 'download_path'), tmp_fname) # Data contains random garbage from an actual file, so when # catting the file, you'll see some 'real' compiled data for i in range(random.randint(3, 15)): if random.randint(1, 3) == 1: data = data + command_gcc.RANDOM_DATA[::-1] else: data = data + command_gcc.RANDOM_DATA # Write random data with open(safeoutfile, 'wb') as f: f.write(data) # Output file outfile = self.fs.resolve_path(outfile, self.protocol.cwd) # Create file for the protocol self.fs.mkfile(outfile, 0, 0, len(data), 33188) self.fs.update_realfile(self.fs.getfile(outfile), safeoutfile) self.fs.chown(outfile, self.protocol.user.uid, self.protocol.user.gid) # Segfault command class segfault_command(HoneyPotCommand): def call(self): self.write("Segmentation fault\n") # Trick the 'new compiled file' as an segfault self.protocol.commands[outfile] = segfault_command # Done self.exit()
def __init__(self): self.seen = set() self.session = get_session() self.session.set_credentials( CONFIG.get("output_s3", "access_key_id"), CONFIG.get("output_s3", "secret_access_key"), ) self.client = self.session.create_client( 's3', region_name=CONFIG.get("output_s3", "region"), endpoint_url=CONFIG.get("output_s3", "endpoint") or None, verify=False if CONFIG.get("output_s3", "verify") == "no" else True, ) self.bucket = CONFIG.get("output_s3", "bucket") cowrie.core.output.Output.__init__(self)
def open(self, filename, openFlags, mode): """ #log.msg("fs.open %s" % filename) #if (openFlags & os.O_APPEND == os.O_APPEND): # log.msg("fs.open append") #if (openFlags & os.O_CREAT == os.O_CREAT): # log.msg("fs.open creat") #if (openFlags & os.O_TRUNC == os.O_TRUNC): # log.msg("fs.open trunc") #if (openFlags & os.O_EXCL == os.O_EXCL): # log.msg("fs.open excl") # treat O_RDWR same as O_WRONLY """ if openFlags & os.O_WRONLY == os.O_WRONLY or openFlags & os.O_RDWR == os.O_RDWR: # strip executable bit hostmode = mode & ~(111) hostfile = '%s/%s_sftp_%s' % \ (CONFIG.get('honeypot', 'download_path'), time.strftime('%Y%m%d-%H%M%S'), re.sub('[^A-Za-z0-9]', '_', filename)) #log.msg("fs.open file for writing, saving to %s" % safeoutfile) self.mkfile(filename, 0, 0, 0, stat.S_IFREG | mode) fd = os.open(hostfile, openFlags, hostmode) self.update_realfile(self.getfile(filename), hostfile) self.tempfiles[fd] = hostfile self.filenames[fd] = filename return fd elif openFlags & os.O_RDONLY == os.O_RDONLY: return None return None
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) #username=theusername.encode('string-escape'), #password=thepassword.encode('string-escape')) return True else: log.msg(eventid='cowrie.login.failed', format='login attempt [%(username)s/%(password)s] failed', username=theusername, password=thepassword) #username=theusername.encode('string-escape'), #password=thepassword.encode('string-escape')) return False
def load(self): """ load the user db """ try: with open( '{}/userdb.txt'.format(CONFIG.get('honeypot', 'etc_path')), 'r') as db: userdb = db.readlines() except IOError: log.msg( "Could not read etc/userdb.txt, default database activated") userdb = _USERDB_DEFAULTS for user in userdb: if not user.startswith('#'): try: login = user.split(':')[0].encode('utf8') password = user.split(':')[2].strip().encode('utf8') except IndexError: continue else: self.adduser(login, password)
def getSensor(self): if CONFIG.has_option('honeypot', 'sensor_name'): return CONFIG.get('honeypot', 'sensor_name') return None
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 __init__(self): self.slack_channel = CONFIG.get('output_slack', 'channel') self.slack_token = CONFIG.get('output_slack', 'token') cowrie.core.output.Output.__init__(self)
def __init__(self): self.url_base = CONFIG.get('output_cuckoo', 'url_base').encode('utf-8') self.api_user = CONFIG.get('output_cuckoo', 'user') self.api_passwd = CONFIG.get('output_cuckoo', 'passwd', raw=True) self.cuckoo_force = int(CONFIG.getboolean('output_cuckoo', 'force')) cowrie.core.output.Output.__init__(self)
def start(self): try: optlist, args = getopt.getopt(self.args, 'cvu:p:P:') except getopt.GetoptError: self.help() self.exit() return if len(args) < 2: self.help() self.exit() return self.verbose = False self.username = '' self.password = '' self.port = 21 self.host = '' self.local_file = '' self.remote_path = '' for opt in optlist: if opt[0] == '-v': self.verbose = True elif opt[0] == '-u': self.username = opt[1] elif opt[0] == '-p': self.password = opt[1] elif opt[0] == '-P': try: self.port = int(opt[1]) except ValueError: pass if len(args) == 2: self.host, self.remote_path = args elif len(args) >= 3: self.host, self.local_file, self.remote_path = args[:3] self.remote_dir = os.path.dirname(self.remote_path) self.remote_file = os.path.basename(self.remote_path) if not self.local_file: self.local_file = self.remote_file fakeoutfile = self.fs.resolve_path(self.local_file, self.protocol.cwd) path = os.path.dirname(fakeoutfile) if not path or not self.fs.exists(path) or not self.fs.isdir(path): self.write( 'ftpget: can\'t open \'%s\': No such file or directory' % self.local_file) self.exit() return self.download_path = CONFIG.get('honeypot', 'download_path') self.url_log = 'ftp://' if self.username: self.url_log = '{}{}'.format(self.url_log, self.username) if self.password: self.url_log = '{}:{}'.format(self.url_log, self.password) self.url_log = '{}@'.format(self.url_log) self.url_log = '{}{}'.format(self.url_log, self.host) if self.port != 21: self.url_log = '{}:{}'.format(self.url_log, self.port) self.url_log = '{}/{}'.format(self.url_log, self.remote_path) self.artifactFile = Artifact(self.local_file) result = self.ftp_download() self.artifactFile.close() if not result: # log to cowrie.log log.msg( format='Attempt to download file(s) from URL (%(url)s) failed', url=self.url_log) self.protocol.logDispatch( eventid='cowrie.session.file_download.failed', format='Attempt to download file(s) from URL (%(url)s) failed', url=self.url_log) self.exit() return # log to cowrie.log log.msg( format= 'Downloaded URL (%(url)s) with SHA-256 %(shasum)s to %(outfile)s', url=self.url_log, 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=self.url_log, outfile=self.artifactFile.shasumFilename, shasum=self.artifactFile.shasum, destfile=self.local_file) # Update the honeyfs to point to downloaded file self.fs.mkfile(fakeoutfile, 0, 0, os.path.getsize(self.artifactFile.shasumFilename), 33188) self.fs.update_realfile(self.fs.getfile(fakeoutfile), self.artifactFile.shasumFilename) self.fs.chown(fakeoutfile, self.protocol.user.uid, self.protocol.user.gid) self.exit()
except: import pickle import os import time import fnmatch import hashlib import re import stat import errno from twisted.python import log from cowrie.core.config import CONFIG PICKLE = pickle.load(open(CONFIG.get('honeypot', 'filesystem_file'), 'rb')) A_NAME, \ A_TYPE, \ A_UID, \ A_GID, \ A_SIZE, \ A_MODE, \ A_CTIME, \ A_CONTENTS, \ A_TARGET, \ A_REALFILE = list(range(0, 10)) T_LINK, \ T_DIR, \ T_FILE, \ T_BLK, \
import os import time import fnmatch import hashlib import re import stat import errno from twisted.python import log from cowrie.core.config import CONFIG # At the moment this is the first place a config file is used # Put extra help here in case it goes wrong try: PICKLE = pickle.load(open(CONFIG.get('shell', 'filesystem'), 'rb')) except: print("ERROR: Config file not found: etc/cowrie.cfg.dist") exit(2) A_NAME, \ A_TYPE, \ A_UID, \ A_GID, \ A_SIZE, \ A_MODE, \ A_CTIME, \ A_CONTENTS, \ A_TARGET, \ A_REALFILE = list(range(0, 10))
def start(self): try: optlist, args = getopt.getopt(self.args, 'cvu:p:P:') except getopt.GetoptError as err: self.help() self.exit() return if len(args) < 2: self.help() self.exit() return self.verbose = False self.username = '' self.password = '' self.port = 21 self.host = '' self.local_file = '' self.remote_path = '' for opt in optlist: if opt[0] == '-v': self.verbose = True elif opt[0] == '-u': self.username = opt[1] elif opt[0] == '-p': self.password = opt[1] elif opt[0] == '-P': try: self.port = int(opt[1]) except ValueError: pass if len(args) == 2: self.host, self.remote_path = args elif len(args) >= 3: self.host, self.local_file, self.remote_path = args[:3] self.remote_dir = os.path.dirname(self.remote_path) self.remote_file = os.path.basename(self.remote_path) if not self.local_file: self.local_file = self.remote_file fakeoutfile = self.fs.resolve_path(self.local_file, self.protocol.cwd) path = os.path.dirname(fakeoutfile) if not path or \ not self.fs.exists(path) or \ not self.fs.isdir(path): self.write( 'ftpget: can\'t open \'%s\': No such file or directory' % self.local_file) self.exit() return url = 'ftp://%s/%s' % (self.host, self.remote_path) self.download_path = CONFIG.get('honeypot', 'download_path') self.url_log = 'ftp://' if self.username: self.url_log = '{}{}'.format(self.url_log, self.username) if self.password: self.url_log = '{}:{}'.format(self.url_log, self.password) self.url_log = '{}@'.format(self.url_log) self.url_log = '{}{}'.format(self.url_log, self.host) if self.port != 21: self.url_log = '{}:{}'.format(self.url_log, self.port) self.url_log = '{}/{}'.format(self.url_log, self.remote_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]', '_', url)) self.safeoutfile = os.path.join(self.download_path, tmp_fname) result = self.ftp_download(self.safeoutfile) if not result: self.protocol.logDispatch( eventid='cowrie.session.file_download.failed', format='Attempt to download file(s) from URL (%(url)s) failed', url=self.url_log) self.safeoutfile = None self.exit() return if not os.path.isfile(self.safeoutfile): log.msg("there's no file " + self.safeoutfile) self.exit() return with open(self.safeoutfile, 'rb') as f: shasum = hashlib.sha256(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 URL (%(url)s) with SHA-256 %(shasum)s to %(outfile)s', url=self.url_log, 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.mkfile(fakeoutfile, 0, 0, os.path.getsize(hash_path), 33188) self.fs.update_realfile(self.fs.getfile(fakeoutfile), hash_path) self.fs.chown(fakeoutfile, self.protocol.user.uid, self.protocol.user.gid) self.exit()
def __init__(self): self.userdb = [] self.userdb_file = '%s/userdb.txt' % CONFIG.get( 'honeypot', 'data_path') self.load()
def __init__(self, realm): self.avatars = [] self.hostname = CONFIG.get('honeypot', 'hostname')
def __init__(self): self.group_file = '%s/etc/group' % (CONFIG.get('honeypot', 'contents_path'), ) self.load()
import errno import fnmatch import hashlib import os import re import stat import time from twisted.python import log from cowrie.core.config import CONFIG # At the moment this is the first place a config file is used # Put extra help here in case it goes wrong try: with open(CONFIG.get('shell', 'filesystem'), 'rb') as f: PICKLE = pickle.load(f) except UnicodeDecodeError: with open(CONFIG.get('shell', 'filesystem'), 'rb') as f: PICKLE = pickle.load(f, encoding='utf8') except Exception as e: log.err(e, "ERROR: Failed to load filesystem") exit(2) A_NAME, A_TYPE, A_UID, A_GID, A_SIZE, A_MODE, A_CTIME, A_CONTENTS, A_TARGET, A_REALFILE = list( range(0, 10)) T_LINK, T_DIR, T_FILE, T_BLK, T_CHR, T_SOCK, T_FIFO = list(range(0, 7)) SPECIAL_PATHS = ['/sys', '/proc', '/dev/pts']
def __init__(self): self.passwd_file = '%s/etc/passwd' % (CONFIG.get( 'honeypot', 'contents_path'), ) self.load()
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()
def __init__(self): self.enabled = CONFIG.getboolean('output_malshare', 'enabled') self.host = CONFIG.get('output_remotesyslog', 'host') self.port = CONFIG.get('output_remotesyslog', 'port') self.server = CONFIG.get('output_remotesyslog', 'server') cowrie.core.output.Output.__init__(self)
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
class LoggingServerProtocol(insults.ServerProtocol): """ Wrapper for ServerProtocol that implements TTY logging """ redirlogOpen = False # it will be set at core/protocol.py stdinlogOpen = False ttylogOpen = False ttylogPath = CONFIG.get('honeypot', 'ttylog_path') downloadPath = CONFIG.get('honeypot', 'download_path') ttylogEnabled = CONFIG.getboolean('honeypot', 'ttylog', fallback=True) bytesReceivedLimit = CONFIG.getint('honeypot', 'download_limit_size', fallback=0) bytesReceived = 0 redirFiles = set() def __init__(self, prot=None, *a, **kw): insults.ServerProtocol.__init__(self, prot, *a, **kw) if prot is protocol.HoneyPotExecProtocol: self.type = 'e' # Execcmd else: self.type = 'i' # Interactive def getSessionId(self): transportId = self.transport.session.conn.transport.transportId channelId = self.transport.session.id return (transportId, channelId) def connectionMade(self): transportId, channelId = self.getSessionId() self.startTime = time.time() if self.ttylogEnabled: self.ttylogFile = '%s/%s-%s-%s%s.log' % \ (self.ttylogPath, time.strftime('%Y%m%d-%H%M%S'), transportId, channelId, self.type) ttylog.ttylog_open(self.ttylogFile, self.startTime) self.ttylogOpen = True self.ttylogSize = 0 self.stdinlogFile = '%s/%s-%s-%s-stdin.log' % \ (self.downloadPath, time.strftime('%Y%m%d-%H%M%S'), transportId, channelId) if self.type == 'e': self.stdinlogOpen = True else: self.stdinlogOpen = False insults.ServerProtocol.connectionMade(self) if self.type == 'e': cmd = self.terminalProtocol.execcmd.encode('utf8') ttylog.ttylog_write(self.ttylogFile, len(cmd), ttylog.TYPE_INTERACT, time.time(), cmd) def write(self, data): if self.ttylogEnabled and self.ttylogOpen: ttylog.ttylog_write(self.ttylogFile, len(data), ttylog.TYPE_OUTPUT, time.time(), data) self.ttylogSize += len(data) insults.ServerProtocol.write(self, data) def dataReceived(self, data): """ Input received from user """ self.bytesReceived += len(data) if self.bytesReceivedLimit and self.bytesReceived > self.bytesReceivedLimit: log.msg(format='Data upload limit reached') self.eofReceived() return if self.stdinlogOpen: with open(self.stdinlogFile, 'ab') as f: f.write(data) elif self.ttylogEnabled and self.ttylogOpen: ttylog.ttylog_write(self.ttylogFile, len(data), ttylog.TYPE_INPUT, time.time(), data) # prevent crash if something like this was passed: # echo cmd ; exit; \n\n if self.terminalProtocol: insults.ServerProtocol.dataReceived(self, data) def eofReceived(self): """ Receive channel close and pass on to terminal """ if self.terminalProtocol: self.terminalProtocol.eofReceived() def loseConnection(self): """ Override super to remove the terminal reset on logout """ self.transport.loseConnection() def connectionLost(self, reason): """ FIXME: this method is called 4 times on logout.... it's called once from Avatar.closed() if disconnected """ if self.stdinlogOpen: try: with open(self.stdinlogFile, 'rb') as f: shasum = hashlib.sha256(f.read()).hexdigest() shasumfile = os.path.join(self.downloadPath, shasum) if os.path.exists(shasumfile): os.remove(self.stdinlogFile) duplicate = True else: os.rename(self.stdinlogFile, shasumfile) duplicate = False log.msg( eventid='cowrie.session.file_download', format= 'Saved stdin contents with SHA-256 %(shasum)s to %(outfile)s', url='stdin', duplicate=duplicate, outfile=shasumfile, shasum=shasum, destfile='') except IOError: pass finally: self.stdinlogOpen = False if self.redirFiles: for rp in self.redirFiles: rf = rp[0] if rp[1]: url = rp[1] else: url = rf[rf.find('redir_') + len('redir_'):] try: if not os.path.exists(rf): continue if os.path.getsize(rf) == 0: os.remove(rf) continue with open(rf, 'rb') as f: shasum = hashlib.sha256(f.read()).hexdigest() shasumfile = os.path.join(self.downloadPath, shasum) if os.path.exists(shasumfile): os.remove(rf) duplicate = True else: os.rename(rf, shasumfile) duplicate = False log.msg( eventid='cowrie.session.file_download', format= 'Saved redir contents with SHA-256 %(shasum)s to %(outfile)s', url=url, duplicate=duplicate, outfile=shasumfile, shasum=shasum, destfile=url) except IOError: pass self.redirFiles.clear() if self.ttylogEnabled and self.ttylogOpen: ttylog.ttylog_close(self.ttylogFile, time.time()) self.ttylogOpen = False shasum = ttylog.ttylog_inputhash(self.ttylogFile) shasumfile = os.path.join(self.ttylogPath, shasum) if os.path.exists(shasumfile): duplicate = True os.remove(self.ttylogFile) else: duplicate = False os.rename(self.ttylogFile, shasumfile) umask = os.umask(0) os.umask(umask) os.chmod(shasumfile, 0o666 & ~umask) log.msg( eventid='cowrie.log.closed', format='Closing TTY Log: %(ttylog)s after %(duration)d seconds', ttylog=shasumfile, size=self.ttylogSize, shasum=shasum, duplicate=duplicate, duration=time.time() - self.startTime) insults.ServerProtocol.connectionLost(self, reason)
def __init__(self): """ """ self.format = CONFIG.get('output_textlog', 'format') self.outfile = open(CONFIG.get('output_textlog', 'logfile'), 'a') cowrie.core.output.Output.__init__(self)
def __init__(self): self.userdb = OrderedDict() self.userdb_file = '{}/userdb.txt'.format( CONFIG.get('honeypot', 'data_path')) self.load()