Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve bloodhound connector with Netbios domain name #88

Merged
merged 8 commits into from
Nov 3, 2023
4 changes: 0 additions & 4 deletions nxc/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -389,10 +389,6 @@ def try_credentials(self, domain, username, owned, secret, cred_type, data=None)
return False
if self.args.continue_on_success and owned:
return False
# Enforcing FQDN for SMB if not using local authentication. Related issues/PRs: #26, #28, #24, #38
if self.args.protocol == "smb" and not self.args.local_auth and "." not in domain and not self.args.laps and secret != "" and self.domain.upper() != self.hostname.upper():
self.logger.error(f"Domain {domain} for user {username.rstrip()} need to be FQDN ex:domain.local, not domain")
return False

with sem:
if cred_type == "plaintext":
Expand Down
25 changes: 18 additions & 7 deletions nxc/helpers/bloodhound.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,26 @@ def add_user_bh(user, domain, logger, config):
try:
with driver.session() as session, session.begin_transaction() as tx:
for info in users_owned:
distinguished_name = "".join([f"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()
if not domain_query:
raise Exception("Domain not found in bloodhound")
else:
domain = domain_query[0]["d"].get("name")

if info["username"][-1] == "$":
user_owned = info["username"][:-1] + "." + info["domain"]
user_owned = f"{info['username'][:-1]}.{domain}"
account_type = "Computer"
else:
user_owned = info["username"] + "@" + info["domain"]
user_owned = f"{info['username']}@{domain}"
account_type = "User"

result = tx.run(f'MATCH (c:{account_type} {{name:"{user_owned}"}}) RETURN c')

result = tx.run(f"MATCH (c:{account_type} {{name:'{user_owned}'}}) RETURN c")

if result.data()[0]["c"].get("owned") in (False, None):
logger.debug(f'MATCH (c:{account_type} {{name:"{user_owned}"}}) SET c.owned=True RETURN c.name AS name')
result = tx.run(f'MATCH (c:{account_type} {{name:"{user_owned}"}}) SET c.owned=True RETURN c.name AS name')
logger.debug(f"MATCH (c:{account_type} {{name:'{user_owned}'}}) SET c.owned=True RETURN c.name AS name")
result = tx.run(f"MATCH (c:{account_type} {{name:'{user_owned}'}}) SET c.owned=True RETURN c.name AS name")
logger.highlight(f"Node {user_owned} successfully set as owned in BloodHound")
except AuthError:
logger.fail(f"Provided Neo4J credentials ({config.get('BloodHound', 'bh_user')}:{config.get('BloodHound', 'bh_pass')}) are not valid.")
Expand All @@ -63,7 +71,10 @@ def add_user_bh(user, domain, logger, config):
logger.fail(f"Neo4J does not seem to be available on {uri}.")
return
except Exception as e:
logger.fail(f"Unexpected error with Neo4J: {e}")
logger.fail("Account not found on the domain")
if "Domain not found in bloodhound" in str(e):
Marshall-Hallenbeck marked this conversation as resolved.
Show resolved Hide resolved
logger.fail("Neo4J Error: Domain not found in BloodHound. Please specify the FQDN ex:domain.local.")
else:
logger.fail(f"Unexpected error with Neo4J: {e}")
logger.fail("Account not found on the domain")
return
driver.close()