Merge pull request #1478 from guardicore/powershell-pth-on-windows

Powershell pth on windows
This commit is contained in:
Mike Salvatore 2021-09-21 08:14:45 -04:00 committed by GitHub
commit 96ac13c579
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 151 additions and 89 deletions

View File

@ -31,6 +31,12 @@ ScoutSuite = {git = "git://github.com/guardicode/ScoutSuite"}
pyopenssl = "==19.0.0" # We can't build 32bit ubuntu12 binary with newer versions of pyopenssl
pypsrp = "*"
typing-extensions = "*"
cython = "*" # Remove this after removing pyspnego
# Pinning pyspnego to this commit resolves #1456. A new pyspnego release that includes this commit
# is expected after 2021-10-01. Once a new version of pyspnego is released (v0.2.0?), both pyspnego
# and cython can be removed from this Pipfile (since pyspnego is a dependency of pypsrp and pypsrp
# has no hard version requirement.
pyspnego = {editable = true, ref = "3f748f210e4fb6b186b0036e1a0bf38762d64c37", git = "https://github.com/jborean93/pyspnego"}
[dev-packages]

View File

@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
"sha256": "96a125018d143a7446fe9b2849991c00d79f37c433694db77e616c1135baeaf9"
"sha256": "e4052afd20556222b3cf8266aeca93f39568da6d1219b108b79070fa198ad908"
},
"pipfile-spec": 6,
"requires": {
@ -26,11 +26,11 @@
},
"altgraph": {
"hashes": [
"sha256:1f05a47122542f97028caf78775a095fbe6a2699b5089de8477eb583167d69aa",
"sha256:c623e5f3408ca61d4016f23a681b9adb100802ca3e3da5e718915a9e4052cebe"
"sha256:743628f2ac6a7c26f5d9223c91ed8ecbba535f506f4b6f558885a8a56a105857",
"sha256:ebf2269361b47d97b3b88e696439f6e4cbc607c17c51feb1754f90fb79839158"
],
"index": "pypi",
"version": "==0.17"
"version": "==0.17.2"
},
"asn1crypto": {
"hashes": [
@ -69,19 +69,19 @@
},
"boto3": {
"hashes": [
"sha256:461f659c06f9f56693cebbca70b11866f096021eafbd949a3c029c3a8adee6a4",
"sha256:596d2afda27ae3d9a10112a475aa25c4d6b5cf023919e370ad8e6c6ae04d57a6"
"sha256:3a270f002818703d5f2eef5296c2fd8b44ef21a3f3290a716ec2202da8dd464e",
"sha256:8bc3211a7d7767c2c72ae9b226edb5eec5bb96989c83696832b8a5c35feb356a"
],
"markers": "python_version >= '3.6'",
"version": "==1.18.33"
"version": "==1.18.44"
},
"botocore": {
"hashes": [
"sha256:204327b9a33e3ae5207ff9acdd7d3b6d1f99f5dc9165a4d843d6f1a566f3006c",
"sha256:b321b570a0da4c6280e737d817c8f740bce0ef914f564e1c27246c7ae76b4c31"
"sha256:2e134c9f799015e448086ed2b809fe50cc776f6600f093d1a44772288e61260f",
"sha256:c7640cb49c0e009bea4ad767715acbe0d305b7007235f52422bf31b5d23be8f1"
],
"markers": "python_version >= '3.6'",
"version": "==1.21.33"
"version": "==1.21.44"
},
"certifi": {
"hashes": [
@ -151,11 +151,11 @@
},
"charset-normalizer": {
"hashes": [
"sha256:0c8911edd15d19223366a194a513099a302055a962bca2cec0f54b8b63175d8b",
"sha256:f23667ebe1084be45f6ae0538e4a5a865206544097e4e8bbcacf42cd02a348f3"
"sha256:5d209c0a931f215cee683b6445e2d77677e7e75e159f78def0db09d68fafcaa6",
"sha256:5ec46d183433dcbd0ab716f2d7f29d8dee50505b3fdb40c6b985c7c4f5a3591f"
],
"markers": "python_version >= '3'",
"version": "==2.0.4"
"version": "==2.0.6"
},
"cheroot": {
"hashes": [
@ -229,6 +229,51 @@
"index": "pypi",
"version": "==2.5"
},
"cython": {
"hashes": [
"sha256:09ac3087ac7a3d489ebcb3fb8402e00c13d1a3a1c6bc73fd3b0d756a3e341e79",
"sha256:0a142c6b862e6ed6b02209d543062c038c110585b5e32d1ad7c9717af4f07e41",
"sha256:0d414458cb22f8a90d64260da6dace5d5fcebde43f31be52ca51f818c46db8cb",
"sha256:10cb3def9774fa99e4583617a5616874aed3255dc241fd1f4a3c2978c78e1c53",
"sha256:112efa54a58293a4fb0acf0dd8e5b3736e95b595eee24dd88615648e445abe41",
"sha256:166f9f29cd0058ce1a14a7b3a2458b849ed34b1ec5fd4108af3fdd2c24afcbb0",
"sha256:2d9e61ed1056a3b6a4b9156b62297ad18b357a7948e57a2f49b061217696567e",
"sha256:2f41ef7edd76dd23315925e003f0c58c8585f3ab24be6885c4b3f60e77c82746",
"sha256:37bcfa5df2a3009f49624695d917c3804fccbdfcdc5eda6378754a879711a4d5",
"sha256:416046a98255eff97ec02077d20ebeaae52682dfca1c35aadf31260442b92514",
"sha256:4cf4452f0e4d50e11701bca38f3857fe6fa16593e7fd6a4d5f7be66f611b7da2",
"sha256:55b0ee28c2c8118bfb3ad9b25cf7a6cbd724e442ea96956e32ccd908d5e3e043",
"sha256:5dd56d0be50073f0e54825a8bc3393852de0eed126339ecbca0ae149dba55cfc",
"sha256:5fa12ebafc2f688ea6d26ab6d1d2e634a9872509ba7135b902bb0d8b368fb04b",
"sha256:5fb977945a2111f6b64501fdf7ed0ec162cc502b84457fd648d6a558ea8de0d6",
"sha256:60c958bcab0ff315b4036a949bed1c65334e1f6a69e17e9966d742febb59043a",
"sha256:661dbdea519d9cfb288867252b75fef73ffa8e8bb674cec27acf70646afb369b",
"sha256:6a2cf2ccccc25413864928dfd730c29db6f63eaf98206c1e600003a445ca7f58",
"sha256:6ade74eece909fd3a437d9a5084829180751d7ade118e281e9824dd75eafaff2",
"sha256:73ac33a4379056a02031baa4def255717fadb9181b5ac2b244792d53eae1c925",
"sha256:76cbca0188d278e93d12ebdaf5990678e6e436485fdfad49dbe9b07717d41a3c",
"sha256:774cb8fd931ee1ba52c472bc1c19077cd6895c1b24014ae07bb27df59aed5ebe",
"sha256:821c2d416ad7d006b069657ee1034c0e0cb45bdbe9ab6ab631e8c495dfcfa4ac",
"sha256:84826ec1c11cda56261a252ddecac0c7d6b02e47e81b94f40b27b4c23c29c17c",
"sha256:854fe2193d3ad4c8b61932ff54d6dbe10c5fa8749eb8958d72cc0ab28243f833",
"sha256:88dc3c250dec280b0489a83950b15809762e27232f4799b1b8d0bad503f5ab84",
"sha256:8cb87777e82d1996aef6c146560a19270684271c9c669ba62ac6803b3cd2ff82",
"sha256:91339ee4b465924a3ea4b2a9cec7f7227bc4cadf673ce859d24c2b9ef60b1214",
"sha256:9164aeef1af6f837e4fc20402a31d256188ba4d535e262c6cb78caf57ad744f8",
"sha256:a102cfa795c6b3b81a29bdb9dbec545367cd7f353c03e6f30a056fdfefd92854",
"sha256:ad43e684ade673565f6f9d6638015112f6c7f11aa2a632167b79014f613f0f5f",
"sha256:afb521523cb46ddaa8d269b421f88ea2731fee05e65b952b96d4db760f5a2a1c",
"sha256:b28f92e617f540d3f21f8fd479a9c6491be920ffff672a4c61b7fc4d7f749f39",
"sha256:bc05de569f811be1fcfde6756c9048ae518f0c4b6d9f8f024752c5365d934cac",
"sha256:cdf04d07c3600860e8c2ebaad4e8f52ac3feb212453c1764a49ac08c827e8443",
"sha256:d8d1a087f35e39384303f5e6b75d465d6f29d746d7138eae9d3b6e8e6f769eae",
"sha256:eb2843f8cc01c645725e6fc690a84e99cdb266ce8ebe427cf3a680ff09f876aa",
"sha256:f2e9381497b12e8f622af620bde0d1d094035d79b899abb2ddd3a7891f535083",
"sha256:f96411f0120b5cae483923aaacd2872af8709be4b46522daedc32f051d778385"
],
"index": "pypi",
"version": "==0.29.24"
},
"dnspython": {
"hashes": [
"sha256:95d12f6ef0317118d2a1a6fc49aac65ffec7eb8087474158f42f26a639135216",
@ -268,11 +313,11 @@
},
"humanfriendly": {
"hashes": [
"sha256:332da98c24cc150efcc91b5508b19115209272bfdf4b0764a56795932f854271",
"sha256:f7dba53ac7935fd0b4a2fc9a29e316ddd9ea135fb3052d3d0279d10c18ff9c48"
"sha256:1697e1a8a8f550fd43c2865cd84542fc175a61dcb779b6fee18cf6b6ccba1477",
"sha256:6b0b831ce8f15f7300721aa49829fc4e83921a9a301cc7f606be6686a2288ddc"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
"version": "==9.2"
"version": "==10.0"
},
"idna": {
"hashes": [
@ -441,11 +486,11 @@
},
"minidump": {
"hashes": [
"sha256:67b3327cb96e319633653a353c6281703772335dc84797d6fdce7daf0b3be077",
"sha256:fdd9eb4566b6d3dabc205bf644ded724067bdbdb453eb418565261e5520b3537"
"sha256:5b9872a6417be626b7bc8db2f9feb6f9089e48ecfce372829a3418575fe22a1c",
"sha256:f545257f16437959d4c460dbb39b245ac019ba5f10a3bdd9b2efec4fad0d29e7"
],
"markers": "python_version >= '3.6'",
"version": "==0.0.19"
"version": "==0.0.20"
},
"minikerberos": {
"hashes": [
@ -457,11 +502,11 @@
},
"more-itertools": {
"hashes": [
"sha256:2cf89ec599962f2ddc4d568a05defc40e0a587fbc10d5989713638864c36be4d",
"sha256:83f0308e05477c68f56ea3a888172c78ed5d5b3c282addb67508e7ba6c8f813a"
"sha256:1debcabeb1df793814859d64a81ad7cb10504c24349368ccf214c664c474f41f",
"sha256:56ddac45541718ba332db05f464bebfb0768110111affd27f66e0051f276fa43"
],
"markers": "python_version >= '3.5'",
"version": "==8.8.0"
"version": "==8.10.0"
},
"msldap": {
"hashes": [
@ -538,10 +583,10 @@
},
"policyuniverse": {
"hashes": [
"sha256:1d5136329b4c4d33b114f8c781ebb2e306ff9dc6969d106ece2567e312b2dd15",
"sha256:a95adcecd8c5b6aafedbf0094217f9251589a5a350b3db54aa55b6cabc26a7ff"
"sha256:184f854fc716754ff07cd9f601923d1ce30a6826617e7c2b252abebe76746b6d",
"sha256:44145447d473c37ff2776667b5e1018a00c0a493c16a0a489399521b3786a8be"
],
"version": "==1.4.0.20210816"
"version": "==1.4.0.20210819"
},
"portend": {
"hashes": [
@ -804,7 +849,7 @@
"sha256:65540c21bfe14405a3a77e4c085ecfce88724743a4ead47c66b84defcf82c32e",
"sha256:9ce5fa65b8992dfa373bddc5b6e0864ead8f291c94fbfec05fbd5c836162e67b"
],
"markers": "sys_platform == 'win32'",
"markers": "python_version < '3.8' and sys_platform == 'win32'",
"version": "==2.1"
},
"pysmb": {
@ -815,24 +860,9 @@
"version": "==1.2.5"
},
"pyspnego": {
"hashes": [
"sha256:0356bccedc033b7266d89503eca50717f81fc9d3b98cb1dd5227bb7c1a9275ae",
"sha256:0940e0bdec72c6266ef9604db929ddda86f1dafe2c804ac3d6e30161a53e414d",
"sha256:44469f7cf2a9435d7115c557db4df6bd6a74ce0056511b88b672b58ff2d477f7",
"sha256:507809d2e1fc8733a4f0801ee59d01db646b41d3ab8b90a6f3a16a17eef3fc37",
"sha256:5701dd50597c0a11b4bd1d3921fd1c32ba3b7ec15c3e273c486870efe673dd52",
"sha256:5be3fa80bc81a11b9254e3800aa350db06b2eb1b9d830f7770a1baadae415185",
"sha256:777c9524e91298b2ec3d728dbb85e44d047ddd857db6c2658d977401fedfcc9c",
"sha256:83d52b9e8b55243fa3711d89e77d94935a60b8638e8659b572dee898d359bbe6",
"sha256:c05aa1efcb9b0cf3c6341c48a6b349c3b669b0d7d99ab65a789c0c1071701136",
"sha256:cc57132ebe7b6b5d14e940bf4069a1206ad0fe23f51281dee4e7979b34a369d3",
"sha256:d3e7d55447cc353765cef6d77b3c57fd02f77ddc83a4fb3b4b696df92f908ae1",
"sha256:e021472424fcb477d9a211437f6a14c2d9cb59e20eeee9ae7992bd7deee50064",
"sha256:ed4fece1a834cc29377f43f4ff459ae7eb7c7d937cfd3e4b46676fe9984c8c74",
"sha256:f90a41f7d31e049f3a2e566f02ce06d86f13bbd2e3796b3af3bdb2be75c6e836"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
"version": "==0.1.6"
"editable": true,
"git": "https://github.com/jborean93/pyspnego",
"ref": "3f748f210e4fb6b186b0036e1a0bf38762d64c37"
},
"python-dateutil": {
"hashes": [
@ -961,11 +991,11 @@
},
"tqdm": {
"hashes": [
"sha256:80aead664e6c1672c4ae20dc50e1cdc5e20eeff9b14aa23ecd426375b28be588",
"sha256:a4d6d112e507ef98513ac119ead1159d286deab17dffedd96921412c2d236ff5"
"sha256:8dd278a422499cd6b727e6ae4061c40b48fce8b76d1ccbf5d34fca9b7f925b0c",
"sha256:d359de7217506c9851b7869f3708d8ee53ed70a1b8edbba4dbcb47442592920d"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==4.62.2"
"version": "==4.62.3"
},
"typing-extensions": {
"hashes": [

View File

@ -47,7 +47,7 @@ class PowerShellExploiter(HostExploiter):
def _exploit_host(self):
try:
is_https = self._is_client_using_https()
use_ssl = self._is_client_using_https()
except PowerShellRemotingDisabledError as e:
logging.info(e)
return False
@ -59,7 +59,7 @@ class PowerShellExploiter(HostExploiter):
self._config.exploit_ntlm_hash_list,
is_windows_os(),
)
auth_options = get_auth_options(credentials, is_https)
auth_options = [get_auth_options(creds, use_ssl) for creds in credentials]
self._client = self._authenticate_via_brute_force(credentials, auth_options)
if not self._client:

View File

@ -1,10 +1,10 @@
from dataclasses import dataclass
from typing import List
from infection_monkey.exploit.powershell_utils.credentials import Credentials
from infection_monkey.exploit.powershell_utils.credentials import Credentials, SecretType
AUTH_BASIC = "basic"
AUTH_NEGOTIATE = "negotiate"
AUTH_NTLM = "ntlm"
ENCRYPTION_AUTO = "auto"
ENCRYPTION_NEVER = "never"
@ -16,15 +16,28 @@ class AuthOptions:
ssl: bool
def get_auth_options(credentials: List[Credentials], use_ssl: bool) -> List[AuthOptions]:
auth_options = []
def get_auth_options(credentials: Credentials, use_ssl: bool) -> AuthOptions:
ssl = _get_ssl(credentials, use_ssl)
auth_type = _get_auth_type(credentials)
encryption = _get_encryption(credentials)
for creds in credentials:
# Passwordless login only works with SSL false, AUTH_BASIC and ENCRYPTION_NEVER
ssl = False if creds.secret == "" else use_ssl
auth_type = AUTH_BASIC if creds.secret == "" else AUTH_NEGOTIATE
encryption = ENCRYPTION_NEVER if creds.secret == "" else ENCRYPTION_AUTO
return AuthOptions(auth_type, encryption, ssl)
auth_options.append(AuthOptions(auth_type, encryption, ssl))
return auth_options
def _get_ssl(credentials: Credentials, use_ssl):
# Passwordless login only works with SSL false, AUTH_BASIC and ENCRYPTION_NEVER
return False if credentials.secret == "" else use_ssl
def _get_auth_type(credentials: Credentials):
if credentials.secret == "":
return AUTH_BASIC
if credentials.secret_type in {SecretType.LM_HASH, SecretType.NT_HASH}:
return AUTH_NTLM
return AUTH_NEGOTIATE
def _get_encryption(credentials: Credentials):
return ENCRYPTION_NEVER if credentials.secret == "" else ENCRYPTION_AUTO

View File

@ -2,86 +2,99 @@
from infection_monkey.exploit.powershell_utils.auth_options import (
AUTH_BASIC,
AUTH_NEGOTIATE,
AUTH_NTLM,
ENCRYPTION_AUTO,
ENCRYPTION_NEVER,
get_auth_options,
)
from infection_monkey.exploit.powershell_utils.credentials import Credentials, SecretType
CREDENTIALS = [
Credentials("user1", "password1", SecretType.PASSWORD),
Credentials("user2", "", SecretType.PASSWORD),
Credentials("user3", None, SecretType.CACHED),
]
CREDENTIALS_WITH_PASSWORD = Credentials("user1", "password1", SecretType.PASSWORD)
CREDENTIALS_EMPTY_PASSWORD = Credentials("user2", "", SecretType.PASSWORD)
CREDENTIALS_NONE_PASSWORD = Credentials("user3", None, SecretType.CACHED)
CREDENTIALS_LM_HASH = Credentials("user4", "LM_HASH:NONE", SecretType.LM_HASH)
CREDENTIALS_NT_HASH = Credentials("user5", "NONE:NT_HASH", SecretType.NT_HASH)
def test_get_auth_options__ssl_true_with_password():
auth_options = get_auth_options(CREDENTIALS, use_ssl=True)
auth_options = get_auth_options(CREDENTIALS_WITH_PASSWORD, use_ssl=True)
assert auth_options[0].ssl
assert auth_options.ssl
def test_get_auth_options__ssl_true_empty_password():
auth_options = get_auth_options(CREDENTIALS, use_ssl=True)
auth_options = get_auth_options(CREDENTIALS_EMPTY_PASSWORD, use_ssl=True)
assert not auth_options[1].ssl
assert not auth_options.ssl
def test_get_auth_options__ssl_true_none_password():
auth_options = get_auth_options(CREDENTIALS, use_ssl=True)
auth_options = get_auth_options(CREDENTIALS_NONE_PASSWORD, use_ssl=True)
assert auth_options[2].ssl
assert auth_options.ssl
def test_get_auth_options__ssl_false_with_password():
auth_options = get_auth_options(CREDENTIALS, use_ssl=False)
auth_options = get_auth_options(CREDENTIALS_WITH_PASSWORD, use_ssl=False)
assert not auth_options[0].ssl
assert not auth_options.ssl
def test_get_auth_options__ssl_false_empty_password():
auth_options = get_auth_options(CREDENTIALS, use_ssl=False)
auth_options = get_auth_options(CREDENTIALS_EMPTY_PASSWORD, use_ssl=False)
assert not auth_options[1].ssl
assert not auth_options.ssl
def test_get_auth_options__ssl_false_none_password():
auth_options = get_auth_options(CREDENTIALS, use_ssl=False)
auth_options = get_auth_options(CREDENTIALS_NONE_PASSWORD, use_ssl=False)
assert not auth_options[2].ssl
assert not auth_options.ssl
def test_get_auth_options__auth_type_with_password():
auth_options = get_auth_options(CREDENTIALS, use_ssl=False)
auth_options = get_auth_options(CREDENTIALS_WITH_PASSWORD, use_ssl=False)
assert auth_options[0].auth_type == AUTH_NEGOTIATE
assert auth_options.auth_type == AUTH_NEGOTIATE
def test_get_auth_options__auth_type_empty_password():
auth_options = get_auth_options(CREDENTIALS, use_ssl=False)
auth_options = get_auth_options(CREDENTIALS_EMPTY_PASSWORD, use_ssl=False)
assert auth_options[1].auth_type == AUTH_BASIC
assert auth_options.auth_type == AUTH_BASIC
def test_get_auth_options__auth_type_none_password():
auth_options = get_auth_options(CREDENTIALS, use_ssl=False)
auth_options = get_auth_options(CREDENTIALS_NONE_PASSWORD, use_ssl=False)
assert auth_options[2].auth_type == AUTH_NEGOTIATE
assert auth_options.auth_type == AUTH_NEGOTIATE
def test_get_auth_options__auth_type_with_LM_hash():
auth_options = get_auth_options(CREDENTIALS_LM_HASH, use_ssl=False)
assert auth_options.auth_type == AUTH_NTLM
def test_get_auth_options__auth_type_with_NT_hash():
auth_options = get_auth_options(CREDENTIALS_NT_HASH, use_ssl=False)
assert auth_options.auth_type == AUTH_NTLM
def test_get_auth_options__encryption_with_password():
auth_options = get_auth_options(CREDENTIALS, use_ssl=False)
auth_options = get_auth_options(CREDENTIALS_WITH_PASSWORD, use_ssl=False)
assert auth_options[0].encryption == ENCRYPTION_AUTO
assert auth_options.encryption == ENCRYPTION_AUTO
def test_get_auth_options__encryption_empty_password():
auth_options = get_auth_options(CREDENTIALS, use_ssl=False)
auth_options = get_auth_options(CREDENTIALS_EMPTY_PASSWORD, use_ssl=False)
assert auth_options[1].encryption == ENCRYPTION_NEVER
assert auth_options.encryption == ENCRYPTION_NEVER
def test_get_auth_options__encryption_none_password():
auth_options = get_auth_options(CREDENTIALS, use_ssl=False)
auth_options = get_auth_options(CREDENTIALS_NONE_PASSWORD, use_ssl=False)
assert auth_options[2].encryption == ENCRYPTION_AUTO
assert auth_options.encryption == ENCRYPTION_AUTO