From da3475c645e4c7d1a59e48e9100f7c63ac74ac64 Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Wed, 1 Sep 2021 13:20:54 -0400 Subject: [PATCH] Agent: Move Powershell auth and encryption selection to AuthOptions --- monkey/infection_monkey/exploit/powershell.py | 10 +++- .../exploit/powershell_utils/auth_options.py | 7 +++ .../auth_options_generators.py | 23 ++++---- .../exploit/powershell_utils/utils.py | 13 +---- .../test_auth_options_generators.py | 54 ++++++++++++++++--- 5 files changed, 80 insertions(+), 27 deletions(-) diff --git a/monkey/infection_monkey/exploit/powershell.py b/monkey/infection_monkey/exploit/powershell.py index 9069406f8..3acc683a7 100644 --- a/monkey/infection_monkey/exploit/powershell.py +++ b/monkey/infection_monkey/exploit/powershell.py @@ -13,7 +13,11 @@ from common.utils.exploit_enum import ExploitType from infection_monkey.exploit.consts import WIN_ARCH_32, WIN_ARCH_64 from infection_monkey.exploit.HostExploiter import HostExploiter from infection_monkey.exploit.powershell_utils import utils -from infection_monkey.exploit.powershell_utils.auth_options import AuthOptions +from infection_monkey.exploit.powershell_utils.auth_options import ( + AUTH_NEGOTIATE, + ENCRYPTION_AUTO, + AuthOptions, +) from infection_monkey.exploit.powershell_utils.auth_options_generators import get_auth_options from infection_monkey.exploit.powershell_utils.credential_generators import get_credentials from infection_monkey.exploit.powershell_utils.credentials import Credentials @@ -96,6 +100,8 @@ class PowerShellExploiter(HostExploiter): password=self._config.exploit_password_list[0], ) auth_options = AuthOptions( + auth_type=AUTH_NEGOTIATE, + encryption=ENCRYPTION_AUTO, ssl=False, ) self._authenticate(credentials, auth_options) @@ -106,6 +112,8 @@ class PowerShellExploiter(HostExploiter): password=self._config.exploit_password_list[0], ) auth_options = AuthOptions( + auth_type=AUTH_NEGOTIATE, + encryption=ENCRYPTION_AUTO, ssl=True, ) self._authenticate(credentials, auth_options) diff --git a/monkey/infection_monkey/exploit/powershell_utils/auth_options.py b/monkey/infection_monkey/exploit/powershell_utils/auth_options.py index 5d590d166..50d0e24e5 100644 --- a/monkey/infection_monkey/exploit/powershell_utils/auth_options.py +++ b/monkey/infection_monkey/exploit/powershell_utils/auth_options.py @@ -1,6 +1,13 @@ from dataclasses import dataclass +AUTH_BASIC = "basic" +AUTH_NEGOTIATE = "negotiate" +ENCRYPTION_AUTO = "auto" +ENCRYPTION_NEVER = "never" + @dataclass class AuthOptions: + auth_type: str + encryption: str ssl: bool diff --git a/monkey/infection_monkey/exploit/powershell_utils/auth_options_generators.py b/monkey/infection_monkey/exploit/powershell_utils/auth_options_generators.py index 304d798da..178060d9b 100644 --- a/monkey/infection_monkey/exploit/powershell_utils/auth_options_generators.py +++ b/monkey/infection_monkey/exploit/powershell_utils/auth_options_generators.py @@ -1,19 +1,24 @@ from typing import List -from infection_monkey.exploit.powershell_utils.auth_options import AuthOptions +from infection_monkey.exploit.powershell_utils.auth_options import ( + AUTH_BASIC, + AUTH_NEGOTIATE, + ENCRYPTION_AUTO, + ENCRYPTION_NEVER, + AuthOptions, +) from infection_monkey.exploit.powershell_utils.credentials import Credentials -def get_auth_options(credentials: List[Credentials], ssl: bool) -> List[AuthOptions]: +def get_auth_options(credentials: List[Credentials], use_ssl: bool) -> List[AuthOptions]: auth_options = [] - for cred in credentials: - opts = AuthOptions(ssl) + for creds in credentials: + # Passwordless login only works with SSL false, AUTH_BASIC and ENCRYPTION_NEVER + ssl = False if creds.password == "" else use_ssl + auth_type = AUTH_BASIC if creds.password == "" else AUTH_NEGOTIATE + encryption = ENCRYPTION_NEVER if creds.password == "" else ENCRYPTION_AUTO - # Passwordless login only works with SSL false - if cred.password == "": - opts.ssl = False - - auth_options.append(opts) + auth_options.append(AuthOptions(auth_type, encryption, ssl)) return auth_options diff --git a/monkey/infection_monkey/exploit/powershell_utils/utils.py b/monkey/infection_monkey/exploit/powershell_utils/utils.py index 1b8a92e4c..642394a62 100644 --- a/monkey/infection_monkey/exploit/powershell_utils/utils.py +++ b/monkey/infection_monkey/exploit/powershell_utils/utils.py @@ -22,11 +22,6 @@ def build_monkey_execution_command(host: VictimHost, depth: int, executable_path } -AUTH_BASIC = "basic" -AUTH_NEGOTIATE = "negotiate" -ENCRYPTION_AUTO = "auto" -ENCRYPTION_NEVER = "never" - CONNECTION_TIMEOUT = 3 # Seconds @@ -38,17 +33,13 @@ class IClient(Protocol): def get_client_based_on_auth_options( ip_addr: str, credentials: Credentials, auth_options: AuthOptions ) -> IClient: - # Passwordless login only works with SSL false, AUTH_BASIC and ENCRYPTION_NEVER - auth = AUTH_NEGOTIATE if credentials.password != "" else AUTH_BASIC - encryption = ENCRYPTION_AUTO if credentials.password != "" else ENCRYPTION_NEVER - return Client( ip_addr, username=credentials.username, password=credentials.password, cert_validation=False, + auth=auth_options.auth_type, + encryption=auth_options.encryption, ssl=auth_options.ssl, - auth=auth, - encryption=encryption, connection_timeout=CONNECTION_TIMEOUT, ) diff --git a/monkey/tests/unit_tests/infection_monkey/exploit/powershell_utils/test_auth_options_generators.py b/monkey/tests/unit_tests/infection_monkey/exploit/powershell_utils/test_auth_options_generators.py index 61a4583a0..7a040d7c8 100644 --- a/monkey/tests/unit_tests/infection_monkey/exploit/powershell_utils/test_auth_options_generators.py +++ b/monkey/tests/unit_tests/infection_monkey/exploit/powershell_utils/test_auth_options_generators.py @@ -1,4 +1,10 @@ # from infection_monkey.exploit.powershell_utils.auth_options import AuthOptions +from infection_monkey.exploit.powershell_utils.auth_options import ( + AUTH_BASIC, + AUTH_NEGOTIATE, + ENCRYPTION_AUTO, + ENCRYPTION_NEVER, +) from infection_monkey.exploit.powershell_utils.auth_options_generators import get_auth_options from infection_monkey.exploit.powershell_utils.credentials import Credentials @@ -10,36 +16,72 @@ CREDENTIALS = [ def test_get_auth_options__ssl_true_with_password(): - auth_options = get_auth_options(CREDENTIALS, ssl=True) + auth_options = get_auth_options(CREDENTIALS, use_ssl=True) assert auth_options[0].ssl def test_get_auth_options__ssl_true_empty_password(): - auth_options = get_auth_options(CREDENTIALS, ssl=True) + auth_options = get_auth_options(CREDENTIALS, use_ssl=True) assert not auth_options[1].ssl def test_get_auth_options__ssl_true_none_password(): - auth_options = get_auth_options(CREDENTIALS, ssl=True) + auth_options = get_auth_options(CREDENTIALS, use_ssl=True) assert auth_options[2].ssl def test_get_auth_options__ssl_false_with_password(): - auth_options = get_auth_options(CREDENTIALS, ssl=False) + auth_options = get_auth_options(CREDENTIALS, use_ssl=False) assert not auth_options[0].ssl def test_get_auth_options__ssl_false_empty_password(): - auth_options = get_auth_options(CREDENTIALS, ssl=False) + auth_options = get_auth_options(CREDENTIALS, use_ssl=False) assert not auth_options[1].ssl def test_get_auth_options__ssl_false_none_password(): - auth_options = get_auth_options(CREDENTIALS, ssl=False) + auth_options = get_auth_options(CREDENTIALS, use_ssl=False) assert not auth_options[2].ssl + + +def test_get_auth_options__auth_type_with_password(): + auth_options = get_auth_options(CREDENTIALS, use_ssl=False) + + assert auth_options[0].auth_type == AUTH_NEGOTIATE + + +def test_get_auth_options__auth_type_empty_password(): + auth_options = get_auth_options(CREDENTIALS, use_ssl=False) + + assert auth_options[1].auth_type == AUTH_BASIC + + +def test_get_auth_options__auth_type_none_password(): + auth_options = get_auth_options(CREDENTIALS, use_ssl=False) + + assert auth_options[2].auth_type == AUTH_NEGOTIATE + + +def test_get_auth_options__encryption_with_password(): + auth_options = get_auth_options(CREDENTIALS, use_ssl=False) + + assert auth_options[0].encryption == ENCRYPTION_AUTO + + +def test_get_auth_options__encryption_empty_password(): + auth_options = get_auth_options(CREDENTIALS, use_ssl=False) + + assert auth_options[1].encryption == ENCRYPTION_NEVER + + +def test_get_auth_options__encryption_none_password(): + auth_options = get_auth_options(CREDENTIALS, use_ssl=False) + + assert auth_options[2].encryption == ENCRYPTION_AUTO