-
Notifications
You must be signed in to change notification settings - Fork 394
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
40 changed files
with
965 additions
and
258 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
class NXCModule: | ||
""" | ||
Enumerate SQL Server users with impersonation rights | ||
Module by deathflamingo | ||
""" | ||
|
||
name = "enum_impersonate" | ||
description = "Enumerate users with impersonation privileges" | ||
supported_protocols = ["mssql"] | ||
opsec_safe = True | ||
multiple_hosts = True | ||
|
||
def __init__(self): | ||
self.mssql_conn = None | ||
self.context = None | ||
|
||
def on_login(self, context, connection): | ||
self.context = context | ||
self.mssql_conn = connection.conn | ||
impersonate_users = self.get_impersonate_users() | ||
if impersonate_users: | ||
self.context.log.success("Users with impersonation rights:") | ||
for user in impersonate_users: | ||
self.context.log.display(f" - {user}") | ||
else: | ||
self.context.log.fail("No users with impersonation rights found.") | ||
|
||
def get_impersonate_users(self) -> list: | ||
""" | ||
Fetches a list of users with impersonation rights. | ||
Returns | ||
------- | ||
list: List of user names. | ||
""" | ||
query = """ | ||
SELECT DISTINCT b.name | ||
FROM sys.server_permissions a | ||
INNER JOIN sys.server_principals b | ||
ON a.grantor_principal_id = b.principal_id | ||
WHERE a.permission_name LIKE 'IMPERSONATE%' | ||
""" | ||
res = self.mssql_conn.sql_query(query) | ||
return [user["name"] for user in res] if res else [] | ||
def options(self, context, module_options): | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
class NXCModule: | ||
""" | ||
Enumerate SQL Server linked servers | ||
Module by deathflamingo, NeffIsBack | ||
""" | ||
|
||
name = "enum_links" | ||
description = "Enumerate linked SQL Servers and their login configurations." | ||
supported_protocols = ["mssql"] | ||
opsec_safe = True | ||
multiple_hosts = True | ||
|
||
def __init__(self): | ||
self.mssql_conn = None | ||
self.context = None | ||
|
||
def options(self, context, module_options): | ||
pass | ||
|
||
def on_login(self, context, connection): | ||
self.context = context | ||
self.mssql_conn = connection.conn | ||
linked_servers = self.get_linked_servers() | ||
if linked_servers: | ||
self.context.log.success("Linked servers found:") | ||
for server in linked_servers: | ||
self.context.log.display(f" - {server}") | ||
else: | ||
self.context.log.fail("No linked servers found.") | ||
|
||
def on_admin_login(self, context, connection): | ||
res = self.mssql_conn.sql_query("EXEC sp_helplinkedsrvlogin") | ||
srvs = [srv for srv in res if srv["Local Login"] != "NULL"] | ||
if not srvs: | ||
self.context.log.fail("No linked servers found.") | ||
return | ||
self.context.log.success("Linked servers found:") | ||
for srv in srvs: | ||
self.context.log.display(f"Linked server: {srv['Linked Server']}") | ||
self.context.log.display(f" - Local login: {srv['Local Login']}") | ||
self.context.log.display(f" - Remote login: {srv['Remote Login']}") | ||
|
||
def get_linked_servers(self) -> list: | ||
""" | ||
Fetches a list of linked servers. | ||
Returns | ||
------- | ||
list: List of linked server names. | ||
""" | ||
query = "EXEC sp_linkedservers;" | ||
res = self.mssql_conn.sql_query(query) | ||
return [server["SRV_NAME"] for server in res] if res else [] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
class NXCModule: | ||
""" | ||
Enumerate SQL Server logins | ||
Module by deathflamingo | ||
""" | ||
|
||
name = "enum_logins" | ||
description = "Enumerate SQL Server logins" | ||
supported_protocols = ["mssql"] | ||
opsec_safe = True | ||
multiple_hosts = True | ||
|
||
def __init__(self): | ||
self.mssql_conn = None | ||
self.context = None | ||
|
||
def on_login(self, context, connection): | ||
self.context = context | ||
self.mssql_conn = connection.conn | ||
logins = self.get_logins() | ||
if logins: | ||
self.context.log.success("Logins found:") | ||
for login in logins: | ||
self.context.log.display(f" - {login}") | ||
else: | ||
self.context.log.fail("No logins found.") | ||
|
||
def get_logins(self) -> list: | ||
""" | ||
Fetches a list of SQL Server logins. | ||
Returns | ||
------- | ||
list: List of login names. | ||
""" | ||
query = "SELECT name FROM sys.server_principals WHERE type_desc = 'SQL_LOGIN';" | ||
res = self.mssql_conn.sql_query(query) | ||
return [login["name"] for login in res] if res else [] | ||
def options(self, context, module_options): | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
class NXCModule: | ||
""" | ||
Execute commands on linked servers | ||
Module by deathflamingo | ||
""" | ||
|
||
name = "exec_on_link" | ||
description = "Execute commands on a SQL Server linked server" | ||
supported_protocols = ["mssql"] | ||
opsec_safe = False | ||
multiple_hosts = False | ||
|
||
def __init__(self): | ||
self.mssql_conn = None | ||
self.context = None | ||
self.linked_server = None | ||
self.command = None | ||
|
||
def options(self, context, module_options): | ||
""" | ||
LINKED_SERVER: The name of the linked server to execute the command on. | ||
COMMAND: The command to execute on the linked server. | ||
""" | ||
if "LINKED_SERVER" in module_options: | ||
self.linked_server = module_options["LINKED_SERVER"] | ||
if "COMMAND" in module_options: | ||
self.command = module_options["COMMAND"] | ||
|
||
def on_login(self, context, connection): | ||
self.context = context | ||
self.mssql_conn = connection.conn | ||
if not self.linked_server or not self.command: | ||
self.context.log.fail("Please specify both LINKED_SERVER and COMMAND options.") | ||
return | ||
|
||
self.execute_on_link() | ||
|
||
def execute_on_link(self): | ||
"""Executes the specified command on the linked server.""" | ||
query = f"EXEC ('{self.command}') AT [{self.linked_server}];" | ||
result = self.mssql_conn.sql_query(query) | ||
self.context.log.display(f"Command output: {result}") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
class NXCModule: | ||
""" | ||
Enable or disable xp_cmdshell on a linked SQL server | ||
Module by deathflamingo | ||
""" | ||
|
||
name = "link_enable_xp" | ||
description = "Enable or disable xp_cmdshell on a linked SQL server" | ||
supported_protocols = ["mssql"] | ||
opsec_safe = False | ||
multiple_hosts = False | ||
|
||
def __init__(self): | ||
self.action = None | ||
self.linked_server = None | ||
|
||
def options(self, context, module_options): | ||
""" | ||
Defines the options for enabling or disabling xp_cmdshell on the linked server. | ||
ACTION Specifies whether to enable or disable: | ||
- enable (default) | ||
- disable | ||
LINKED_SERVER The name of the linked SQL server to target. | ||
""" | ||
self.action = module_options.get("ACTION", "enable") | ||
self.linked_server = module_options.get("LINKED_SERVER") | ||
|
||
def on_login(self, context, connection): | ||
self.context = context | ||
self.mssql_conn = connection.conn | ||
if not self.linked_server: | ||
self.context.log.fail("Please provide a linked server name using the LINKED_SERVER option.") | ||
return | ||
|
||
# Enable or disable xp_cmdshell based on action | ||
if self.action == "enable": | ||
self.enable_xp_cmdshell() | ||
elif self.action == "disable": | ||
self.disable_xp_cmdshell() | ||
else: | ||
self.context.log.fail(f"Unknown action: {self.action}") | ||
|
||
def enable_xp_cmdshell(self): | ||
"""Enable xp_cmdshell on the linked server.""" | ||
query = f"EXEC ('sp_configure ''show advanced options'', 1; RECONFIGURE;') AT [{self.linked_server}]" | ||
self.context.log.display(f"Enabling advanced options on {self.linked_server}...") | ||
out = self.query_and_get_output(query) | ||
query = f"EXEC ('sp_configure ''xp_cmdshell'', 1; RECONFIGURE;') AT [{self.linked_server}]" | ||
self.context.log.display(f"Enabling xp_cmdshell on {self.linked_server}...") | ||
out = self.query_and_get_output(query) | ||
self.context.log.display(out) | ||
self.context.log.success(f"xp_cmdshell enabled on {self.linked_server}") | ||
|
||
def disable_xp_cmdshell(self): | ||
"""Disable xp_cmdshell on the linked server.""" | ||
query = f"EXEC ('sp_configure ''xp_cmdshell'', 0; RECONFIGURE; sp_configure ''show advanced options'', 0; RECONFIGURE;') AT [{self.linked_server}]" | ||
self.context.log.display(f"Disabling xp_cmdshell on {self.linked_server}...") | ||
self.query_and_get_output(query) | ||
self.context.log.success(f"xp_cmdshell disabled on {self.linked_server}") | ||
|
||
def query_and_get_output(self, query): | ||
"""Executes a query and returns the output.""" | ||
return self.mssql_conn.sql_query(query) |
Oops, something went wrong.