def start(self): log.msg( "WARNING: Beta version of new hpfeeds enabled. This will become hpfeeds in a future release." ) if CowrieConfig.has_option("output_hpfeeds3", "channel"): self.channel = CowrieConfig.get("output_hpfeeds3", "channel") if CowrieConfig.has_option("output_hpfeeds3", "endpoint"): endpoint = CowrieConfig.get("output_hpfeeds3", "endpoint") else: server = CowrieConfig.get("output_hpfeeds3", "server") port = CowrieConfig.getint("output_hpfeeds3", "port") if CowrieConfig.has_option("output_hpfeeds3", "tlscert"): with open(CowrieConfig.get("output_hpfeeds3", "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 = CowrieConfig.get("output_hpfeeds3", "identifier") secret = CowrieConfig.get("output_hpfeeds3", "secret") self.meta = {} self.client = ClientSessionService(endpoint, ident, secret) self.client.startService()
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 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 connectionMade(self): pt = self.getProtoTransport() self.sessionno = pt.transport.sessionno 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) timeout = CowrieConfig.getint("honeypot", "interactive_timeout", fallback=180) self.setTimeout(timeout) # Source IP of client in user visible reports (can be fake or real) try: self.clientIP = CowrieConfig.get("honeypot", "fake_addr") except Exception: self.clientIP = self.realClientIP # Source IP of server in user visible reports (can be fake or real) if CowrieConfig.has_option("honeypot", "internet_facing_ip"): self.kippoIP = CowrieConfig.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 CowrieConfig.has_option("honeypot", "auth_class"): authclass = CowrieConfig.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(f"auth_class: {authclass} not found in {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 showPrompt(self) -> None: if not self.interactive: return prompt = "" if CowrieConfig.has_option("honeypot", "prompt"): prompt = CowrieConfig.get("honeypot", "prompt") prompt += " " else: cwd = self.protocol.cwd homelen = len(self.protocol.user.avatar.home) if cwd == self.protocol.user.avatar.home: cwd = "~" elif (len(cwd) > (homelen + 1) and cwd[:(homelen + 1)] == self.protocol.user.avatar.home + "/"): cwd = "~" + cwd[homelen:] # Example: [root@svr03 ~]# (More of a "CentOS" feel) # Example: root@svr03:~# (More of a "Debian" feel) prompt = f"{self.protocol.user.username}@{self.protocol.hostname}:{cwd}" if not self.protocol.user.uid: prompt += "# " # "Root" user else: prompt += "$ " # "Non-Root" user self.protocol.terminal.write(prompt.encode("ascii")) self.protocol.ps = (prompt.encode("ascii"), b"> ")
def download(self, url, fakeoutfile, *args, **kwargs): """ url - URL to download fakeoutfile - file in guest's fs that attacker wants content to be downloaded to """ 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(f"{url}: Unsupported scheme.\n") return None # File in host's fs that will hold content of the downloaded file # HTTPDownloader will close() the file object so need to preserve the name self.artifactFile = Artifact(self.outfile) if not self.quiet: self.errorWrite("--{}-- {}\n".format( 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, self.artifactFile, *args, **kwargs) out_addr = None if CowrieConfig.has_option("honeypot", "out_addr"): out_addr = (CowrieConfig.get("honeypot", "out_addr"), 0) if scheme == b"https": context_factory = ssl.optionsForClientTLS(hostname=host) self.connection = reactor.connectSSL(host, port, factory, context_factory, 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): 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): # Default values self.mintry, self.maxtry, self.maxcache = 2, 5, 10 # Are there auth_class parameters? if CowrieConfig.has_option("honeypot", "auth_class_parameters"): parameters = CowrieConfig.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(f"maxtry < mintry, adjusting maxtry to: {self.maxtry}") self.uservar = {} self.uservar_file = "{}/auth_random.json".format( CowrieConfig.get("honeypot", "state_path") ) self.loadvars()
def ftp_download(self): out_addr = ("", 0) if CowrieConfig.has_option("honeypot", "out_addr"): out_addr = (CowrieConfig.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={}, port={}, err={}".format( 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={}, passwd={}, err={}".format( 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 start(self): host = CowrieConfig.get("output_influx", "host", fallback="") port = CowrieConfig.getint("output_influx", "port", fallback=8086) ssl = CowrieConfig.getboolean("output_influx", "ssl", fallback=False) self.client = None try: self.client = InfluxDBClient(host=host, port=port, ssl=ssl, verify_ssl=ssl) except InfluxDBClientError as e: log.msg(f"output_influx: I/O error({e.code}): '{e.message}'") return if self.client is None: log.msg("output_influx: cannot instantiate client!") return if CowrieConfig.has_option("output_influx", "username") and CowrieConfig.has_option( "output_influx", "password"): username = CowrieConfig.get("output_influx", "username") password = CowrieConfig.get("output_influx", "password", raw=True) self.client.switch_user(username, password) try: dbname = CowrieConfig.get("output_influx", "database_name") except Exception: dbname = "cowrie" retention_policy_duration_default = "12w" retention_policy_name = dbname + "_retention_policy" if CowrieConfig.has_option("output_influx", "retention_policy_duration"): retention_policy_duration = CowrieConfig.get( "output_influx", "retention_policy_duration") match = re.search(r"^\d+[dhmw]{1}$", retention_policy_duration) if not match: log.msg( ("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)