Replaced ping with curl/wget and Invoke-WebRequest

This commit is contained in:
Shay Nehmad 2019-12-23 17:41:42 +02:00
parent 34c2ff6bb6
commit c8a742674f
2 changed files with 24 additions and 17 deletions

View File

@ -10,10 +10,10 @@ from infection_monkey.post_breach.pba import PBA
from infection_monkey.telemetry.post_breach_telem import PostBreachTelem from infection_monkey.telemetry.post_breach_telem import PostBreachTelem
from infection_monkey.utils.environment import is_windows_os from infection_monkey.utils.environment import is_windows_os
PING_TEST_DOMAIN = "google.com" INFECTION_MONKEY_WEBSITE_URL = "https://infectionmonkey.com"
CREATED_PROCESS_AS_USER_PING_SUCCESS_FORMAT = "Created process '{}' as user '{}', and successfully pinged." CREATED_PROCESS_AS_USER_SUCCESS_FORMAT = "Created process '{}' as user '{}' and the process succeeded."
CREATED_PROCESS_AS_USER_PING_FAILED_FORMAT = "Created process '{}' as user '{}', but failed to ping (exit status {})." CREATED_PROCESS_AS_USER_FAILED_FORMAT = "Created process '{}' as user '{}', but the process failed (exit status {})."
USERNAME_PREFIX = "somenewuser" USERNAME_PREFIX = "somenewuser"
PASSWORD = "N3WPa55W0rD!1" PASSWORD = "N3WPa55W0rD!1"
@ -23,8 +23,8 @@ logger = logging.getLogger(__name__)
class CommunicateAsNewUser(PBA): class CommunicateAsNewUser(PBA):
""" """
This PBA creates a new user, and then pings google as that user. This is used for a Zero Trust test of the People This PBA creates a new user, and then creates HTTP/S requests as that user. This is used for a Zero Trust test of the
pillar. See the relevant telemetry processing to see what findings are created. People pillar. See the relevant telemetry processing to see what findings are created.
""" """
def __init__(self): def __init__(self):
@ -34,9 +34,9 @@ class CommunicateAsNewUser(PBA):
username = CommunicateAsNewUser.get_random_new_user_name() username = CommunicateAsNewUser.get_random_new_user_name()
try: try:
with create_auto_new_user(username, PASSWORD) as new_user: with create_auto_new_user(username, PASSWORD) as new_user:
ping_commandline = CommunicateAsNewUser.get_commandline_for_ping() http_request_commandline = CommunicateAsNewUser.get_commandline_for_http_request(INFECTION_MONKEY_WEBSITE_URL)
exit_status = new_user.run_as(ping_commandline) exit_status = new_user.run_as(http_request_commandline)
self.send_ping_result_telemetry(exit_status, ping_commandline, username) self.send_result_telemetry(exit_status, http_request_commandline, username)
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:
PostBreachTelem(self, (e.output.decode(), False)).send() PostBreachTelem(self, (e.output.decode(), False)).send()
except NewUserError as e: except NewUserError as e:
@ -47,21 +47,28 @@ class CommunicateAsNewUser(PBA):
return USERNAME_PREFIX + ''.join(random.choice(string.ascii_lowercase) for _ in range(5)) return USERNAME_PREFIX + ''.join(random.choice(string.ascii_lowercase) for _ in range(5))
@staticmethod @staticmethod
def get_commandline_for_ping(domain=PING_TEST_DOMAIN, is_windows=is_windows_os()): def get_commandline_for_http_request(url, is_windows=is_windows_os()):
format_string = "PING.exe {domain} -n 1" if is_windows else "ping -c 1 {domain}" if is_windows:
return format_string.format(domain=domain) format_string = "powershell -command \"Invoke-WebRequest {url}\""
else:
# true || false -> 0. false || true -> 0. false || false -> 1. So:
# if curl works, we're good.
# If curl doesn't exist or fails and wget work, we're good.
# And if both don't exist: we'll call it a win.
format_string = "curl {url} || wget -O/dev/null -q {url}"
return format_string.format(url=url)
def send_ping_result_telemetry(self, exit_status, commandline, username): def send_result_telemetry(self, exit_status, commandline, username):
""" """
Parses the result of ping and sends telemetry accordingly. Parses the result of the command and sends telemetry accordingly.
:param exit_status: In both Windows and Linux, 0 exit code from Ping indicates success. :param exit_status: In both Windows and Linux, 0 exit code indicates success.
:param commandline: Exact commandline which was executed, for reporting back. :param commandline: Exact commandline which was executed, for reporting back.
:param username: Username from which the command was executed, for reporting back. :param username: Username from which the command was executed, for reporting back.
""" """
if exit_status == 0: if exit_status == 0:
PostBreachTelem(self, ( PostBreachTelem(self, (
CREATED_PROCESS_AS_USER_PING_SUCCESS_FORMAT.format(commandline, username), True)).send() CREATED_PROCESS_AS_USER_SUCCESS_FORMAT.format(commandline, username), True)).send()
else: else:
PostBreachTelem(self, ( PostBreachTelem(self, (
CREATED_PROCESS_AS_USER_PING_FAILED_FORMAT.format(commandline, username, exit_status), False)).send() CREATED_PROCESS_AS_USER_FAILED_FORMAT.format(commandline, username, exit_status), False)).send()

View File

@ -65,7 +65,7 @@ class AutoNewWindowsUser(AutoNewUser):
self.username, self.username,
".", # Use current domain. ".", # Use current domain.
self.password, self.password,
win32con.LOGON32_LOGON_INTERACTIVE, # Logon type - interactive (normal user). Need this to open ping win32con.LOGON32_LOGON_INTERACTIVE, # Logon type - interactive (normal user).
# using a shell. # using a shell.
win32con.LOGON32_PROVIDER_DEFAULT) # Which logon provider to use - whatever Windows offers. win32con.LOGON32_PROVIDER_DEFAULT) # Which logon provider to use - whatever Windows offers.
except Exception as err: except Exception as err: