def __init__(self, username: bytes, server: server.CowrieServer) -> None: avatar.ConchUser.__init__(self) self.username: str = username.decode("utf-8") self.server = server self.channelLookup[b"session"] = sshsession.HoneyPotSSHSession self.temporary: bool try: pwentry = pwd.Passwd().getpwnam(self.username) self.temporary = False except KeyError: pwentry = pwd.Passwd().setpwentry(self.username) self.temporary = True self.uid = pwentry["pw_uid"] self.gid = pwentry["pw_gid"] self.home = pwentry["pw_dir"] # SFTP support enabled only when option is explicitly set if CowrieConfig.getboolean("ssh", "sftp_enabled", fallback=False): self.subsystemLookup[b"sftp"] = conchfiletransfer.FileTransferServer # SSH forwarding disabled only when option is explicitly set if CowrieConfig.getboolean("ssh", "forwarding", fallback=True): self.channelLookup[ b"direct-tcpip" ] = forwarding.cowrieOpenConnectForwardingClient
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 # buffer self.backend_buffer = [] # 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 = "{}/telnet-{}.log".format( self.ttylogPath, time.strftime("%Y%m%d-%H%M%S")) ttylog.ttylog_open(self.ttylogFile, self.startTime)
def __init__(self, factory): self.factory = factory 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) if self.use_nat: self.nat_public_ip = CowrieConfig.get("backend_pool", "nat_public_ip")
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, factory: PoolServerFactory) -> None: self.factory: PoolServerFactory = factory self.local_pool: bool = (CowrieConfig.get("proxy", "pool", fallback="local") == "local") self.pool_only: bool = CowrieConfig.getboolean("backend_pool", "pool_only", fallback=False) self.use_nat: bool = CowrieConfig.getboolean("backend_pool", "use_nat", fallback=True) if self.use_nat: self.nat_public_ip: str = CowrieConfig.get("backend_pool", "nat_public_ip")
def start(self): self.api_url = CowrieConfig.get( "output_threatjammer", "api_url", fallback=THREATJAMMER_REPORT_URL, ) self.default_ttl = CowrieConfig.getint( "output_threatjammer", "ttl", fallback=THREATJAMMER_DEFAULT_TTL) self.default_category = CowrieConfig.get( "output_threatjammer", "category", fallback=THREATJAMMER_DEFAULT_CATEGORY, ) self.track_login = CowrieConfig.getboolean( "output_threatjammer", "track_login", fallback=THREATJAMMER_DEFAULT_TRACK_LOGIN, ) self.track_session = CowrieConfig.getboolean( "output_threatjammer", "track_session", fallback=THREATJAMMER_DEFAULT_TRACK_SESSION, ) self.bearer_token = CowrieConfig.get("output_threatjammer", "bearer_token") self.tags = CowrieConfig.get("output_threatjammer", "tags").split(",") self.last_report: int = -1 self.report_bucket: int = BUFFER_FLUSH_MAX_SIZE self.ip_set: Set[str] = set() self.track_events = [] if self.track_login: self.track_events.append("cowrie.login") if self.track_session: self.track_events.append("cowrie.session") self.http_client = HTTPClient(self.api_url, self.bearer_token) log.msg( eventid="cowrie.threatjammer.reporterinitialized", format="ThreatJammer.com output plugin successfully initialized.\ Category=%(category)s. TTL=%(ttl)s. Session Tracking=%(session_tracking)s. Login Tracking=%(login_tracking)s", category=self.default_category, ttl=self.default_ttl, session_tracking=self.track_session, login_tracking=self.track_login, )
def start(self): self.bucket = CowrieConfig.get("output_s3", "bucket") self.seen = set() self.session = get_session() try: if CowrieConfig.get("output_s3", "access_key_id") and CowrieConfig.get( "output_s3", "secret_access_key"): self.session.set_credentials( CowrieConfig.get("output_s3", "access_key_id"), CowrieConfig.get("output_s3", "secret_access_key"), ) except NoOptionError: log.msg( "No AWS credentials found in config - using botocore global settings." ) self.client = self.session.create_client( "s3", region_name=CowrieConfig.get("output_s3", "region"), endpoint_url=CowrieConfig.get("output_s3", "endpoint", fallback=None), verify=CowrieConfig.getboolean("output_s3", "verify", fallback=True), )
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 __init__(self, uuid, channelName, ssh, channelId, command): super().__init__(uuid, channelName, ssh) try: log.msg( eventid="cowrie.command.input", input=command.decode("utf8"), format="CMD: %(input)s", ) except UnicodeDecodeError: log.err("Unusual execcmd: {}".format(repr(command))) self.transportId = ssh.server.transportId self.channelId = channelId self.startTime: float = time.time() self.ttylogPath: str = CowrieConfig.get("honeypot", "ttylog_path") self.ttylogEnabled: bool = CowrieConfig.getboolean("honeypot", "ttylog", fallback=True) self.ttylogSize: bool = 0 if self.ttylogEnabled: self.ttylogFile = "{}/{}-{}-{}e.log".format( self.ttylogPath, time.strftime("%Y%m%d-%H%M%S"), self.transportId, self.channelId, ) ttylog.ttylog_open(self.ttylogFile, self.startTime)
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 pool_ready(self) -> None: backend: str = CowrieConfig.get("honeypot", "backend", fallback="shell") # this method is never called if self.pool_only is False, # since we do not start the pool handler that would call it if self.enableSSH: factory = cowrie.ssh.factory.CowrieSSHFactory(backend, self.pool_handler) factory.tac = self # type: ignore factory.portal = portal.Portal(core.realm.HoneyPotRealm()) factory.portal.registerChecker(core.checkers.HoneypotPublicKeyChecker()) factory.portal.registerChecker(core.checkers.HoneypotPasswordChecker()) if CowrieConfig.getboolean("ssh", "auth_none_enabled", fallback=False): factory.portal.registerChecker(core.checkers.HoneypotNoneChecker()) if CowrieConfig.has_section("ssh"): listen_endpoints = get_endpoints_from_section(CowrieConfig, "ssh", 2222) else: listen_endpoints = get_endpoints_from_section( CowrieConfig, "honeypot", 2222 ) create_endpoint_services( reactor, self.topService, listen_endpoints, factory ) if self.enableTelnet: f = cowrie.telnet.factory.HoneyPotTelnetFactory(backend, self.pool_handler) f.tac = self # type: ignore f.portal = portal.Portal(core.realm.HoneyPotRealm()) f.portal.registerChecker(core.checkers.HoneypotPasswordChecker()) listen_endpoints = get_endpoints_from_section(CowrieConfig, "telnet", 2223) create_endpoint_services(reactor, self.topService, listen_endpoints, f)
def __init__(self, uuid, channelName, ssh, channelId, command): super().__init__(uuid, channelName, ssh) log.msg( eventid="cowrie.command.input", input=command.decode("ascii"), format="CMD: %(input)s", ) self.transportId = ssh.server.transportId self.channelId = channelId 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 = "{}/{}-{}-{}e.log".format( self.ttylogPath, time.strftime("%Y%m%d-%H%M%S"), self.transportId, self.channelId, ) ttylog.ttylog_open(self.ttylogFile, self.startTime)
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 start(self): self.auth_key = CowrieConfig.get("output_dshield", "auth_key") self.userid = CowrieConfig.get("output_dshield", "userid") self.batch_size = CowrieConfig.getint("output_dshield", "batch_size") self.debug = CowrieConfig.getboolean("output_dshield", "debug", fallback=False) self.batch = [] # This is used to store login attempts in batches
def start(self): """ Start output plugin """ self.url_base = CowrieConfig.get("output_cuckoo", "url_base").encode("utf-8") self.api_user = CowrieConfig.get("output_cuckoo", "user") self.api_passwd = CowrieConfig.get("output_cuckoo", "passwd", raw=True) self.cuckoo_force = int(CowrieConfig.getboolean("output_cuckoo", "force"))
def __init__(self, nat_service): self.qemu = backend_pool.libvirt.backend_service.LibvirtBackendService( ) self.nat_service = nat_service self.guests = [] self.guest_id: int = 0 self.guest_lock = Lock() # time in seconds between each loop iteration self.loop_sleep_time: int = 5 self.loop_next_call = None # default configs; custom values will come from the client when they connect to the pool self.max_vm: int = 2 self.vm_unused_timeout: int = 600 self.share_guests: bool = True # file configs self.ssh_port: int = CowrieConfig.getint("backend_pool", "guest_ssh_port", fallback=-1) self.telnet_port: int = CowrieConfig.getint("backend_pool", "guest_telnet_port", fallback=-1) self.local_pool: str = (CowrieConfig.get("proxy", "pool", fallback="local") == "local") self.pool_only: bool = CowrieConfig.getboolean("backend_pool", "pool_only", fallback=False) self.use_nat: bool = 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: bool = False # TODO fix for no VM available
def start(self): log.msg("Early version of hpfeeds-output, untested!") server = CowrieConfig.get("output_hpfeeds", "server") port = CowrieConfig.getint("output_hpfeeds", "port") ident = CowrieConfig.get("output_hpfeeds", "identifier") secret = CowrieConfig.get("output_hpfeeds", "secret") debug = CowrieConfig.getboolean("output_hpfeeds", "debug") self.client = hpclient(server, port, ident, secret, debug) self.meta = {}
def start(self): self.epoch_timestamp = CowrieConfig.getboolean("output_jsonlog", "epoch_timestamp", fallback=False) fn = CowrieConfig.get("output_jsonlog", "logfile") dirs = os.path.dirname(fn) base = os.path.basename(fn) self.outfile = cowrie.python.logfile.CowrieDailyLogFile( base, dirs, defaultMode=0o664)
def start(self): """ Start output plugin """ self.apiKey = CowrieConfig.get("output_cowrie", "api_key", fallback=None) self.debug = CowrieConfig.getboolean("output_cowrie", "debug", 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 run(self, application, jidstr, password, muc, server): self.xmppclient = XMPPClient(JID(jidstr), password) if CowrieConfig.getboolean("output_xmpp", "debug", fallback=False): self.xmppclient.logTraffic = True (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 start(self): """ Start the output module. Note that csirtsdk is imported here because it reads CSIRTG_TOKEN on import Cowrie sets this environment variable. """ self.user = CowrieConfig.get("output_csirtg", "username") self.feed = CowrieConfig.get("output_csirtg", "feed") self.debug = CowrieConfig.getboolean("output_csirtg", "debug", fallback=False) self.description = CowrieConfig.get("output_csirtg", "description") self.context = {}
def serviceStarted(self) -> None: self.interfaceToMethod[credentials.IUsername] = b"none" self.interfaceToMethod[credentials.IUsernamePasswordIP] = b"password" keyboard: bool = CowrieConfig.getboolean( "ssh", "auth_keyboard_interactive_enabled", fallback=False) if keyboard is True: self.interfaceToMethod[ credentials. IPluggableAuthenticationModulesIP] = b"keyboard-interactive" self.bannerSent: bool = False self._pamDeferred: Optional[defer.Deferred] = None userauth.SSHUserAuthServer.serviceStarted(self)
def send_initialisation(self): """ Used only by the PoolHandler on the first connection, to set the pool up. """ max_vms = CowrieConfig.getint("proxy", "pool_max_vms", fallback=2) vm_unused_timeout = CowrieConfig.getint( "proxy", "pool_vm_unused_timeout", fallback=600 ) share_guests = CowrieConfig.getboolean( "proxy", "pool_share_guests", fallback=True ) buf = struct.pack("!cII?", b"i", max_vms, vm_unused_timeout, share_guests) self.transport.write(buf)
def start(self): """ Start output plugin """ self.apiKey = CowrieConfig.get("output_virustotal", "api_key") self.debug = CowrieConfig.getboolean( "output_virustotal", "debug", fallback=False ) self.upload = CowrieConfig.getboolean( "output_virustotal", "upload", fallback=True ) self.comment = CowrieConfig.getboolean( "output_virustotal", "comment", fallback=True ) self.scan_file = CowrieConfig.getboolean( "output_virustotal", "scan_file", fallback=True ) self.scan_url = CowrieConfig.getboolean( "output_virustotal", "scan_url", fallback=False ) self.commenttext = CowrieConfig.get( "output_virustotal", "commenttext", fallback=COMMENT ) self.agent = client.Agent(reactor, WebClientContextFactory())
def start(self): self.debug = CowrieConfig.getboolean("output_mysql", "debug", fallback=False) port = CowrieConfig.getint("output_mysql", "port", fallback=3306) try: self.db = ReconnectingConnectionPool( "MySQLdb", host=CowrieConfig.get("output_mysql", "host"), db=CowrieConfig.get("output_mysql", "database"), user=CowrieConfig.get("output_mysql", "username"), passwd=CowrieConfig.get("output_mysql", "password", raw=True), port=port, cp_min=1, cp_max=1, charset="utf8mb4", cp_reconnect=True, use_unicode=True, ) except (MySQLdb.Error, MySQLdb._exceptions.Error) as e: log.msg("output_mysql: Error %d: %s" % (e.args[0], e.args[1]))
def destroy_guest(self, domain, snapshot): if not self.ready: return try: # destroy the domain in qemu domain.destroy() # we want to remove the snapshot if either: # - explicitely set save_snapshots to False # - no snapshot dir was defined (using cowrie's root dir) - should not happen but prevent it if ((not CowrieConfig.getboolean( "backend_pool", "save_snapshots", fallback=True) or CowrieConfig.get( "backend_pool", "snapshot_path", fallback=None) is None) and os.path.exists(snapshot) and os.path.isfile(snapshot)): os.remove(snapshot) # destroy its disk snapshot except Exception as error: log.err( eventid="cowrie.backend_pool.qemu", format="Error destroying guest: %(error)s", error=error, )
def __init__(self, uuid, chan_name, ssh, channelId): super().__init__(uuid, chan_name, ssh) self.command = b"" self.pointer = 0 self.tabPress = False self.upArrow = False self.transportId = ssh.server.transportId self.channelId = channelId 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 = "{}/{}-{}-{}i.log".format( self.ttylogPath, time.strftime("%Y%m%d-%H%M%S"), uuid, self.channelId) ttylog.ttylog_open(self.ttylogFile, self.startTime)
def start(self): self.debug = CowrieConfig.getboolean("output_mysql", "debug", fallback=False) port = CowrieConfig.getint("output_mysql", "port", fallback=3306) try: self.db = ReconnectingConnectionPool( "mysql.connector", host=CowrieConfig.get("output_mysql", "host"), db=CowrieConfig.get("output_mysql", "database"), user=CowrieConfig.get("output_mysql", "username"), passwd=CowrieConfig.get("output_mysql", "password", raw=True), port=port, cp_min=1, cp_max=1, charset="utf8mb4", cp_reconnect=True, use_unicode=True, ) # except (MySQLdb.Error, MySQLdb._exceptions.Error) as e: except Exception as e: log.msg(f"output_mysql: Error {e.args[0]}: {e.args[1]}") self.lc = LoopingCall(self.check_wait) self.lc.start(30) self.versions = {}
class CowrieSSHChannel(channel.SSHChannel): """ This is an SSH channel with built-in logging """ ttylogEnabled = True ttylogFile = "" bytesReceived = 0 bytesReceivedLimit = 0 bytesWritten = 0 name = b"cowrie-ssh-channel" startTime: float = 0.0 ttylogPath = CowrieConfig.get("honeypot", "log_path") downloadPath = CowrieConfig.get("honeypot", "download_path") ttylogEnabled = CowrieConfig.getboolean("honeypot", "ttylog", fallback=True) bytesReceivedLimit = CowrieConfig.getint("honeypot", "download_limit_size", fallback=0) def __repr__(self): """ Return a pretty representation of this object. @return Pretty representation of this object as a string @rtype: L{str} """ return f"Cowrie SSH Channel {self.name}" def __init__(self, *args, **kw): """ Initialize logging """ channel.SSHChannel.__init__(self, *args, **kw) def channelOpen(self, specificData): self.startTime = time.time() self.ttylogFile = "{}/tty/{}-{}-{}.log".format( self.ttylogPath, time.strftime("%Y%m%d-%H%M%S"), self.conn.transport.transportId, self.id, ) log.msg( eventid="cowrie.log.open", ttylog=self.ttylogFile, format="Opening TTY Log: %(ttylog)s", ) ttylog.ttylog_open(self.ttylogFile, time.time()) channel.SSHChannel.channelOpen(self, specificData) def closed(self): log.msg( eventid="cowrie.log.closed", format="Closing TTY Log: %(ttylog)s after %(duration)f seconds", ttylog=self.ttylogFile, size=self.bytesReceived + self.bytesWritten, duration=time.time() - self.startTime, ) ttylog.ttylog_close(self.ttylogFile, time.time()) channel.SSHChannel.closed(self) def dataReceived(self, data): """ Called when we receive data from the user @type data: L{bytes} @param data: Data sent to the server from the client """ self.bytesReceived += len(data) if self.bytesReceivedLimit and self.bytesReceived > self.bytesReceivedLimit: log.msg(f"Data upload limit reached for channel {self.id}") self.eofReceived() return if self.ttylogEnabled: ttylog.ttylog_write(self.ttylogFile, len(data), ttylog.TYPE_INPUT, time.time(), data) channel.SSHChannel.dataReceived(self, data) def write(self, data): """ Called when we send data to the user @type data: L{bytes} @param data: Data sent to the client from the server """ if self.ttylogEnabled: ttylog.ttylog_write(self.ttylogFile, len(data), ttylog.TYPE_OUTPUT, time.time(), data) self.bytesWritten += len(data) channel.SSHChannel.write(self, data)