def connectionMade(self): """ Initializes the session """ super(SSHProtocol, self).connectionMade() # Service related self.service_name = Config.ssh.name self.local_ip = Config.general.address self.local_port = Config.ssh.port self.log = log # Connection related self.user = self.terminal.transport.session.avatar self.remote = self.user.conn.transport.transport.client self._parser = FilesystemParser(Config.folder.filesystem) self.current_dir = expanduser("~") load = self.loadLoginTime(self.user.username) if not load: # Random, plausible last login time tdelta = timedelta(days=randint(1, 365), seconds=randint(0, 60), minutes=randint(0, 60), hours=randint(0, 24)) now = datetime.now() login = now - tdelta loginStr = str(login.ctime()) else: loginStr = load self.saveLoginTime(self.user.username) self.terminal.write("Last login: " + loginStr) self.terminal.nextLine() self.showPrompt()
def connectionMade(self): """ Initializes the session """ super(SSHProtocol, self).connectionMade() self.user = self.terminal.transport.session.avatar self.userName = self.user.username.decode() self.name = config.sshName self.port = config.sshPort self._parser = FilesystemParser(config.path_to_filesys) self.userIP = self.user.conn.transport.transport.client[0] self.l = log self.current_dir = expanduser("~") load = self.loadLoginTime(self.userName) if load == False: # Zufällige, plausible last login time tdelta = timedelta(days=ri(1, 365), seconds=ri(0, 60), minutes=ri(0, 60), hours=ri(0, 24)) now = datetime.now() login = now - tdelta loginStr = str(login.ctime()) else: loginStr = load self.saveLoginTime(self.userName) self.terminal.write("Last login: " + loginStr) self.terminal.nextLine() self.showPrompt()
def setUp(self): self.ftp = FTPProtocol() FilesystemParser.honeytoken_directory = config.tokendir self.ftp._parser = FilesystemParser(config.resources + "/test_dir_sys.xml") self.ftp.factory = FactoryMock() self.ftp.transport = TransportMock() self.ftp.l = fakelogging
def setUp(self): self.ssh = SSHProtocol() self.ssh.transport = TransportMock() self.ssh.terminal = TerminalBuffer() self.ssh.userName = "******" self.ssh.name = config.sshName self.ssh.port = config.sshPort FilesystemParser.honeytoken_directory = config.tokendir self.ssh._parser = FilesystemParser(config.resources + "/test_unix.xml") self.ssh.userIP = "TestIP" self.ssh.l = TestLogging
class SSHProtocol(recvline.HistoricRecvLine): def connectionMade(self): """ Initializes the session """ super(SSHProtocol, self).connectionMade() # Service related self.service_name = Config.ssh.name self.local_ip = Config.general.address self.local_port = Config.ssh.port self.log = log # Connection related self.user = self.terminal.transport.session.avatar self.remote = self.user.conn.transport.transport.client self._parser = FilesystemParser(Config.folder.filesystem) self.current_dir = expanduser("~") load = self.loadLoginTime(self.user.username) if not load: # Random, plausible last login time tdelta = timedelta(days=randint(1, 365), seconds=randint(0, 60), minutes=randint(0, 60), hours=randint(0, 24)) now = datetime.now() login = now - tdelta loginStr = str(login.ctime()) else: loginStr = load self.saveLoginTime(self.user.username) self.terminal.write("Last login: "******"user profiles" to keep an attacker from filling the memory if len(lastLoginTime) <= 10000: if Config.general.use_utc: lastLoginTime[username] = str(datetime.utcnow().ctime()) else: lastLoginTime[username] = str(datetime.now().ctime()) def loadLoginTime(self, username): if username in lastLoginTime: return lastLoginTime[username] else: return False def print(self, lines, log=None): """ Prints a response to the client's terminal :param lines: a line or list of lines to be printed :param log: string that will appear in the log file """ if not isinstance(lines, list): # if only a single line should be printed lines = [lines] for line in lines: self.terminal.write(line) self.terminal.nextLine() if not log: log = lines self.log.response(self.service_name, self.remote[0], self.remote[1], self.local_ip, self.local_port, log, self.user.username) def showPrompt(self): """ Show prompt at start of line. """ self.terminal.write(self.user.username + "@" + Config.general.hostname + ":" + self._parser.get_formatted_path() + "$ ") def getCommandFunc(self, cmd): """ Get the corresponding function to a command. :param cmd: the command to search for :return: the corresponding "ssh_" function """ return getattr(self, 'ssh_' + cmd, None) def get_help(self, cmd): """ Get the helptext for a command :param cmd: :return: the corresponding text """ helptext = "" append = False with open(str(Config.ssh.helptext_folder)) as helps: for line in helps: if append and re.match("^\S", line): return helptext if re.match("^" + cmd, line): append = True if append: helptext = helptext + line return helptext def handle_arguments(self, args): """ Split arguments in path and list of arguments :param args: arguments :return: path, arguments """ path = "" arguments = [] for arg in args: if not arg.startswith("-"): path = arg else: for char in arg: if char != "-": arguments.append(char) return path, arguments def lineReceived(self, line): """ What to do, when we receive input. Also handles real command execution. :param line: the line received """ line = line.strip() if line: line = line.decode() # log call, we received a request self.log.request(self.service_name, self.remote[0], self.remote[1], self.local_ip, self.local_port, line, self.user.username) res = None if Config.ssh.real_shell: # Forwarding commands to the real shell if "cd" in line: try: self.current_dir = subprocess.check_output(line + " && pwd", stderr=subprocess.STDOUT, shell=True, cwd=self.current_dir).decode().strip() except subprocess.CalledProcessError as e: res = e.output res = res.decode() res = res.split("\n")[:-1] if "exit" in line: self.ssh_exit() else: try: res = subprocess.check_output(line, stderr=subprocess.STDOUT, shell=True, cwd=self.current_dir) except subprocess.CalledProcessError as e: res = e.output res = res.decode() res = res.split("\n")[:-1] else: # faking an ssh session cmdAndArgs = line.split() cmd = cmdAndArgs[0] args = cmdAndArgs[1:] func = self.getCommandFunc(cmd) if func: try: res = func(*args) except Exception as e: self.log.err(str(e)) else: res = cmd + ": command not found" if res: if not isinstance(res, tuple): # If only response and no log text res = (res, "") self.print(*res) self.showPrompt() def ssh_help(self, cmd=''): """ Prints the GNU bash help for cmd or the universal help text if cmd is not given :param cmd: the command """ if cmd: func = self.getCommandFunc(cmd) if func: text = self.get_help(cmd) if not func or not text: text = "help: no help topics match `{}'. " \ "Try `help help' or `man -k {}' or `info {}'.".format(cmd, cmd, cmd) return text gnuhelp = [] with open(str(Config.ssh.gnuhelp_folder)) as file: for line in file: gnuhelp.append(line) return gnuhelp, "Help text" def ssh_pwd(self): """ Prints the path to the current directory in fake filesystem """ return self._parser.get_current_path() def ssh_echo(self, *args): """ Prints whatever is in args """ return " ".join(args) def ssh_whoami(self): """ prints the username """ return self.user.username def ssh_exit(self): """ close the connection """ self.terminal.nextLine() self.terminal.loseConnection() def ssh_clear(self): """clear the terminal""" self.terminal.reset() def ssh_cd(self, *args): """ Change directory in fake filesystem :param args: arguments and path """ res = None if args: res = self._parser.cd(args[-1]) return res def ssh_ls(self, *args): """ Lists the content of the given directory in faked filesystem or of the current one if no path is given in args :param args: arguments and path """ path, arguments = self.handle_arguments(args) try: lines = self._parser.ls(path).split("\n")[:-1] # Split puts an empty string after the last "/n" except Exception: return "ls: " + path + ": No such file or directory." for line in lines: if line and line[0] == "." and "a" not in arguments: lines.remove(line) lines = lines return lines, "ls Text" def ssh_mkdir(self, *args): """ Creates a directory in the fake filesystem :param args: path to be created :return: """ return self._parser.mkdir(args[-1]) def ssh_touch(self, *args): """ Creates a file in the fake filesystem :param args: path to the new file """ return self._parser.touch(args[-1]) def ssh_rm(self, *args): """ removes whatever is at the specified path :param args: arguments and path :return: """ path, arguments = self.handle_arguments(args) if "r" in arguments and "f" in arguments and path == "/": time.sleep(4) self.ssh_exit() # r e a l i s m return if self._parser.valid_directory(path) and "r" not in arguments: return "rm: " + args[-1] + ": is a directory" return self._parser.delete(path) def ssh_mv(self, *args): """ Moves an element in the fake filesystem :param args: arguments, original path, new path """ res = self._parser.move(args[-2], args[-1]) if res: return "mv: " + res def ssh_cat(self, *args): """ Display the content of a file :param args: filepath """ try: response = self._parser.cat(args[-1]) except Exception as e: if str(e) == "File not found": response = "cat: " + args[-1] + ": File or directory not found" if str(e) == "Is a directory": response = "cat: " + args[-1] + ": Is a directory" return response def ssh_wget(self, *args): """ Downloads a file from the internet :param args: url """ # Handle URL url = args[-1] filename = url.split('/')[-1].split('#')[0].split('?')[0] if not re.match(r"^https?://", url): url = "http://" + url if not re.match(r"^https?://.*\..*/", url): # wenn die URL nichts hinter dem "/" nach der TLD hat filename = "index.html" # Determine filename i = 1 while filename in os.listdir(Config.folder.quarantine): filename = filename + "." + str(i) i += 1 # Write to disk filepath = "" if Config.ssh.accept_files: request.urlretrieve(url, Config.folder.quarantine / filename) filepath = Config.folder.quarantine / filename self.log.file(self.name, self.userIP, filename, filepath, self.user.username) def ssh_ll(self, *args): """ Alias for ls -l :param args: arguments """ return self.ssh_ls(*args + ("-l",))
def __init__(self): self._parser = FilesystemParser() self.user = "******" self.l = hg_log
class FTPProtocol(FTP): overwritten_commands_whitelist = [ 'CWD', 'DELE', 'LIST', 'MDTM', 'MKD', 'PASS', 'PWD', 'RETR', 'RMD', 'RNTO', 'SIZE', 'STOR', 'USER' ] inherited_commands_whitelist = [ 'FEAT', 'CDUP', 'NOOP', 'PASV', 'QUIT', 'RNFR', 'PORT', 'TYPE', 'SYST', 'STRU', 'MODE' ] inherited_responses = { 'FEAT': " ", 'NOOP': RESPONSE.get(CMD_OK), 'PASV': RESPONSE.get(ENTERING_PASV_MODE), 'QUIT': " ", 'RNFR': RESPONSE.get(REQ_FILE_ACTN_PENDING_FURTHER_INFO), 'PORT': " ", 'TYPE': " ", 'SYST': " ", 'STRU': " ", 'MODE': " " } honeytokenDirectory = str(Config.folder.honeytoken_files) receivedDataDirectory = str(Config.folder.quarantine) lastmodified = dt.now() def __init__(self): self._parser = FilesystemParser() self.user = "******" self.l = hg_log def ftp_PWD(self): """ Print current directory in faked filesystem. """ self.l.request(FTPService._name, self.transport.getPeer().host, FTPService._port, "PWD", self.user, "PWD") cur = " " + self._parser.get_formatted_path() self.l.response(FTPService._name, self.transport.getPeer().host, FTPService._port, cur, self.user, "PWD") return PWD_REPLY, cur def ftp_CWD(self, path): """ Change current directory in faked filesystem to path if path is valid. @param path: path to navigate to @type path: str """ self.l.request(FTPService._name, self.transport.getPeer().host, FTPService._port, "CWD " + path, self.user, "CWD") if self._parser.valid_directory(path): self._parser.cd(path) self.l.response(FTPService._name, self.transport.getPeer().host, FTPService._port, RESPONSE.get(REQ_FILE_ACTN_COMPLETED_OK, "ab"), self.user, "CWD") return (REQ_FILE_ACTN_COMPLETED_OK, ) self.l.response(FTPService._name, self.transport.getPeer().host, FTPService._port, RESPONSE.get(FILE_NOT_FOUND), self.user, "CWD") return defer.fail(FileNotFoundError(path)) def ftp_DELE(self, path): """ If path is valid path in faked filesystem, delete directory/file at path in faked filesystem. @param path: path of directory/file @type path: str """ self.l.request(FTPService._name, self.transport.getPeer().host, FTPService._port, "DELE " + path, self.user, "DELE") if self._parser.valid_path(path): self._parser.delete(path) self.l.response(FTPService._name, self.transport.getPeer().host, FTPService._port, RESPONSE.get(REQ_FILE_ACTN_COMPLETED_OK), self.user, "DELE") return REQ_FILE_ACTN_COMPLETED_OK self.l.response(FTPService._name, self.transport.getPeer().host, FTPService._port, RESPONSE.get(FILE_NOT_FOUND), self.user, "DELE") return defer.fail(FileNotFoundError(path)) def ftp_LIST(self, path=''): """ Return childs of directory at path in fake filesystem. (first 5 lines copied from twisted.protocols.ftp.FTP.ftp_LIST) @param path: path of directory @type path: str """ self.l.request(FTPService._name, self.transport.getPeer().host, FTPService._port, "LS " + path, self.user, "LS") if self.dtpInstance is None or not self.dtpInstance.isConnected: self.l.response( FTPService._name, self.transport.getPeer().host, FTPService._port, BAD_CMD_SEQ + ': PORT or PASV required before RETR', self.user, "LS") return defer.fail( BadCmdSequenceError('must send PORT or PASV before RETR')) if path.lower() in ['-a', '-l', '-la', '-al']: path = '' if self._parser.valid_directory(path): files = self._parser.ls(path).split() self.reply(DATA_CNX_ALREADY_OPEN_START_XFR) [ self.dtpInstance.sendLine(file.encode(self._encoding)) for file in files ] self.dtpInstance.transport.loseConnection() self.l.response(FTPService._name, self.transport.getPeer().host, FTPService._port, RESPONSE.get(TXFR_COMPLETE_OK), self.user, "LS") return (TXFR_COMPLETE_OK, ) self.l.response(FTPService._name, self.transport.getPeer().host, FTPService._port, RESPONSE.get(FILE_NOT_FOUND), self.user, "LS") return defer.fail(FileNotFoundError(path)) def ftp_MDTM(self, path): """ If path is valid path to 'file' in faked filesystem, return self.lastmodified. @param path: path to file/directory @type path: str """ self.l.request(FTPService._name, self.transport.getPeer().host, FTPService._port, "MDTM " + path, self.user, "MDTM") if self._parser.valid_path(path): response = self.lastmodified.strftime('%Y%m%d%H%M%S') self.l.response(FTPService._name, self.transport.getPeer().host, FTPService._port, FILE_STATUS + " " + response, self.user, "MDTM") return (FILE_STATUS, response) self.l.response(FTPService._name, self.transport.getPeer().host, FTPService._port, RESPONSE.get(FILE_NOT_FOUND), self.user, "MDTM") return defer.fail(FileNotFoundError(path)) def ftp_MKD(self, name): """ In faked filesystem: create a directory at path. @param path: new directory's path @type path: str """ self.l.request(FTPService._name, self.transport.getPeer().host, FTPService._port, "MKD " + name, self.user, "MKD") validName = not set('[~!@#$%^&*()+{}":;\']+$').intersection(name) if (not self._parser.valid_directory(name)) and validName: self._parser.mkdir(name) self.l.response(FTPService._name, self.transport.getPeer().host, FTPService._port, RESPONSE.get(MKD_REPLY) + " " + name, self.user, "MKD") return (MKD_REPLY, name) self.l.response(FTPService._name, self.transport.getPeer().host, FTPService._port, RESPONSE.get(FILE_NOT_FOUND), self.user, "MKD") return defer.fail(FileNotFoundError(name)) def ftp_RMD(self, path): """ In faked filesystem: remove directory at path. @param path: path to directory @type path: str """ self.l.request(FTPService._name, self.transport.getPeer().host, FTPService._port, "RMD " + path, self.user, "RMD") if self._parser.valid_directory(path): self._parser.delete(path) self.l.response(FTPService._name, self.transport.getPeer().host, FTPService._port, RESPONSE.get(REQ_FILE_ACTN_COMPLETED_OK), self.user, "RMD") return (REQ_FILE_ACTN_COMPLETED_OK, ) self.l.response(FTPService._name, self.transport.getPeer().host, FTPService._port, RESPONSE.get(FILE_NOT_FOUND), self.user, "RMD") return defer.fail(FileNotFoundError(path)) def ftp_RNTO(self, toName): """ Renames a previously chosen file to toName. @param toName: new name of the file @type toName: str """ self.l.request(FTPService._name, self.transport.getPeer().host, FTPService._port, "RNTO " + toName, self.user, "RNTO") fromName = self._fromName del self._fromName self.state = self.AUTHED validToName = not set('[~!@#$%^&*()+{}":;\']+$').intersection(toName) if (self._parser.valid_path(fromName)) and validToName: self._parser.rename(fromName, toName) self.l.response(FTPService._name, self.transport.getPeer().host, FTPService._port, RESPONSE.get(REQ_FILE_ACTN_COMPLETED_OK), self.user, "RNTO") return (REQ_FILE_ACTN_COMPLETED_OK, ) self.l.response(FTPService._name, self.transport.getPeer().host, FTPService._port, RESPONSE.get(FILE_NOT_FOUND) % fromName, self.user, "RNTO") return defer.fail(FileNotFoundError(fromName)) def ftp_SIZE(self, path): """ Return a random number between 100 and 5000000, if path is a valid path in faked filesystem. @param path: path to file @type path: str """ response = '' self.l.request(FTPService._name, self.transport.getPeer().host, FTPService._port, "SIZE " + path, self.user, "SIZE") if not self._parser.valid_path(path): self.l.response(FTPService._name, self.transport.getPeer().host, FTPService._port, RESPONSE.get(FILE_NOT_FOUND), self.user, "SIZE") return defer.fail(FileNotFoundError(path)) if self._parser.valid_directory(path): response = random.randint(20000, 5000000) if self._parser.valid_file(path): response = random.randint(100, 30000) self.l.response(FTPService._name, self.transport.getPeer().host, FTPService._port, FILE_STATUS + " " + str(response), self.user, "SIZE") return FILE_STATUS, response def ftp_STOR(self, path): """ Stores an uploaded File in self.receivedDataDirectory. @param path: path to file @type path: str """ abs_path = self._parser.get_absolute_path(path) # Windows-Mode etc. filename = abs_path.split("/")[-1] if self.dtpInstance is None: raise BadCmdSequenceError('PORT or PASV required before STOR') self.l.request(FTPService._name, self.transport.getPeer().host, FTPService._port, "STOR " + path, self.user, "STOR") if not self._parser.valid_file(path): self._parser.touch(path) self.setTimeout(None) def enableTimeout(result): self.setTimeout(self.factory.timeOut) return result def cbOpened(file): """ File was open for reading. Launch the data transfer channel via the file consumer. """ d = file.receive() d.addCallback(cbConsumer) d.addCallback(lambda ignored: file.close()) d.addCallbacks(cbSent, ebSent) return d def ebOpened(err): """ Called when failed to open the file for reading. For known errors, return the FTP error code. For all other, return a file not found error. """ if isinstance(err.value, FTPCmdError): return (err.value.errorCode, path) log.err(err, "Unexpected error received while opening file:") self.l.response(FTPService._name, self.transport.getPeer().host, FTPService._port, RESPONSE.get(FILE_NOT_FOUND), self.user, "STOR") return FILE_NOT_FOUND, path def cbConsumer(cons): """ Called after the file was opended for reading. Prepare the data transfer channel and send the response to the command channel. """ if not self.binary: cons = ASCIIConsumerWrapper(cons) d = self.dtpInstance.registerConsumer(cons) if self.dtpInstance.isConnected: self.reply(DATA_CNX_ALREADY_OPEN_START_XFR) else: self.reply(FILE_STATUS_OK_OPEN_DATA_CNX) return d def cbSent(result): """ Called from data transport when transfer is done. """ if Config.ftp.accept_files: self.l.file(FTPService._name, self.transport.getPeer().host, FTPService._port, filename, self.receivedDataDirectory + "/" + filename, self.user) else: self.l.file(FTPService._name, self.transport.getPeer().host, FTPService._port, filename, user=self.user) self.l.response(FTPService._name, self.transport.getPeer().host, FTPService._port, RESPONSE.get(TXFR_COMPLETE_OK), self.user, "STOR") return (TXFR_COMPLETE_OK, ) def ebSent(err): """ Called from data transport when there are errors during the transfer. """ log.err(err, "Unexpected error received during transfer:") if err.check(FTPCmdError): return err self.l.response(FTPService._name, self.transport.getPeer().host, FTPService._port, RESPONSE.get(CNX_CLOSED_TXFR_ABORTED), self.user, "STOR") return (CNX_CLOSED_TXFR_ABORTED, ) if Config.ftp.accept_files: i = 1 name = filename while name in os.listdir(self.receivedDataDirectory): name = filename + "." + str(i) i += 1 fObj = open(self.receivedDataDirectory + "/" + name, 'wb') d = defer.succeed(FW(fObj)) else: d = defer.succeed() d.addCallbacks(cbOpened, ebOpened) d.addBoth(enableTimeout) return d def ftp_RETR(self, path): """ This command causes the content of a file to be sent over the data transfer channel. If the path is to a folder, an error will be raised. @type path: str @param path: The path to the file which should be transferred over the data transfer channel. """ if self.dtpInstance is None: raise BadCmdSequenceError('PORT or PASV required before RETR') self.l.request(FTPService._name, self.transport.getPeer().host, FTPService._port, "RETR " + path, self.user, "RETR") honeytoken_filenames = os.listdir(self.honeytokenDirectory) if not (self._parser.valid_file(path) and path in honeytoken_filenames): self.l.response(FTPService._name, self.transport.getPeer().host, FTPService._port, FILE_NOT_FOUND, self.user, "RETR") return FILE_NOT_FOUND, path self.setTimeout(None) def enableTimeout(result): self.setTimeout(self.factory.timeOut) return result if not self.binary: cons = ASCIIConsumerWrapper(self.dtpInstance) else: cons = self.dtpInstance def cbSent(result): self.l.response(FTPService._name, self.transport.getPeer().host, FTPService._port, TXFR_COMPLETE_OK, self.user, "RETR") return (TXFR_COMPLETE_OK, ) def ebSent(err): log.msg("Unexpected error attempting to transmit file to client:") log.err(err) if err.check(FTPCmdError): return err self.l.response(FTPService._name, self.transport.getPeer().host, FTPService._port, CNX_CLOSED_TXFR_ABORTED, self.user, "RETR") return (CNX_CLOSED_TXFR_ABORTED, ) def cbOpened(file): if self.dtpInstance.isConnected: self.reply(DATA_CNX_ALREADY_OPEN_START_XFR) else: self.reply(FILE_STATUS_OK_OPEN_DATA_CNX) d = file.send(cons) d.addCallbacks(cbSent, ebSent) return d def ebOpened(err): if not err.check(PermissionDeniedError, FileNotFoundError, IsADirectoryError): log.msg( "Unexpected error attempting to open file for transmission:" ) log.err(err) if err.check(FTPCmdError): return (err.value.errorCode, path) self.l.response(FTPService._name, self.transport.getPeer().host, FTPService._port, FILE_NOT_FOUND, self.user, "RETR") return FILE_NOT_FOUND, path fObj = open(self.honeytokenDirectory + '/' + path, 'rb') d = defer.succeed(FR(fObj)) d.addCallbacks(cbOpened, ebOpened) d.addBoth(enableTimeout) return d def ftp_PASS(self, password): """ Second part of login. Get the password the peer wants to authenticate with. """ if self.factory.allowAnonymous and self._user == self.factory.userAnonymous: # anonymous login creds = credentials.Anonymous() reply = GUEST_LOGGED_IN_PROCEED else: # user login creds = credentials.UsernamePassword(self._user, password) reply = USR_LOGGED_IN_PROCEED self.user = self._user del self._user def _cbLogin(result): (interface, avatar, logout) = result assert interface is IFTPShell, "The realm is busted, jerk." self.shell = avatar self.logout = logout self.workingDirectory = [] self.state = self.AUTHED self.l.login( FTPService._name, self.transport.getPeer().host, FTPService._port, True, self.user, password, str(FTPService.credchecker.try_get_tokens(self.user, password))) return reply def _ebLogin(failure): failure.trap(cred_error.UnauthorizedLogin, cred_error.UnhandledCredentials) self.state = self.UNAUTH self.l.login( FTPService._name, self.transport.getPeer().host, FTPService._port, False, self.user, password, str(FTPService.credchecker.try_get_tokens(self.user, password))) self.user = '******' raise AuthorizationError d = self.portal.login(creds, None, IFTPShell) d.addCallbacks(_cbLogin, _ebLogin) return d def ftp_USER(self, username): """ First part of login. Get the username the peer wants to authenticate as. """ if not username: return defer.fail(CmdSyntaxError('USER requires an argument')) self._user = username self.state = self.INAUTH if self.factory.allowAnonymous and self._user == self.factory.userAnonymous: return GUEST_NAME_OK_NEED_EMAIL else: return USR_NAME_OK_NEED_PASS, username def processCommand(self, cmd, *params): """ Processes an FTP-Command. @param cmd: Received FTP-Command @param params: Received Parameters for FTP-Command """ def call_ftp_command(command): if command in self.overwritten_commands_whitelist: method = getattr(self, "ftp_" + command, None) return method(*params) if command in self.inherited_commands_whitelist: self.l.request(FTPService._name, self.transport.getPeer().host, FTPService._port, command, self.user, command) self.l.response(FTPService._name, self.transport.getPeer().host, FTPService._port, self.inherited_responses.get(command), self.user, command) method = getattr(self, "ftp_" + command, None) return method(*params) return defer.fail(CmdNotImplementedError(command)) cmd = cmd.upper() if self.state == self.UNAUTH: if cmd == 'USER': return self.ftp_USER(*params) elif cmd == 'PASS': return BAD_CMD_SEQ, "USER required before PASS" else: return NOT_LOGGED_IN elif self.state == self.INAUTH: if cmd == 'PASS': return self.ftp_PASS(*params) else: return BAD_CMD_SEQ, "PASS required after USER" elif self.state == self.AUTHED: return call_ftp_command(cmd) elif self.state == self.RENAMING: if cmd == 'RNTO': return self.ftp_RNTO(*params) else: return BAD_CMD_SEQ, "RNTO required after RNFR"
def setUp(self): FilesystemParser.honeytoken_directory = config.tokendir self.fp = FilesystemParser(resources._path[0] + '/test_unix.xml')
class FilesystemParserUnixTest(unittest.TestCase): def setUp(self): FilesystemParser.honeytoken_directory = config.tokendir self.fp = FilesystemParser(resources._path[0] + '/test_unix.xml') def test_get_absolute_path(self): self.assertEqual("/home/root", self.fp.get_absolute_path("../../bin/../home/root")) self.assertEqual("/bin", self.fp.get_absolute_path("/../home/../bin")) def test_tree_contains(self): self.assertTrue(self.fp.tree_contains("id_rsa.pub")) self.assertFalse(self.fp.tree_contains("michgibtsnicht")) def test_add_honeytoken_files(self): self.assertTrue(self.fp.tree_contains("id_rsa")) self.assertTrue(self.fp.tree_contains("id_rsa.pub")) self.assertTrue(self.fp.tree_contains("suspicious_data.txt")) def test_get_element(self): self.assertEqual(self.fp.get_element([]).attrib['name'], "/") def test_get_current_path(self): self.fp.cd("/home/root") self.assertEqual(self.fp.get_current_path(), "/home/root") self.fp.cd("..") self.assertEqual(self.fp.get_current_path(), "/home") self.fp.cd("/") self.assertEqual(self.fp.get_current_path(), "/") def test_get_formatted_path(self): self.fp.cd("/home/root") self.assertEqual(self.fp.get_formatted_path(), "~") self.fp.cd("/home") self.assertFalse(self.fp.get_formatted_path() == "~") def test_mkdir(self): self.fp.mkdir("new_folder_01") self.assertTrue(self.fp.tree_contains("new_folder_01")) self.assertEqual(self.fp.ls().count("new_folder_01"), 1) # pruefen, dass nicht mehrfach erzeugt self.fp.mkdir("~/new_folder_02") self.assertTrue(self.fp.tree_contains("new_folder_02")) self.fp.mkdir("../new_folder_03") self.assertTrue(self.fp.tree_contains("new_folder_03")) response = self.fp.mkdir("~/new_folder_02") self.assertEqual( response, "mkdir: cannot create directory 'new_folder_02': File exists") def test_touch(self): self.fp.mkdir("new_file_01") self.assertTrue(self.fp.tree_contains("new_file_01")) self.assertEqual(self.fp.ls().count("new_file_01"), 1) # pruefen, dass nicht mehrfach erzeugt self.fp.mkdir("~/new_file_02") self.assertTrue(self.fp.tree_contains("new_file_02")) self.fp.mkdir("../new_file_03") self.assertTrue(self.fp.tree_contains("new_file_03")) def test_ls(self): self.assertEqual(self.fp.ls("/var"), "log\nmail\nspool\ntmp\n") self.assertEqual(self.fp.ls("/var/log"), "") self.fp.cd("~") self.assertEqual(self.fp.ls(".ssh"), "id_rsa\nid_rsa.pub\n") def test_change_dir(self): path = self.fp.get_current_path() # alten Pfad merken self.fp.cd("./..") self.assertEqual( self.fp.get_current_path().split("/")[-1], path.split("/")[-2]) # neuer Pfad = alter Pfad ohne letzten / self.fp.cd("~") path = self.fp.get_current_path() # alten Pfad merken self.fp.cd("../.") self.assertEqual( self.fp.get_current_path().split("/")[-1], path.split("/")[-2]) # neuer Pfad = alter Pfad ohne letzten / self.fp.cd("/") self.assertEqual(self.fp.get_current_path(), "/") self.fp.cd("~") self.assertEqual(self.fp.get_formatted_path(), "~") self.fp.cd("../..") self.fp.cd("../../..") self.assertEqual(self.fp.get_current_path(), "/") path = "mich/gibtsnicht" self.assertEqual(self.fp.cd(path), path + ": No such file or directory") path = "~~" self.assertEqual(self.fp.cd(path), path + ": No such file or directory") def test_get_absoulte_path(self): self.fp.cd("/home/root") self.assertEqual(self.fp.get_absolute_path("~"), "/home/root") self.assertEqual(self.fp.get_absolute_path("./."), "/home/root") self.assertEqual(self.fp.get_absolute_path("./"), "/home/root") self.assertEqual(self.fp.get_absolute_path("."), "/home/root") self.assertEqual(self.fp.get_absolute_path("/"), "/") self.assertEqual(self.fp.get_absolute_path("/home"), "/home") self.assertEqual(self.fp.get_absolute_path("/home/../bin"), "/bin") self.assertEqual(self.fp.get_absolute_path(""), "") self.fp.cd("/") self.assertEqual(self.fp.get_absolute_path("C:\\Benutzer"), "/C:\\Benutzer") self.assertEqual( self.fp.get_absolute_path( "/#wasistdaßfür1Verzeichnis,_vong_Name_her?\\\n"), "/#wasistdaßfür1Verzeichnis,_vong_Name_her?\\\n") self.assertEqual(self.fp.get_absolute_path("/PfadDarfMitSlashEnden/"), "/PfadDarfMitSlashEnden") def test_valid_dir(self): self.assertTrue(self.fp.valid_directory("/home/root")) self.assertTrue(self.fp.valid_directory("/home/root/")) self.assertTrue(self.fp.valid_directory("/")) self.assertTrue(self.fp.valid_directory("~")) self.assertTrue(self.fp.valid_directory("..")) self.assertTrue(self.fp.valid_directory("./..")) self.assertTrue(self.fp.valid_directory("../..")) self.assertTrue(self.fp.valid_directory(".")) self.assertTrue(self.fp.valid_directory("./.")) self.assertTrue(self.fp.valid_directory("../.")) self.assertFalse(self.fp.valid_directory("...")) def test_valid_file(self): self.assertTrue(self.fp.valid_file("~/.ssh/id_rsa")) self.assertTrue(self.fp.valid_file("~/.ssh/id_rsa.pub")) self.assertFalse(self.fp.valid_file("michgibtsnicht!1!")) def test_delete(self): self.fp.cd("/") self.fp.mkdir("testdir") self.fp.cd("testdir") self.fp.cd("..") self.assertTrue("testdir" in self.fp.ls()) self.assertEqual(self.fp.ls().count("testdir"), 1) self.fp.delete("testdir") self.assertFalse("testdir" in self.fp.ls()) self.fp.touch("testfile") self.assertTrue("testfile" in self.fp.ls()) self.assertEqual(self.fp.ls().count("testfile"), 1) response = self.fp.delete(".") self.assertEqual( response, "rm: refusing to remove '.' or '..' directory: skipping '.'") response = self.fp.delete("..") self.assertEqual( response, "rm: refusing to remove '.' or '..' directory: skipping '..'") def test_rename(self): self.fp.cd("/") self.fp.touch("old_name") self.fp.rename("old_name", "new_name") self.assertFalse("old_name" in self.fp.ls()) self.assertTrue("new_name" in self.fp.ls()) self.assertEqual(self.fp.ls().count("new_name"), 1) def test_move(self): self.fp.cd("/") self.fp.mkdir("testdir") self.fp.touch("testfile") response = self.fp.move("testfile", "testdir") self.assertEqual(response, "Not possible") self.fp.mkdir("testdir/testrecursive") self.fp.move("testdir", "/bin/testdir") self.assertFalse("testdir" in self.fp.ls()) self.assertTrue("testdir" in self.fp.ls("/bin")) self.assertEqual(self.fp.ls("/bin").count("testdir"), 1) self.assertTrue("testrecursive" in self.fp.ls("/bin/testdir")) self.assertEqual(self.fp.ls("/bin/testdir").count("testrecursive"), 1) def test_cat(self): self.fp.cd("~") self.assertTrue( "-----BEGIN RSA PRIVATE KEY-----" in self.fp.cat(".ssh/id_rsa")) self.assertFalse(self.fp.cat("~/suspicious_data.txt") == "")
class FilesystemParserWindowsTest(unittest.TestCase): def setUp(self): FilesystemParser.honeytoken_directory = config.tokendir self.fp = FilesystemParser(resources._path[0] + '/test_dir_sys.xml') def test_get_absolute_path(self): self.assertEqual(self.fp.get_absolute_path("~"), "/Benutzer/TestUser") def test_tree_contains(self): self.assertTrue(self.fp.tree_contains("scan_01.jpg")) self.assertTrue(self.fp.tree_contains("Firefox")) self.assertTrue(self.fp.tree_contains("id_rsa")) self.assertFalse(self.fp.tree_contains("michgibtsnicht")) def test_add_honeytoken_files(self): print(self.fp.ls()) self.assertTrue(self.fp.tree_contains("id_rsa")) self.assertTrue(self.fp.tree_contains("suspicious_data.txt")) def test_get_element(self): self.assertEqual(self.fp.get_element([]).attrib['name'], "C:") def test_get_current_path(self): self.fp.cd("\Programme\Firefox") self.assertEqual(self.fp.get_current_path(), "/Programme/Firefox") self.fp.cd("..") self.assertEqual(self.fp.get_current_path(), "/Programme") self.fp.cd("\\") self.assertEqual(self.fp.get_current_path(), "/") def test_mkdir(self): self.fp.mkdir("new_folder_01") self.assertTrue(self.fp.tree_contains("new_folder_01")) self.assertEqual(self.fp.ls().count("new_folder_01"), 1) # pruefen, dass nicht mehrfach erzeugt self.fp.mkdir("~/new_folder_02") self.assertTrue(self.fp.tree_contains("new_folder_02")) self.fp.mkdir("../new_folder_03") self.assertTrue(self.fp.tree_contains("new_folder_03")) response = self.fp.mkdir("~/new_folder_02") self.assertEqual( response, "mkdir: cannot create directory 'new_folder_02': File exists") def test_touch(self): self.fp.mkdir("new_file_01") self.assertTrue(self.fp.tree_contains("new_file_01")) self.assertEqual(self.fp.ls().count("new_file_01"), 1) # pruefen, dass nicht mehrfach erzeugt self.fp.mkdir("~/new_file_02") self.assertTrue(self.fp.tree_contains("new_file_02")) self.fp.mkdir("../new_file_03") self.assertTrue(self.fp.tree_contains("new_file_03")) def test_ls(self): self.assertEqual(self.fp.ls("\Benutzer\TestUser\Musik"), "asdf.mp3\n") self.assertEqual(self.fp.ls("~/Downloads/"), "") def test_change_dir(self): path = self.fp.get_current_path() # alten Pfad merken self.fp.cd("./..") self.assertEqual( self.fp.get_current_path().split("/")[-1], path.split("/")[-2]) # neuer Pfad = alter Pfad ohne letzten / self.fp.cd("~") path = self.fp.get_current_path() # alten Pfad merken self.fp.cd("../.") self.assertEqual( self.fp.get_current_path().split("/")[-1], path.split("/")[-2]) # neuer Pfad = alter Pfad ohne letzten / self.fp.cd("/") self.assertEqual(self.fp.get_current_path(), "/") self.fp.cd("~") self.assertEqual(self.fp.get_formatted_path(), "C:\\Benutzer\\TestUser") self.fp.cd("../..") self.fp.cd("../../..") self.assertEqual(self.fp.get_current_path(), "/") path = "mich/gibtsnicht" self.assertEqual(self.fp.cd(path), path + ": No such file or directory") path = "~~" self.assertEqual(self.fp.cd(path), path + ": No such file or directory") def test_valid_dir(self): self.fp.cd("~") self.assertTrue(self.fp.valid_directory("..\..\Programme\Firefox")) self.assertTrue(self.fp.valid_directory("/")) self.assertTrue(self.fp.valid_directory("~")) self.assertTrue(self.fp.valid_directory("..")) self.assertTrue(self.fp.valid_directory("./..")) self.assertTrue(self.fp.valid_directory("../..")) self.assertTrue(self.fp.valid_directory(".")) self.assertTrue(self.fp.valid_directory("./.")) self.assertTrue(self.fp.valid_directory("../.")) self.assertFalse(self.fp.valid_directory("...")) def test_valid_file(self): self.assertFalse(self.fp.valid_file("michgibtsnicht!1!")) def test_delete(self): self.fp.cd("/") self.fp.mkdir("testdir") self.fp.cd("testdir") self.fp.cd("..") self.assertTrue("testdir" in self.fp.ls()) self.assertEqual(self.fp.ls().count("testdir"), 1) self.fp.delete("testdir") self.assertFalse("testdir" in self.fp.ls()) self.fp.touch("testfile") self.assertTrue("testfile" in self.fp.ls()) self.assertEqual(self.fp.ls().count("testfile"), 1) response = self.fp.delete(".") self.assertEqual( response, "rm: refusing to remove '.' or '..' directory: skipping '.'") response = self.fp.delete("..") self.assertEqual( response, "rm: refusing to remove '.' or '..' directory: skipping '..'") def test_rename(self): self.fp.cd("/") self.fp.touch("old_name") self.fp.rename("old_name", "new_name") self.assertFalse("old_name" in self.fp.ls()) self.assertTrue("new_name" in self.fp.ls()) self.assertEqual(self.fp.ls().count("new_name"), 1) def test_move(self): self.fp.cd("/") self.fp.mkdir("testdir") self.fp.touch("testfile") response = self.fp.move("testfile", "testdir") self.assertEqual(response, "Not possible") # self.fp.mkdir("testdir/testrecursive") # self.fp.move("testdir", "/bin/testdir") # self.assertFalse("testdir" in self.fp.ls()) # self.assertTrue("testdir" in self.fp.ls("/bin")) # self.assertEqual(self.fp.ls("/bin").count("testdir"), 1) # self.assertTrue("testrecursive" in self.fp.ls("/bin/testdir")) # self.assertEqual(self.fp.ls("/bin/testdir").count("testrecursive"), 1) def test_cat(self): # self.assertTrue("-----BEGIN RSA PRIVATE KEY-----" in self.fp.cat("~/.ssh/id_rsa")) # self.assertTrue("ssh-rsa " in self.fp.cat("~/.ssh/id_rsa.pub")) self.assertFalse(self.fp.cat("~/suspicious_data.txt") == "")