Skip to content

Commit 0166a42

Browse files
committed
Merge branch 'main' into dns
2 parents 47b1c1f + 65030d7 commit 0166a42

3 files changed

Lines changed: 69 additions & 25 deletions

File tree

nxc/protocols/ssh.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,8 +195,10 @@ def plaintext_login(self, username, password, private_key=""):
195195
username=username,
196196
passphrase=password if password != "" else None,
197197
key_filename=private_key if private_key else self.args.key_file,
198+
timeout=self.args.ssh_timeout,
198199
look_for_keys=False,
199200
allow_agent=False,
201+
banner_timeout=self.args.ssh_timeout,
200202
)
201203

202204
cred_id = self.db.add_credential(
@@ -213,8 +215,10 @@ def plaintext_login(self, username, password, private_key=""):
213215
port=self.port,
214216
username=username,
215217
password=password,
218+
timeout=self.args.ssh_timeout,
216219
look_for_keys=False,
217220
allow_agent=False,
221+
banner_timeout=self.args.ssh_timeout,
218222
)
219223
cred_id = self.db.add_credential("plaintext", username, password)
220224

@@ -226,6 +230,8 @@ def plaintext_login(self, username, password, private_key=""):
226230
except SSHException as e:
227231
if "Invalid key" in str(e):
228232
self.logger.fail(f"{username}:{process_secret(password)} Could not decrypt private key, error: {e}")
233+
if "Error reading SSH protocol banner" in str(e):
234+
self.logger.error(f"Internal Paramiko error for {username}:{process_secret(password)}, {e}")
229235
else:
230236
self.logger.exception(e)
231237
except Exception as e:

tests/e2e_commands.txt

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -151,9 +151,9 @@ netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M spooler
151151
netexec smb TARGET_HOST -u '' -p '' -M zerologon
152152
netexec smb TARGET_HOST -u '' -p '' -M petitpotam
153153
##### SMB Auth File
154-
netexec smb TARGET_HOST -u data/test_users.txt -p data/test_passwords.txt --no-bruteforce
155-
netexec smb TARGET_HOST -u data/test_users.txt -p data/test_passwords.txt --no-bruteforce --continue-on-success
156-
netexec smb TARGET_HOST -u data/test_users.txt -p data/test_passwords.txt
154+
netexec smb TARGET_HOST -u TEST_USER_FILE -p TEST_PASSWORD_FILE--no-bruteforce
155+
netexec smb TARGET_HOST -u TEST_USER_FILE -p TEST_PASSWORD_FILE--no-bruteforce --continue-on-success
156+
netexec smb TARGET_HOST -u TEST_USER_FILE -p data/test_passwords.txt
157157
##### WMI
158158
netexec wmi TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS # need an extra space after this command due to regex
159159
netexec wmi TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS --wmi-namespace root/cimv2
@@ -164,7 +164,9 @@ netexec wmi TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M spooler
164164
netexec wmi TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M zerologon
165165
netexec wmi TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M enum_dns
166166
netexec wmi TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M get_netconnections
167-
netexec wmi TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M rdp
167+
netexec wmi TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M rdp --options
168+
#netexec wmi TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M rdp -o ACTION=enable
169+
#netexec wmi TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M rdp -o ACTION=disable
168170
##### LDAP
169171
netexec {DNS} ldap TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS
170172
netexec ldap TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS --users
@@ -219,7 +221,7 @@ netexec winrm TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS --port 59
219221
netexec winrm TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS --check-proto http --port 5985
220222
netexec winrm TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS --check-proto https --port 5986
221223
##### MSSQL
222-
netexec mssql TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS
224+
netexec mssql TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS # Need a space at the end for kerb regex
223225
netexec {DNS} mssql TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS
224226
##### MSSQL Modules
225227
# netexec mssql TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD -M empire_exec
@@ -241,22 +243,22 @@ netexec rdp TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS # need an e
241243
netexec {DNS} rdp TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS
242244
netexec rdp TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS --nla-screenshot
243245
##### SSH - Default test passwords and random key; switch these out if you want correct authentication
244-
netexec ssh TARGET_HOST -u USERNAME -p PASSWORD
245-
netexec ssh TARGET_HOST -u data/test_users.txt -p data/test_passwords.txt --no-bruteforce
246-
netexec ssh TARGET_HOST -u data/test_users.txt -p data/test_passwords.txt --no-bruteforce --continue-on-success
247-
netexec ssh TARGET_HOST -u data/test_users.txt -p data/test_passwords.txt
248-
netexec ssh TARGET_HOST -u USERNAME -p PASSWORD --key-file data/test_key.priv
249-
netexec ssh TARGET_HOST -u USERNAME -p '' --key-file data/test_key.priv
250-
netexec ssh TARGET_HOST -u USERNAME -p PASSWORD --sudo-check
251-
netexec ssh TARGET_HOST -u USERNAME -p PASSWORD --sudo-check --sudo-check-method sudo-stdin
252-
netexec ssh TARGET_HOST -u USERNAME -p PASSWORD --sudo-check --sudo-check-method sudo-stdin --get-output-tries 10
253-
netexec ssh TARGET_HOST -u USERNAME -p PASSWORD --sudo-check --sudo-check-method mkfifo
254-
netexec ssh TARGET_HOST -u USERNAME -p PASSWORD --sudo-check --sudo-check-method mkfifo --get-output-tries 10
246+
netexec ssh TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD
247+
netexec ssh TARGET_HOST -u TEST_USER_FILE -p TEST_PASSWORD_FILE--no-bruteforce
248+
netexec ssh TARGET_HOST -u TEST_USER_FILE -p TEST_PASSWORD_FILE--no-bruteforce --continue-on-success
249+
netexec ssh TARGET_HOST -u TEST_USER_FILE -p data/test_passwords.txt
250+
netexec ssh TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD --key-file data/test_key.priv
251+
netexec ssh TARGET_HOST -u LOGIN_USERNAME -p '' --key-file data/test_key.priv
252+
netexec ssh TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD --sudo-check
253+
netexec ssh TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD --sudo-check --sudo-check-method sudo-stdin
254+
netexec ssh TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD --sudo-check --sudo-check-method sudo-stdin --get-output-tries 10
255+
netexec ssh TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD --sudo-check --sudo-check-method mkfifo
256+
netexec ssh TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD --sudo-check --sudo-check-method mkfifo --get-output-tries 10
255257
##### FTP- Default test passwords and random key; switch these out if you want correct authentication
256-
netexec ftp TARGET_HOST -u USERNAME -p PASSWORD
257-
netexec ftp TARGET_HOST -u USERNAME -p PASSWORD --ls
258-
netexec ftp TARGET_HOST -u USERNAME -p PASSWORD --put data/test_file.txt test_file.txt
259-
netexec ftp TARGET_HOST -u USERNAME -p PASSWORD --get test_file.txt
260-
netexec ftp TARGET_HOST -u data/test_users.txt -p data/test_passwords.txt --no-bruteforce
261-
netexec ftp TARGET_HOST -u data/test_users.txt -p data/test_passwords.txt --no-bruteforce --continue-on-success
262-
netexec ftp TARGET_HOST -u data/test_users.txt -p data/test_passwords.txt
258+
netexec ftp TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD
259+
netexec ftp TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD --ls
260+
netexec ftp TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD --put data/test_file.txt test_file.txt
261+
netexec ftp TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD --get test_file.txt
262+
netexec ftp TARGET_HOST -u TEST_USER_FILE -p TEST_PASSWORD_FILE --no-bruteforce
263+
netexec ftp TARGET_HOST -u TEST_USER_FILE -p TEST_PASSWORD_FILE --no-bruteforce --continue-on-success
264+
netexec ftp TARGET_HOST -u TEST_USER_FILE -p TEST_PASSWORD_FILE

tests/e2e_tests.py

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,19 @@
44
from rich.console import Console
55
import platform
66

7+
script_dir = os.path.dirname(os.path.abspath(__file__))
8+
run_dir = os.path.dirname(os.path.abspath(__file__))
9+
possible_locations = [
10+
os.path.join(run_dir, "tests/data/test_users.txt"),
11+
os.path.join(run_dir, "data/test_users.txt"),
12+
]
13+
test_user_file = next((loc for loc in possible_locations if os.path.isfile(loc)), None)
14+
possible_locations = [
15+
os.path.join(script_dir, "tests/data/test_passwords.txt"),
16+
os.path.join(script_dir, "data/test_passwords.txt"),
17+
]
18+
test_password_file = next((loc for loc in possible_locations if os.path.isfile(loc)), None)
19+
720

821
def get_cli_args():
922
parser = argparse.ArgumentParser(description="Script for running end to end tests for nxc")
@@ -72,7 +85,21 @@ def get_cli_args():
7285
"--print-failures",
7386
action="store_true",
7487
required=False,
75-
help="Prints all the commands of failed tests at the end"
88+
help="Prints all the commands of failed tests at the end",
89+
)
90+
parser.add_argument(
91+
"--test-user-file",
92+
dest="test_user_file",
93+
required=False,
94+
default=test_user_file,
95+
help="Path to the file containing test usernames",
96+
)
97+
parser.add_argument(
98+
"--test-password-file",
99+
dest="test_password_file",
100+
required=False,
101+
default=test_password_file,
102+
help="Path to the file containing test passwords",
76103
)
77104
parser.add_argument(
78105
"--dns-server",
@@ -126,7 +153,14 @@ def replace_command(args, line):
126153
kerberos = "-k " if args.kerberos else ""
127154
dns_server = f"--dns-server {args.dns_server}" if args.dns_server else ""
128155

129-
line = line.replace("TARGET_HOST", args.target).replace("LOGIN_USERNAME", f'"{args.username}"').replace("LOGIN_PASSWORD", f'"{args.password}"').replace("KERBEROS ", kerberos).replace("{DNS}", dns_server)
156+
line = line\
157+
.replace("TARGET_HOST", args.target)\
158+
.replace("LOGIN_USERNAME", f'"{args.username}"')\
159+
.replace("LOGIN_PASSWORD", f'"{args.password}"')\
160+
.replace("KERBEROS ", kerberos)\
161+
.replace("TEST_USER_FILE", args.test_user_file)\
162+
.replace("TEST_PASSWORD_FILE", args.test_password_file)\
163+
.replace("{DNS}", dns_server)
130164
if args.poetry:
131165
line = f"poetry run {line}"
132166
return line
@@ -154,6 +188,7 @@ def run_e2e_tests(args):
154188
# replace double quotes with single quotes for Linux due to special chars/escaping
155189
if platform.system() == "Linux":
156190
task = task.replace('"', "'")
191+
# we print the command before running because very often things will timeout and we want the last thing ran
157192
console.log(f"Running command: {task}")
158193
result = subprocess.Popen(
159194
task,
@@ -176,6 +211,7 @@ def run_e2e_tests(args):
176211

177212
if args.errors:
178213
raw_text = text.decode("utf-8")
214+
# this is not a good way to detect errors, but it does catch a lot of things
179215
if "error" in raw_text.lower() or "failure" in raw_text.lower():
180216
console.log("[bold red]Error Detected:")
181217
console.log(f"{raw_text}")

0 commit comments

Comments
 (0)