def start(self): """ Start Output Plugin """ self.timeout = [ CowrieConfig().getint('output_reversedns', 'timeout', fallback=3) ]
def sendBackend(self, data): self.backend_buffer.append(data) if not self.client: return for packet in self.backend_buffer: self.client.transport.write(packet) # log raw packets if user sets so if CowrieConfig.getboolean("proxy", "log_raw", fallback=False): log.msg(b"to_backend - " + data) if self.ttylogEnabled and self.authStarted: cleanData = data.replace( b"\x00", b"\n") # some frontends send 0xFF instead of newline ttylog.ttylog_write( self.ttylogFile, len(cleanData), ttylog.TYPE_INPUT, time.time(), cleanData, ) self.ttylogSize += len(cleanData) self.backend_buffer = self.backend_buffer[1:]
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 # this can come from backend in the future, check HonSSH's slim client self.ourVersionString = CowrieConfig().get( 'ssh', 'version', fallback='SSH-2.0-OpenSSH_6.0p1 Debian-4+deb7u2') factory.SSHFactory.startFactory(self) log.msg("Ready to accept SSH connections")
def __build_dict(self): configs = { **self.__get_defaults(), **CowrieConfig()['output_abuseipdb'], 'doge_dump': join(self.plugin_path, DOGE_DUMP) } return configs
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( CowrieConfig().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) -> None: self.sessions: Dict[str, str] = {} self.ips: Dict[str, str] = {} # Need these for each individual transport, or else the session numbers overlap self.sshRegex: Pattern[str] = re.compile( ".*SSHTransport,([0-9]+),[0-9a-f:.]+$") self.telnetRegex: Pattern[str] = re.compile( ".*TelnetTransport,([0-9]+),[0-9a-f:.]+$") self.sensor: str = CowrieConfig.get("honeypot", "sensor_name", fallback=socket.gethostname()) self.timeFormat: str # use Z for UTC (Zulu) time, it's shorter. if "TZ" in environ and environ["TZ"] == "UTC": self.timeFormat = "%Y-%m-%dT%H:%M:%S.%fZ" else: self.timeFormat = "%Y-%m-%dT%H:%M:%S.%f%z" # Event trigger so that stop() is called by the reactor when stopping reactor.addSystemEventTrigger("before", "shutdown", self.stop) # type: ignore self.start()
def start(self): """ Start Output Plugin """ self.timeout = [ CowrieConfig.getint("output_reversedns", "timeout", fallback=3) ]
def __init__(self, tolerance_attempts, state_dump): self.sleeping = False self.sleep_until = 0 self.tolerance_attempts = tolerance_attempts self.tolerance_window = 60 * CowrieConfig.getint( "output_abuseipdb", "tolerance_window", fallback=120) self.rereport_after = 3600 * CowrieConfig.getfloat( "output_abuseipdb", "rereport_after", fallback=24) if self.rereport_after < REREPORT_MINIMUM: self.rereport_after = REREPORT_MINIMUM self.state_dump = state_dump # To write our dump to disk we have a method we call in a thread so we # don't block if we get slow io. This is a cheap hack to get a lock on # the file. See self.write_dump_file() self._writing = False super().__init__()
def requestAvatar(self, avatarId, mind, *interfaces): backend = CowrieConfig().get('honeypot', 'backend', fallback='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 start(self): """ Start output plugin """ misp_url = CowrieConfig.get("output_misp", "base_url") misp_key = CowrieConfig.get("output_misp", "api_key") misp_verifycert = ( "true" == CowrieConfig.get("output_misp", "verify_cert").lower() ) self.misp_api = PyMISP( url=misp_url, key=misp_key, ssl=misp_verifycert, debug=False ) self.debug = CowrieConfig.getboolean("output_misp", "debug", fallback=False) self.publish = CowrieConfig.getboolean( "output_misp", "publish_event", fallback=False )
def backend_connection_success(self, backendTransport): log.msg("Connected to honeypot backend") self.startTime = time.time() self.setTimeout(CowrieConfig().getint('honeypot', 'authentication_timeout', fallback=120))
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 [ f"{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( CowrieConfig.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(f"Can't find command {cmd}") return None
def connectionMade(self): """ Called when the connection is made to the other side. We sent our version and the MSG_KEXINIT packet. """ self.sshParse = ssh.SSH(self) self.transportId = uuid.uuid4().hex[:12] self.peer_ip = self.transport.getPeer().host self.peer_port = self.transport.getPeer().port + 1 self.local_ip = self.transport.getHost().host self.local_port = self.transport.getHost().port self.transport.write(f'{self.ourVersionString}\r\n'.encode()) self.currentEncryptions = transport.SSHCiphers(b'none', b'none', b'none', b'none') self.currentEncryptions.setKeys(b'', b'', b'', b'', b'', b'') self.otherVersionString = 'Unknown' log.msg( eventid='cowrie.session.connect', format= "New connection: %(src_ip)s:%(src_port)s (%(dst_ip)s:%(dst_port)s) [session: %(session)s]", src_ip=self.peer_ip, src_port=self.transport.getPeer().port, dst_ip=self.local_ip, dst_port=self.transport.getHost().port, session=self.transportId, sessionno=f'S{self.transport.sessionno}', protocol='ssh') # if we have a pool connect to it and later request a backend, else just connect to a simple backend # when pool is set we can just test self.pool_interface to the same effect of getting the CowrieConfig proxy_backend = CowrieConfig().get('proxy', 'backend', fallback='simple') if proxy_backend == 'pool': # request a backend d = self.factory.pool_handler.request_interface() d.addCallback(self.pool_connection_success) d.addErrback(self.pool_connection_error) else: # simply a proxy, no pool backend_ip = CowrieConfig().get('proxy', 'backend_ssh_host') backend_port = CowrieConfig().getint('proxy', 'backend_ssh_port') self.connect_to_backend(backend_ip, backend_port)
def start(self): host = CowrieConfig.get("output_elasticsearch", "host") port = CowrieConfig.get("output_elasticsearch", "port") self.index = CowrieConfig.get("output_elasticsearch", "index") self.type = CowrieConfig.get("output_elasticsearch", "type") self.pipeline = CowrieConfig.get("output_elasticsearch", "pipeline") # new options (creds + https) username = CowrieConfig.get("output_elasticsearch", "username", fallback=None) password = CowrieConfig.get("output_elasticsearch", "password", fallback=None) use_ssl = CowrieConfig.getboolean("output_elasticsearch", "ssl", fallback=False) ca_certs = CowrieConfig.get("output_elasticsearch", "ca_certs", fallback=None) verify_certs = CowrieConfig.getboolean("output_elasticsearch", "verify_certs", fallback=True) options: dict[str, Any] = {} # connect if (username is not None) and (password is not None): options["http_auth"] = (username, password) if use_ssl: options["scheme"] = "https" options["use_ssl"] = use_ssl options["ssl_show_warn"] = False options["verify_certs"] = verify_certs if verify_certs: options["ca_certs"] = ca_certs # connect self.es = Elasticsearch(f"{host}:{port}", **options) # self.es = Elasticsearch('{0}:{1}'.format(self.host, self.port)) self.check_index() # ensure geoip pipeline is well set up if self.pipeline == "geoip": # create a new feature if it does not exist yet self.check_geoip_mapping() # ensure the geoip pipeline is setup self.check_geoip_pipeline()
def __init__(self, server): # holds packet data; useful to manipulate it across functions as needed self.currentData = None self.sendData = True # front and backend references self.server = server self.client = None # definitions from config self.spoofAuthenticationData = CowrieConfig().getboolean( 'proxy', 'telnet_spoof_authentication') self.backendLogin = CowrieConfig().get('proxy', 'backend_user').encode() self.backendPassword = CowrieConfig().get('proxy', 'backend_pass').encode() self.usernameInNegotiationRegex = CowrieConfig().get( 'proxy', 'telnet_username_in_negotiation_regex', raw=True).encode() self.usernamePromptRegex = CowrieConfig().get( 'proxy', 'telnet_username_prompt_regex', raw=True).encode() self.passwordPromptRegex = CowrieConfig().get( 'proxy', 'telnet_password_prompt_regex', raw=True).encode() # telnet state self.currentCommand = b'' # auth state self.authStarted = False self.authDone = False self.usernameState = b'' # TODO clear on end self.inputingLogin = False self.passwordState = b'' # TODO clear on end self.inputingPassword = False self.waitingLoginEcho = False # some data is sent by the backend right before the password prompt, we want to capture that # and the respective frontend response and send it before starting to intercept auth data self.prePasswordData = False # tty logging self.startTime = time.time() self.ttylogPath = CowrieConfig().get('honeypot', 'ttylog_path') self.ttylogEnabled = CowrieConfig().getboolean('honeypot', 'ttylog', fallback=True) self.ttylogSize = 0 if self.ttylogEnabled: self.ttylogFile = '{0}/telnet-{1}.log'.format( self.ttylogPath, time.strftime('%Y%m%d-%H%M%S')) ttylog.ttylog_open(self.ttylogFile, self.startTime)
def start(self): self.host = CowrieConfig().get(RETHINK_DB_SEGMENT, 'host') self.port = CowrieConfig().getint(RETHINK_DB_SEGMENT, 'port') self.db = CowrieConfig().get(RETHINK_DB_SEGMENT, 'db') self.table = CowrieConfig().get(RETHINK_DB_SEGMENT, 'table') self.password = CowrieConfig().get(RETHINK_DB_SEGMENT, 'password', raw=True) self.connection = r.connect(host=self.host, port=self.port, db=self.db, password=self.password) try: r.db_create(self.db).run(self.connection) r.db(self.db).table_create(self.table).run(self.connection) except r.RqlRuntimeError: pass
def start(self): self.host = CowrieConfig.get(RETHINK_DB_SEGMENT, "host") self.port = CowrieConfig.getint(RETHINK_DB_SEGMENT, "port") self.db = CowrieConfig.get(RETHINK_DB_SEGMENT, "db") self.table = CowrieConfig.get(RETHINK_DB_SEGMENT, "table") self.password = CowrieConfig.get(RETHINK_DB_SEGMENT, "password", raw=True) self.connection = r.connect(host=self.host, port=self.port, db=self.db, password=self.password) try: r.db_create(self.db).run(self.connection) r.db(self.db).table_create(self.table).run(self.connection) except r.RqlRuntimeError: pass
def __init__(self) -> None: self.pool_handler = None # ssh is enabled by default self.enableSSH: bool = CowrieConfig.getboolean("ssh", "enabled", fallback=True) # telnet is disabled by default self.enableTelnet: bool = CowrieConfig.getboolean("telnet", "enabled", fallback=False) # pool is disabled by default, but need to check this setting in case user only wants to run the pool self.pool_only: bool = CowrieConfig.getboolean("backend_pool", "pool_only", fallback=False)
def __init__(self, nat_service): self.qemu = backend_pool.libvirt.backend_service.LibvirtBackendService( ) self.nat_service = nat_service self.guests = [] self.guest_id = 0 self.guest_lock = Lock() # time in seconds between each loop iteration self.loop_sleep_time = 5 self.loop_next_call = None # default configs; custom values will come from the client when they connect to the pool self.max_vm = 2 self.vm_unused_timeout = 600 self.share_guests = True # file configs self.ssh_port = CowrieConfig().getint("backend_pool", "guest_ssh_port", fallback=-1) self.telnet_port = CowrieConfig().getint("backend_pool", "guest_telnet_port", fallback=-1) self.local_pool = (CowrieConfig().get("proxy", "pool", fallback="local") == "local") self.pool_only = CowrieConfig().getboolean("backend_pool", "pool_only", fallback=False) self.use_nat = CowrieConfig().getboolean("backend_pool", "use_nat", fallback=True) # detect invalid config if not self.ssh_port > 0 and not self.telnet_port > 0: log.msg( eventid="cowrie.backend_pool.service", format= "Invalid configuration: one of SSH or Telnet ports must be defined!", ) os._exit(1) self.any_vm_up = False # TODO fix for no VM available
def __init__(self, logbook, attempts): self.logbook = logbook self.attempts = attempts self.headers = { "User-Agent": "Cowrie Honeypot AbuseIPDB plugin", "Accept": "application/json", "Key": CowrieConfig.get("output_abuseipdb", "api_key"), }
def __init__(self, logbook, attempts): self.logbook = logbook self.attempts = attempts self.headers = { 'User-Agent': 'Cowrie Honeypot AbuseIPDB plugin', 'Accept': 'application/json', 'Key': CowrieConfig().get('output_abuseipdb', 'api_key') }
def __init__(self, realm): try: arches = [arch.strip() for arch in CowrieConfig().get('shell', 'arch').split(',')] self.arch = random.choice(arches) except NoOptionError: self.arch = 'linux-x64-lsb' log.msg(f"Initialized emulated server as architecture: {self.arch}")
def __init__(self, *args, **kw): channel.CowrieSSHChannel.__init__(self, *args, **kw) keyPath = CowrieConfig().get('proxy', 'private_key') self.keys.append(keys.Key.fromFile(keyPath)) try: keyPath = CowrieConfig().get('proxy', 'private_key') self.keys.append(keys.Key.fromFile(keyPath)) except NoOptionError: self.keys = None knownHostsPath = CowrieConfig().get('proxy', 'known_hosts') self.knownHosts = KnownHostsFile.fromPath(knownHostsPath) self.host = CowrieConfig().get('proxy', 'host') self.port = CowrieConfig().getint('proxy', 'port') self.user = CowrieConfig().get('proxy', 'user') try: self.password = CowrieConfig().get('proxy', 'password') except NoOptionError: self.password = None log.msg("knownHosts = {0}".format(repr(self.knownHosts))) log.msg("host = {0}".format(self.host)) log.msg("port = {0}".format(self.port)) log.msg("user = {0}".format(self.user)) self.client = ProxyClient(self)
def download(self, url, fakeoutfile, outputfile, *args, **kwargs): scheme: bytes try: parsed = compat.urllib_parse.urlparse(url) scheme = parsed.scheme host: str = parsed.hostname.decode("utf8") port: int = parsed.port or (443 if scheme == "https" else 80) if scheme != b"http" and scheme != b"https": raise NotImplementedError except Exception: self.errorWrite( f'curl: (1) Protocol "{scheme.encode("utf8")}" not supported or disabled in libcurl\n' ) self.exit() return None # TODO: need to do full name resolution in case someon passes DNS name pointing to local address try: if ipaddress.ip_address(host).is_private: self.errorWrite( "curl: (6) Could not resolve host: {}\n".format(host)) return None except ValueError: pass factory = HTTPProgressDownloader(self, fakeoutfile, url, outputfile, *args, **kwargs) out_addr = None if CowrieConfig.has_option("honeypot", "out_addr"): out_addr = (CowrieConfig.get("honeypot", "out_addr"), 0) if scheme == "https": context_factory = ssl.optionsForClientTLS(hostname=host) self.connection = reactor.connectSSL(host, port, factory, context_factory, bindAddress=out_addr) else: # Can only be http self.connection = reactor.connectTCP(host, port, factory, bindAddress=out_addr) return factory.deferred
def __init__(self, protocol, *args): self.protocol = protocol self.args = list(args) self.environ = self.protocol.cmdstack[0].environ self.fs = self.protocol.fs self.data = None # output data self.input_data = None # used to store STDIN data passed via PIPE self.writefn = self.protocol.pp.outReceived self.errorWritefn = self.protocol.pp.errReceived # MS-DOS style redirect handling, inside the command # TODO: handle >>, 2>, etc if '>' in self.args or '>>' in self.args: self.writtenBytes = 0 self.writefn = self.write_to_file if '>>' in self.args: index = self.args.index('>>') b_append = True else: index = self.args.index('>') b_append = False self.outfile = self.fs.resolve_path(str(self.args[(index + 1)]), self.protocol.cwd) del self.args[index:] p = self.fs.getfile(self.outfile) if not p or not p[fs.A_REALFILE] or p[fs.A_REALFILE].startswith( 'honeyfs') or not b_append: tmp_fname = '%s-%s-%s-redir_%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.outfile)) self.safeoutfile = os.path.join( CowrieConfig().get('honeypot', 'download_path'), tmp_fname) perm = stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH try: self.fs.mkfile(self.outfile, 0, 0, 0, stat.S_IFREG | perm) except fs.FileNotFound: # The outfile locates at a non-existing directory. self.errorWrite('-bash: %s: No such file or directory\n' % self.outfile) self.writefn = self.write_to_failed self.outfile = None self.safeoutfile = None except fs.PermissionDenied: # The outfile locates in a file-system that doesn't allow file creation self.errorWrite('-bash: %s: Permission denied\n' % self.outfile) self.writefn = self.write_to_failed self.outfile = None self.safeoutfile = None else: with open(self.safeoutfile, 'ab'): self.fs.update_realfile(self.fs.getfile(self.outfile), self.safeoutfile) else: self.safeoutfile = p[fs.A_REALFILE]
def backend_connection_success(self, backendTransport): log.msg("Connected to honeypot backend") self.startTime = time.time() # this timeout is replaced with `interactive_timeout` in ssh.py self.setTimeout(CowrieConfig().getint("honeypot", "authentication_timeout", fallback=120))
class Artifact: artifactDir: str = CowrieConfig.get("honeypot", "download_path") def __init__(self, label: str) -> None: self.label: str = label self.fp = tempfile.NamedTemporaryFile(dir=self.artifactDir, delete=False) self.tempFilename = self.fp.name self.closed: bool = False self.shasum: str = "" self.shasumFilename: str = "" def __enter__(self) -> Any: return self.fp def __exit__( self, etype: Optional[Type[BaseException]], einst: Optional[BaseException], etrace: Optional[TracebackType], ) -> bool: self.close() return True def write(self, bytes: bytes) -> None: self.fp.write(bytes) def fileno(self) -> Any: return self.fp.fileno() def close(self, keepEmpty: bool = False) -> Optional[Tuple[str, str]]: size: int = self.fp.tell() if size == 0 and not keepEmpty: os.remove(self.fp.name) return None self.fp.seek(0) data = self.fp.read() self.fp.close() self.closed = True self.shasum = hashlib.sha256(data).hexdigest() self.shasumFilename = os.path.join(self.artifactDir, self.shasum) if os.path.exists(self.shasumFilename): log.msg("Not storing duplicate content " + self.shasum) os.remove(self.fp.name) else: os.rename(self.fp.name, self.shasumFilename) umask = os.umask(0) os.umask(umask) os.chmod(self.shasumFilename, 0o666 & ~umask) return self.shasum, self.shasumFilename
def __init__(self): self.topService = None self.pool_handler = None # ssh is enabled by default self.enableSSH = CowrieConfig().getboolean('ssh', 'enabled', fallback=True) # telnet is disabled by default self.enableTelnet = CowrieConfig().getboolean('telnet', 'enabled', fallback=False) # pool is disabled by default, but need to check this setting in case user only wants to run the pool self.pool_only = CowrieConfig().getboolean('backend_pool', 'pool_only', fallback=False)
def sendFrontend(self, data): self.server.transport.write(data) # log raw packets if user sets so if CowrieConfig().getboolean('proxy', 'log_raw', fallback=False): log.msg(b'to_frontend - ' + data) if self.ttylogEnabled and self.authStarted: ttylog.ttylog_write(self.ttylogFile, len(data), ttylog.TYPE_OUTPUT, time.time(), data)
def __init__(self): log.msg("Early version of hpfeeds-output, untested!") try: self.tags = [tag.strip() for tag in CowrieConfig().get('output_hpfeeds', 'tags').split(',')] except Exception as e: self.tags = [] cowrie.core.output.Output.__init__(self)