From e4f1558b5a95cdc69d482b327f997a9809ffbd18 Mon Sep 17 00:00:00 2001 From: Alexander Neff Date: Mon, 23 Oct 2023 11:20:47 -0400 Subject: [PATCH] Add computer accounts to bloodhound if local admin on host --- nxc/helpers/bloodhound.py | 4 +--- nxc/protocols/ldap.py | 12 ++++++++++++ nxc/protocols/mssql.py | 4 ++++ nxc/protocols/rdp.py | 6 ++++++ nxc/protocols/smb.py | 4 ++++ nxc/protocols/winrm.py | 2 ++ 6 files changed, 29 insertions(+), 3 deletions(-) diff --git a/nxc/helpers/bloodhound.py b/nxc/helpers/bloodhound.py index c6a00dcf..c23bc71b 100644 --- a/nxc/helpers/bloodhound.py +++ b/nxc/helpers/bloodhound.py @@ -1,4 +1,3 @@ - def add_user_bh(user, domain, logger, config): """Adds a user to the BloodHound graph database. @@ -41,7 +40,7 @@ def add_user_bh(user, domain, logger, config): encrypted=False, ) try: - with driver.session() as session, session.begin_transaction() as tx: + with driver.session().begin_transaction() as tx: for info in users_owned: distinguished_name = "".join(["DC=" + dc + "," for dc in info["domain"].split(".")]).rstrip(",") domain_query = tx.run(f'MATCH (d:Domain) WHERE d.distinguishedname STARTS WITH "{distinguished_name}" RETURN d').data() @@ -57,7 +56,6 @@ def add_user_bh(user, domain, logger, config): user_owned = info["username"] + "@" + domain account_type = "User" - result = tx.run(f'MATCH (c:{account_type} {{name:"{user_owned}"}}) RETURN c') if result.data()[0]["c"].get("owned") in (False, None): diff --git a/nxc/protocols/ldap.py b/nxc/protocols/ldap.py index 9cb1241a..5ed47940 100644 --- a/nxc/protocols/ldap.py +++ b/nxc/protocols/ldap.py @@ -379,6 +379,8 @@ class ldap(connection): if not self.args.local_auth: add_user_bh(self.username, self.domain, self.logger, self.config) + if self.admin_privs: + add_user_bh(f"{self.hostname}$", domain, self.logger, self.config) return True except SessionKeyDecryptionError: # for PRE-AUTH account @@ -434,6 +436,8 @@ class ldap(connection): if not self.args.local_auth: add_user_bh(self.username, self.domain, self.logger, self.config) + if self.admin_privs: + add_user_bh(f"{self.hostname}$", domain, self.logger, self.config) return True except SessionError as e: error, desc = e.getErrorString() @@ -488,6 +492,8 @@ class ldap(connection): if not self.args.local_auth: add_user_bh(self.username, self.domain, self.logger, self.config) + if self.admin_privs: + add_user_bh(f"{self.hostname}$", domain, self.logger, self.config) return True except ldap_impacket.LDAPSessionError as e: if str(e).find("strongerAuthRequired") >= 0: @@ -514,6 +520,8 @@ class ldap(connection): if not self.args.local_auth: add_user_bh(self.username, self.domain, self.logger, self.config) + if self.admin_privs: + add_user_bh(f"{self.hostname}$", domain, self.logger, self.config) return True except Exception as e: error_code = str(e).split()[-2][:-1] @@ -578,6 +586,8 @@ class ldap(connection): if not self.args.local_auth: add_user_bh(self.username, self.domain, self.logger, self.config) + if self.admin_privs: + add_user_bh(f"{self.hostname}$", domain, self.logger, self.config) return True except ldap_impacket.LDAPSessionError as e: if str(e).find("strongerAuthRequired") >= 0: @@ -603,6 +613,8 @@ class ldap(connection): if not self.args.local_auth: add_user_bh(self.username, self.domain, self.logger, self.config) + if self.admin_privs: + add_user_bh(f"{self.hostname}$", domain, self.logger, self.config) return True except ldap_impacket.LDAPSessionError as e: error_code = str(e).split()[-2][:-1] diff --git a/nxc/protocols/mssql.py b/nxc/protocols/mssql.py index 28b5d25f..60673d4a 100755 --- a/nxc/protocols/mssql.py +++ b/nxc/protocols/mssql.py @@ -190,6 +190,8 @@ class mssql(connection): self.logger.success(f"{domain}{username}{used_ccache} {self.mark_pwned()}") if not self.args.local_auth: add_user_bh(self.username, self.domain, self.logger, self.config) + if self.admin_privs: + add_user_bh(f"{self.hostname}$", domain, self.logger, self.config) return True except Exception as e: used_ccache = " from ccache" if useCache else f":{process_secret(kerb_pass)}" @@ -219,6 +221,7 @@ class mssql(connection): if self.admin_privs: self.db.add_admin_user("plaintext", domain, username, password, self.host) + add_user_bh(f"{self.hostname}$", domain, self.logger, self.config) domain = f"{domain}\\" if not self.args.local_auth else "" out = f"{domain}{username}:{process_secret(password)} {self.mark_pwned()}" @@ -269,6 +272,7 @@ class mssql(connection): if self.admin_privs: self.db.add_admin_user("hash", domain, username, ntlm_hash, self.host) + add_user_bh(f"{self.hostname}$", domain, self.logger, self.config) out = f"{domain}\\{username} {process_secret(ntlm_hash)} {self.mark_pwned()}" self.logger.success(out) diff --git a/nxc/protocols/rdp.py b/nxc/protocols/rdp.py index 794d47fb..f676f855 100644 --- a/nxc/protocols/rdp.py +++ b/nxc/protocols/rdp.py @@ -235,6 +235,8 @@ class rdp(connection): ) if not self.args.local_auth: add_user_bh(username, domain, self.logger, self.config) + if self.admin_privs: + add_user_bh(f"{self.hostname}$", domain, self.logger, self.config) return True except Exception as e: @@ -279,6 +281,8 @@ class rdp(connection): self.logger.success(f"{domain}\\{username}:{process_secret(password)} {self.mark_pwned()}") if not self.args.local_auth: add_user_bh(username, domain, self.logger, self.config) + if self.admin_privs: + add_user_bh(f"{self.hostname}$", domain, self.logger, self.config) return True except Exception as e: if "Authentication failed!" in str(e): @@ -311,6 +315,8 @@ class rdp(connection): self.logger.success(f"{self.domain}\\{username}:{process_secret(ntlm_hash)} {self.mark_pwned()}") if not self.args.local_auth: add_user_bh(username, domain, self.logger, self.config) + if self.admin_privs: + add_user_bh(f"{self.hostname}$", domain, self.logger, self.config) return True except Exception as e: if "Authentication failed!" in str(e): diff --git a/nxc/protocols/smb.py b/nxc/protocols/smb.py index 8f0398f6..4014d1a6 100755 --- a/nxc/protocols/smb.py +++ b/nxc/protocols/smb.py @@ -399,6 +399,8 @@ class smb(connection): self.logger.success(out) if not self.args.local_auth: add_user_bh(self.username, domain, self.logger, self.config) + if self.admin_privs: + add_user_bh(f"{self.hostname}$", domain, self.logger, self.config) # check https://github.com/byt3bl33d3r/CrackMapExec/issues/321 if self.args.continue_on_success and self.signing: @@ -466,6 +468,7 @@ class smb(connection): self.host, user_id=user_id, ) + add_user_bh(f"{self.hostname}$", domain, self.logger, self.config) out = f"{domain}\\{self.username}:{process_secret(self.password)} {self.mark_pwned()}" self.logger.success(out) @@ -529,6 +532,7 @@ class smb(connection): if self.admin_privs: self.db.add_admin_user("hash", domain, self.username, nthash, self.host, user_id=user_id) + add_user_bh(f"{self.hostname}$", domain, self.logger, self.config) out = f"{domain}\\{self.username}:{process_secret(self.hash)} {self.mark_pwned()}" self.logger.success(out) diff --git a/nxc/protocols/winrm.py b/nxc/protocols/winrm.py index 69552ea2..55a444ae 100644 --- a/nxc/protocols/winrm.py +++ b/nxc/protocols/winrm.py @@ -236,6 +236,7 @@ class winrm(connection): if self.admin_privs: self.logger.debug("Inside admin privs") self.db.add_admin_user("plaintext", domain, self.username, self.password, self.host) # , user_id=user_id) + add_user_bh(f"{self.hostname}$", domain, self.logger, self.config) if not self.args.local_auth: add_user_bh(self.username, self.domain, self.logger, self.config) @@ -288,6 +289,7 @@ class winrm(connection): if self.admin_privs: self.db.add_admin_user("hash", domain, self.username, nthash, self.host) + add_user_bh(f"{self.hostname}$", domain, self.logger, self.config) if not self.args.local_auth: add_user_bh(self.username, self.domain, self.logger, self.config)