From 4ad07ae3ffd75d66414421c5b93d5046798a1b77 Mon Sep 17 00:00:00 2001 From: vakarisz Date: Thu, 31 Mar 2022 17:32:33 +0300 Subject: [PATCH 1/3] Agent: Add timeouts in shell startup modification PBA's --- .../linux/shell_startup_files_modification.py | 5 ++++- .../windows/shell_startup_files_modification.py | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/monkey/infection_monkey/post_breach/shell_startup_files/linux/shell_startup_files_modification.py b/monkey/infection_monkey/post_breach/shell_startup_files/linux/shell_startup_files_modification.py index ddd8f514b..63d67d208 100644 --- a/monkey/infection_monkey/post_breach/shell_startup_files/linux/shell_startup_files_modification.py +++ b/monkey/infection_monkey/post_breach/shell_startup_files/linux/shell_startup_files_modification.py @@ -1,5 +1,6 @@ import subprocess +from common.common_consts.timeouts import MEDIUM_REQUEST_TIMEOUT from infection_monkey.utils.environment import is_windows_os @@ -12,7 +13,9 @@ def get_linux_commands_to_modify_shell_startup_files(): # get list of usernames USERS = ( subprocess.check_output( # noqa: DUO116 - "cut -d: -f1,3 /etc/passwd | egrep ':[0-9]{4}$' | cut -d: -f1", shell=True + "cut -d: -f1,3 /etc/passwd | egrep ':[0-9]{4}$' | cut -d: -f1", + shell=True, + timeout=MEDIUM_REQUEST_TIMEOUT, ) .decode() .split("\n")[:-1] diff --git a/monkey/infection_monkey/post_breach/shell_startup_files/windows/shell_startup_files_modification.py b/monkey/infection_monkey/post_breach/shell_startup_files/windows/shell_startup_files_modification.py index 9d90f3812..714596266 100644 --- a/monkey/infection_monkey/post_breach/shell_startup_files/windows/shell_startup_files_modification.py +++ b/monkey/infection_monkey/post_breach/shell_startup_files/windows/shell_startup_files_modification.py @@ -1,6 +1,7 @@ import subprocess from pathlib import Path +from common.common_consts.timeouts import MEDIUM_REQUEST_TIMEOUT from infection_monkey.utils.environment import is_windows_os MODIFY_POWERSHELL_STARTUP_SCRIPT = Path(__file__).parent / "modify_powershell_startup_file.ps1" @@ -16,7 +17,9 @@ def get_windows_commands_to_modify_shell_startup_files(): # get list of usernames USERS = ( - subprocess.check_output("dir C:\\Users /b", shell=True) # noqa: DUO116 + subprocess.check_output( # noqa: DUO116 + "dir C:\\Users /b", shell=True, timeout=MEDIUM_REQUEST_TIMEOUT + ) .decode() .split("\r\n")[:-1] ) From df349914662ce9046ee1c27252fd4f23f8fd926c Mon Sep 17 00:00:00 2001 From: vakarisz Date: Fri, 1 Apr 2022 11:38:25 +0300 Subject: [PATCH 2/3] Agent: Add timeout handling in modify shell startup PBA --- .../actions/modify_shell_startup_files.py | 16 ++++++--- .../linux/shell_startup_files_modification.py | 34 ++++++++++++------- .../shell_startup_files_modification.py | 34 ++++++++++++------- 3 files changed, 53 insertions(+), 31 deletions(-) diff --git a/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py b/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py index 1a78aa3f0..b6fd9e601 100644 --- a/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py +++ b/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py @@ -2,6 +2,7 @@ import subprocess from typing import Dict from common.common_consts.post_breach_consts import POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION +from common.common_consts.timeouts import LONG_REQUEST_TIMEOUT from infection_monkey.i_puppet.i_puppet import PostBreachData from infection_monkey.post_breach.pba import PBA from infection_monkey.post_breach.shell_startup_files.shell_startup_files_modification import ( @@ -21,7 +22,7 @@ class ModifyShellStartupFiles(PBA): super().__init__(telemetry_messenger, name=POST_BREACH_SHELL_STARTUP_FILE_MODIFICATION) def run(self, options: Dict): - results = [pba.run() for pba in self.modify_shell_startup_PBA_list()] + results = [pba.run(options) for pba in self.modify_shell_startup_PBA_list()] if not results: results = [ ( @@ -70,14 +71,19 @@ class ModifyShellStartupFiles(PBA): windows_cmd=windows_cmds, ) - def run(self): + def run(self, options): if self.command: try: output = subprocess.check_output( # noqa: DUO116 - self.command, stderr=subprocess.STDOUT, shell=True + self.command, + stderr=subprocess.STDOUT, + shell=True, + timeout=LONG_REQUEST_TIMEOUT, ).decode() return output, True - except subprocess.CalledProcessError as e: + except subprocess.CalledProcessError as err: # Return error output of the command - return e.output.decode(), False + return err.output.decode(), False + except subprocess.TimeoutExpired as err: + return err.output.decode(), False diff --git a/monkey/infection_monkey/post_breach/shell_startup_files/linux/shell_startup_files_modification.py b/monkey/infection_monkey/post_breach/shell_startup_files/linux/shell_startup_files_modification.py index 63d67d208..896e50141 100644 --- a/monkey/infection_monkey/post_breach/shell_startup_files/linux/shell_startup_files_modification.py +++ b/monkey/infection_monkey/post_breach/shell_startup_files/linux/shell_startup_files_modification.py @@ -1,29 +1,37 @@ +import logging import subprocess from common.common_consts.timeouts import MEDIUM_REQUEST_TIMEOUT from infection_monkey.utils.environment import is_windows_os +logger = logging.getLogger(__name__) + def get_linux_commands_to_modify_shell_startup_files(): if is_windows_os(): return "", [], [] - HOME_DIR = "/home/" + home_dir = "/home/" + command = "cut -d: -f1,3 /etc/passwd | egrep ':[0-9]{4}$' | cut -d: -f1" # get list of usernames - USERS = ( - subprocess.check_output( # noqa: DUO116 - "cut -d: -f1,3 /etc/passwd | egrep ':[0-9]{4}$' | cut -d: -f1", - shell=True, - timeout=MEDIUM_REQUEST_TIMEOUT, + try: + users = ( + subprocess.check_output( # noqa: DUO116 + command, + shell=True, + timeout=MEDIUM_REQUEST_TIMEOUT, + ) + .decode() + .split("\n")[:-1] ) - .decode() - .split("\n")[:-1] - ) + except subprocess.TimeoutExpired: + logger.error(f"Command {command} timed out") + return "", [], [] # get list of paths of different shell startup files with place for username - STARTUP_FILES = [ - file_path.format(HOME_DIR) + startup_files = [ + file_path.format(home_dir) for file_path in [ "{0}{{0}}/.profile", # bash, dash, ksh, sh "{0}{{0}}/.bashrc", # bash @@ -45,6 +53,6 @@ def get_linux_commands_to_modify_shell_startup_files(): "tee -a {0} &&", # append to file "sed -i '$d' {0}", # remove last line of file (undo changes) ], - STARTUP_FILES, - USERS, + startup_files, + users, ) diff --git a/monkey/infection_monkey/post_breach/shell_startup_files/windows/shell_startup_files_modification.py b/monkey/infection_monkey/post_breach/shell_startup_files/windows/shell_startup_files_modification.py index 714596266..c52411120 100644 --- a/monkey/infection_monkey/post_breach/shell_startup_files/windows/shell_startup_files_modification.py +++ b/monkey/infection_monkey/post_breach/shell_startup_files/windows/shell_startup_files_modification.py @@ -1,3 +1,4 @@ +import logging import subprocess from pathlib import Path @@ -6,34 +7,41 @@ from infection_monkey.utils.environment import is_windows_os MODIFY_POWERSHELL_STARTUP_SCRIPT = Path(__file__).parent / "modify_powershell_startup_file.ps1" +logger = logging.getLogger(__name__) + def get_windows_commands_to_modify_shell_startup_files(): if not is_windows_os(): return "", [] # get powershell startup file path - SHELL_STARTUP_FILE = subprocess.check_output("powershell $Profile").decode().split("\r\n")[0] - SHELL_STARTUP_FILE_PATH_COMPONENTS = SHELL_STARTUP_FILE.split("\\") + shell_startup_file = subprocess.check_output("powershell $Profile").decode().split("\r\n")[0] + shell_startup_file_path_components = shell_startup_file.split("\\") # get list of usernames - USERS = ( - subprocess.check_output( # noqa: DUO116 - "dir C:\\Users /b", shell=True, timeout=MEDIUM_REQUEST_TIMEOUT + command = "dir C:\\Users /b" + try: + users = ( + subprocess.check_output( # noqa: DUO116 + command, shell=True, timeout=MEDIUM_REQUEST_TIMEOUT + ) + .decode() + .split("\r\n")[:-1] ) - .decode() - .split("\r\n")[:-1] - ) - USERS.remove("Public") + users.remove("Public") + except subprocess.TimeoutExpired: + logger.error(f"Command {command} timed out") + return "", [] - STARTUP_FILES_PER_USER = [ + startup_files_per_user = [ "\\".join( - SHELL_STARTUP_FILE_PATH_COMPONENTS[:2] + [user] + SHELL_STARTUP_FILE_PATH_COMPONENTS[3:] + shell_startup_file_path_components[:2] + [user] + shell_startup_file_path_components[3:] ) - for user in USERS + for user in users ] return [ "powershell.exe", str(MODIFY_POWERSHELL_STARTUP_SCRIPT), "-startup_file_path {0}", - ], STARTUP_FILES_PER_USER + ], startup_files_per_user From 7d3a6791355d9810c9128fa39a0af1c943d92362 Mon Sep 17 00:00:00 2001 From: vakaris_zilius Date: Fri, 1 Apr 2022 10:54:53 +0000 Subject: [PATCH 3/3] Agent: Fix error handling in modify_shell_startup_files.py --- .../post_breach/actions/modify_shell_startup_files.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py b/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py index b6fd9e601..21d5d4372 100644 --- a/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py +++ b/monkey/infection_monkey/post_breach/actions/modify_shell_startup_files.py @@ -84,6 +84,6 @@ class ModifyShellStartupFiles(PBA): return output, True except subprocess.CalledProcessError as err: # Return error output of the command - return err.output.decode(), False + return str(err), False except subprocess.TimeoutExpired as err: - return err.output.decode(), False + return str(err), False