def makeTftpRetrieval(self): """ """ progresshook = Progress(self).progresshook if CONFIG.has_option('honeypot', 'download_limit_size'): self.limit_size = CONFIG.getint('honeypot', 'download_limit_size') self.artifactFile = Artifact(self.file_to_get) tclient = None url = '' try: tclient = tftpy.TftpClient(self.hostname, int(self.port)) # tftpy can't handle unicode string as filename # so we have to convert unicode type to str type tclient.download(str(self.file_to_get), self.artifactFile, progresshook) url = 'tftp://%s/%s' % (self.hostname, self.file_to_get.strip('/')) self.file_to_get = self.fs.resolve_path(self.file_to_get, self.protocol.cwd) if hasattr(tclient.context, 'metrics'): self.fs.mkfile(self.file_to_get, 0, 0, tclient.context.metrics.bytes, 33188) else: self.fs.mkfile(self.file_to_get, 0, 0, 0, 33188) except tftpy.TftpException: if tclient and tclient.context and not tclient.context.fileobj.closed: tclient.context.fileobj.close() if url: # log to cowrie.log log.msg( format= 'Downloaded URL (%(url)s) with SHA-256 %(shasum)s to %(outfile)s', url=url, outfile=self.artifactFile.shasumFilename, shasum=self.artifactFile.shasum) self.protocol.logDispatch( eventid='cowrie.session.file_download', format= 'Downloaded URL (%(url)s) with SHA-256 %(shasum)s to %(outfile)s', url=url, outfile=self.artifactFile.shasumFilename, shasum=self.artifactFile.shasum, destfile=self.file_to_get) # Update the honeyfs to point to downloaded file self.fs.update_realfile(self.fs.getfile(self.file_to_get), self.artifactFile.shasumFilename) self.fs.chown(self.file_to_get, self.protocol.user.uid, self.protocol.user.gid)
def makeTftpRetrieval(self): progresshook = Progress(self).progresshook self.artifactFile = Artifact(self.file_to_get) tclient = None url = "" try: tclient = tftpy.TftpClient(self.hostname, int(self.port)) # tftpy can't handle unicode string as filename # so we have to convert unicode type to str type tclient.download(str(self.file_to_get), self.artifactFile, progresshook) url = "tftp://{}/{}".format(self.hostname, self.file_to_get.strip("/")) self.file_to_get = self.fs.resolve_path(self.file_to_get, self.protocol.cwd) if hasattr(tclient.context, "metrics"): self.fs.mkfile(self.file_to_get, 0, 0, tclient.context.metrics.bytes, 33188) else: self.fs.mkfile(self.file_to_get, 0, 0, 0, 33188) except tftpy.TftpException: if tclient and tclient.context and not tclient.context.fileobj.closed: tclient.context.fileobj.close() if url: # log to cowrie.log log.msg( format= "Downloaded URL (%(url)s) with SHA-256 %(shasum)s to %(outfile)s", url=url, outfile=self.artifactFile.shasumFilename, shasum=self.artifactFile.shasum, ) self.protocol.logDispatch( eventid="cowrie.session.file_download", format= "Downloaded URL (%(url)s) with SHA-256 %(shasum)s to %(outfile)s", url=url, outfile=self.artifactFile.shasumFilename, shasum=self.artifactFile.shasum, destfile=self.file_to_get, ) # Update the honeyfs to point to downloaded file self.fs.update_realfile(self.fs.getfile(self.file_to_get), self.artifactFile.shasumFilename) self.fs.chown(self.file_to_get, self.protocol.user.uid, self.protocol.user.gid)
def 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('%s: Unsupported scheme.\n' % (url, )) 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( '--%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, 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 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()
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.protocol.logDispatch(eventid='cowrie.session.file_download', format='Downloaded URL (%(url)s)', url=self.url) self.exit() return 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(f"curl: {err}\n") 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.write(CURL_HELP) self.exit() 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.artifactFile = Artifact(outfile) # HTTPDownloader will close() the file object so need to preserve the name self.deferred = self.download(url, outfile, self.artifactFile) if self.deferred: self.deferred.addCallback(self.success, outfile) self.deferred.addErrback(self.error, url)
def start(self): try: optlist, args = getopt.getopt(self.args, "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.url_log = "ftp://" if self.username: self.url_log = f"{self.url_log}{self.username}" if self.password: self.url_log = f"{self.url_log}:{self.password}" self.url_log = f"{self.url_log}@" self.url_log = f"{self.url_log}{self.host}" if self.port != 21: self.url_log = f"{self.url_log}:{self.port}" self.url_log = f"{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()
def start(self) -> None: 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(f"curl: {err}\n") 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.write(CURL_HELP) self.exit() 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) for opt in optlist: if opt[0] == "-o": self.outfile = opt[1] if opt[0] == "-O": self.outfile = urldata.path.split("/")[-1] if ( self.outfile is None or not len(self.outfile.strip()) or not urldata.path.count("/") ): self.write("curl: Remote file name has no length!\n") self.exit() return if self.outfile: self.outfile = self.fs.resolve_path(self.outfile, self.protocol.cwd) if self.outfile: path = os.path.dirname(self.outfile) if not path or not self.fs.exists(path) or not self.fs.isdir(path): self.write( f"curl: {self.outfile}: Cannot open: No such file or directory\n" ) self.exit() return self.url = url.encode("ascii") parsed = compat.urllib_parse.urlparse(url) if parsed.hostname: self.host = parsed.hostname if parsed.scheme: scheme = parsed.scheme # port: int = parsed.port or (443 if scheme == "https" else 80) if scheme != "http" and scheme != "https": self.errorWrite( f'curl: (1) Protocol "{scheme}" not supported or disabled in libcurl\n' ) self.exit() return # TODO: need to do full name resolution in case someon passes DNS name pointing to local address try: if ipaddress.ip_address(self.host).is_private: self.errorWrite(f"curl: (6) Could not resolve host: {self.host}\n") self.exit() return None except ValueError: pass self.artifact = Artifact("curl-download") self.deferred = self.treqDownload(url) if self.deferred: self.deferred.addCallback(self.success) self.deferred.addErrback(self.error)
def start(self): url: str 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 self.outfile: str = None self.quiet = False for opt in optlist: if opt[0] == "-O": self.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 self.outfile: if "-O" in args: self.outfile = args[args.index("-O") + 1] except Exception: pass if "://" not in url: url = f"http://{url}" urldata = compat.urllib_parse.urlparse(url) self.host = urldata.hostname # TODO: need to do full name resolution in case someon passes DNS name pointing to local address try: if ipaddress.ip_address(self.host).is_private: self.errorWrite( f"curl: (6) Could not resolve host: {self.host}\n") self.exit() return None except ValueError: pass self.url = url.encode("utf8") if self.outfile is None: self.outfile = urldata.path.split("/")[-1] if not len(self.outfile.strip()) or not urldata.path.count("/"): self.outfile = "index.html" if self.outfile != "-": self.outfile = self.fs.resolve_path(self.outfile, self.protocol.cwd) path = os.path.dirname(self.outfile) if not path or not self.fs.exists(path) or not self.fs.isdir(path): self.errorWrite( "wget: {}: Cannot open: No such file or directory\n". format(self.outfile)) self.exit() return self.artifact = Artifact("curl-download") if not self.quiet: tm = time.strftime("%Y-%m-%d %H:%M:%S") self.errorWrite(f"--{tm}-- {url}\n") self.errorWrite( f"Connecting to {self.host}:{urldata.port}... connected.\n") self.errorWrite("HTTP request sent, awaiting response... ") self.deferred = self.wgetDownload(url) if self.deferred: self.deferred.addCallback(self.success) self.deferred.addErrback(self.error)
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 if not self.quiet: self.errorWrite( "--{}-- {}\n".format( time.strftime("%Y-%m-%d %H:%M:%S"), url.decode("utf8") ) ) self.errorWrite(f"Connecting to {host}:{port}... connected.\n") self.errorWrite("HTTP request sent, awaiting response... ") # TODO: need to do full name resolution. try: if ipaddress.ip_address(host).is_private: self.errorWrite( "Resolving {} ({})... failed: nodename nor servname provided, or not known.\n".format( host, host ) ) self.errorWrite(f"wget: unable to resolve host address ‘{host}’\n") return None except ValueError: pass # 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) 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 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.artifactFile = Artifact(outfile) # HTTPDownloader will close() the file object so need to preserve the name self.deferred = self.download(url, outfile, self.artifactFile) if self.deferred: self.deferred.addCallback(self.success, outfile) self.deferred.addErrback(self.error, url)