mirror of
https://github.com/Pennyw0rth/NetExec.git
synced 2026-11-07 09:26:01 -10:00
Merge pull request #1311 from Functionhx/fix/netexec-1273-export-keys
fix: add get_keys fallback to prevent export keys crash
This commit is contained in:
3 files changed
+85
No files matched your search
@@ -208,3 +208,7 @@ class BaseDB:
|
||||
res = self.sess.execute(*args)
|
||||
self.lock.release()
|
||||
return res
|
||||
|
||||
def get_keys(self, key_id=None, cred_id=None):
|
||||
"""Return an empty list by default. Protocols that support keys (e.g. SSH) override this."""
|
||||
return []
|
||||
@@ -310,10 +310,18 @@ class DatabaseNavigator(cmd.Cmd):
|
||||
return
|
||||
print("[+] DPAPI secrets exported")
|
||||
elif command == "keys":
|
||||
if len(line) < 3:
|
||||
print("[-] invalid arguments, export keys <all|id> <filename>")
|
||||
return
|
||||
|
||||
keys = self.db.get_keys() if line[1].lower() == "all" else self.db.get_keys(key_id=int(line[1]))
|
||||
if not keys:
|
||||
print("[-] No keys found in the database for the current protocol")
|
||||
return
|
||||
writable_keys = [key[2] for key in keys]
|
||||
filename = line[2]
|
||||
write_list(filename, writable_keys)
|
||||
print("[+] Keys exported")
|
||||
elif command == "wcc":
|
||||
if len(line) < 3:
|
||||
print("[-] invalid arguments, export wcc <simple|detailed> <filename>")
|
||||
|
||||
@@ -256,3 +256,76 @@ def test_get_loggedin_relations():
|
||||
|
||||
def test_remove_loggedin_relations():
|
||||
pass
|
||||
|
||||
|
||||
def test_get_keys_returns_empty_for_smb(db):
|
||||
"""Protocols without key support (like SMB) must return an empty list.
|
||||
This also verifies the BaseDB default doesn't raise AttributeError.
|
||||
"""
|
||||
keys = db.get_keys()
|
||||
assert keys == []
|
||||
assert isinstance(keys, list)
|
||||
|
||||
|
||||
def test_get_keys_all_and_by_id_fallback(db):
|
||||
"""Both call variants (all / by id) fall back to empty for unsupported protocols."""
|
||||
assert db.get_keys() == []
|
||||
assert db.get_keys(key_id=1) == []
|
||||
|
||||
|
||||
def test_write_list_empty_entries(tmp_path):
|
||||
"""write_list with empty entries truncates the file and writes nothing.
|
||||
This is why the keys export must guard against empty keys — see the
|
||||
check in DatabaseNavigator.do_export for the 'keys' command.
|
||||
"""
|
||||
from nxc.nxcdb import write_list
|
||||
|
||||
test_file = tmp_path / "test_export.txt"
|
||||
# Pre-populate the file with data
|
||||
test_file.write_text("existing content")
|
||||
assert test_file.read_text() == "existing content"
|
||||
|
||||
# write_list with empty entries opens in "w" mode and writes nothing
|
||||
write_list(str(test_file), [])
|
||||
assert test_file.read_text() == ""
|
||||
|
||||
|
||||
def test_do_export_keys_empty_guard(db, tmp_path):
|
||||
"""R2 regression: do_export('keys all <file>') must NOT truncate the
|
||||
target file when the protocol returns no keys (e.g., SMB). Removing
|
||||
the empty-key guard in do_export would leave all other tests passing
|
||||
while restoring false success and file truncation.
|
||||
"""
|
||||
import io
|
||||
|
||||
test_file = tmp_path / "keys_export.txt"
|
||||
test_file.write_text("do not overwrite me")
|
||||
assert test_file.read_text() == "do not overwrite me"
|
||||
|
||||
# Minimal mock — DatabaseNavigator only needs .config and .workspace
|
||||
class MockMainMenu:
|
||||
config = {}
|
||||
workspace = "test"
|
||||
|
||||
from nxc.nxcdb import DatabaseNavigator
|
||||
|
||||
nav = DatabaseNavigator(MockMainMenu(), db, "smb")
|
||||
|
||||
buf = io.StringIO()
|
||||
import sys
|
||||
|
||||
old_stdout = sys.stdout
|
||||
sys.stdout = buf
|
||||
try:
|
||||
nav.do_export(f"keys all {test_file}")
|
||||
finally:
|
||||
sys.stdout = old_stdout
|
||||
|
||||
output = buf.getvalue()
|
||||
|
||||
# File must remain unchanged — the whole point of the guard
|
||||
assert test_file.read_text() == "do not overwrite me"
|
||||
# Failure message must appear
|
||||
assert "[-] No keys found" in output
|
||||
# Success message must NOT appear
|
||||
assert "[+] Keys exported" not in output
|
||||
Reference in new issue
Block a user