Skip to content

Commit 72fee6a

Browse files
authored
Merge pull request Pennyw0rth#405 from 0xQRx/mssql-xp-shell-add-check
Mssql xp_cmdshell added "is enabled" check
2 parents a83c412 + c012e04 commit 72fee6a

1 file changed

Lines changed: 46 additions & 29 deletions

File tree

nxc/protocols/mssql/mssqlexec.py

Lines changed: 46 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@ def __init__(self, connection, logger):
66
self.mssql_conn = connection
77
self.logger = logger
88

9+
# Store the original state of options that have to be enabled/disabled in order to restore them later
10+
self.backuped_options = {}
11+
912
def execute(self, command):
1013
result = None
11-
try:
12-
self.logger.debug("Attempting to enable xp cmd shell")
13-
self.enable_xp_cmdshell()
14-
except Exception as e:
15-
self.logger.error(f"Error when attempting to enable x_cmdshell: {e}")
14+
15+
self.backup_and_enable("advanced options")
16+
self.backup_and_enable("xp_cmdshell")
17+
1618
try:
1719
cmd = f"exec master..xp_cmdshell '{command}'"
1820
self.logger.debug(f"Attempting to execute query: {cmd}")
@@ -27,42 +29,57 @@ def execute(self, command):
2729
except Exception as e:
2830
self.logger.error(f"Error when attempting to execute command via xp_cmdshell: {e}")
2931

30-
try:
31-
self.logger.debug("Attempting to disable xp cmd shell")
32-
self.disable_xp_cmdshell()
33-
except Exception as e:
34-
self.logger.error(f"[OPSEC] Error when attempting to disable xp_cmdshell: {e}")
35-
return result
32+
self.restore("xp_cmdshell")
33+
self.restore("advanced options")
3634

37-
def enable_xp_cmdshell(self):
38-
query = "exec master.dbo.sp_configure 'show advanced options',1;RECONFIGURE;exec master.dbo.sp_configure 'xp_cmdshell', 1;RECONFIGURE;"
39-
self.logger.debug(f"Executing query: {query}")
40-
self.mssql_conn.sql_query(query)
35+
return result
4136

42-
def disable_xp_cmdshell(self):
43-
query = "exec sp_configure 'xp_cmdshell', 0 ;RECONFIGURE;exec sp_configure 'show advanced options', 0 ;RECONFIGURE;"
44-
self.logger.debug(f"Executing query: {query}")
45-
self.mssql_conn.sql_query(query)
37+
def restore(self, option):
38+
try:
39+
if not self.backuped_options[option]:
40+
self.logger.debug(f"Option '{option}' was not enabled originally, attempting to disable it.")
41+
query = f"EXEC master.dbo.sp_configure '{option}', 0;RECONFIGURE;"
42+
self.logger.debug(f"Executing query: {query}")
43+
self.mssql_conn.sql_query(query)
44+
else:
45+
self.logger.debug(f"Option '{option}' was originally enabled, leaving it enabled.")
46+
except Exception as e:
47+
self.logger.error(f"[OPSEC] Error when attempting to restore option '{option}': {e}")
4648

47-
def enable_ole(self):
48-
query = "exec master.dbo.sp_configure 'show advanced options',1;RECONFIGURE;exec master.dbo.sp_configure 'Ole Automation Procedures', 1;RECONFIGURE;"
49-
self.logger.debug(f"Executing query: {query}")
50-
self.mssql_conn.sql_query(query)
49+
def backup_and_enable(self, option):
50+
try:
51+
self.backuped_options[option] = self.is_option_enabled("show advanced options")
52+
if not self.backuped_options[option]:
53+
self.logger.debug(f"Option '{option}' is disabled, attempting to enable it.")
54+
query = f"EXEC master.dbo.sp_configure '{option}', 1;RECONFIGURE;"
55+
self.logger.debug(f"Executing query: {query}")
56+
self.mssql_conn.sql_query(query)
57+
else:
58+
self.logger.debug(f"Option '{option}' is already enabled.")
59+
except Exception as e:
60+
self.logger.error(f"Error when checking/enabling option '{option}': {e}")
5161

52-
def disable_ole(self):
53-
query = "exec master.dbo.sp_configure 'show advanced options',1;RECONFIGURE;exec master.dbo.sp_configure 'Ole Automation Procedures', 0;RECONFIGURE;"
54-
self.logger.debug(f"Executing query: {query}")
55-
self.mssql_conn.sql_query(query)
62+
def is_option_enabled(self, option):
63+
query = f"EXEC master.dbo.sp_configure '{option}';"
64+
self.logger.debug(f"Checking if {option} is enabled: {query}")
65+
result = self.mssql_conn.sql_query(query)
66+
# Assuming the query returns a list of dictionaries with 'config_value' as the key
67+
self.logger.debug(f"{option} check result: {result}")
68+
if result and result[0]["config_value"] == 1:
69+
return True
70+
return False
5671

5772
def put_file(self, data, remote):
5873
try:
59-
self.enable_ole()
74+
self.backup_and_enable("advanced options")
75+
self.backup_and_enable("Ole Automation Procedures")
6076
hexdata = data.hex()
6177
self.logger.debug(f"Hex data to write to file: {hexdata}")
6278
query = f"DECLARE @ob INT;EXEC sp_OACreate 'ADODB.Stream', @ob OUTPUT;EXEC sp_OASetProperty @ob, 'Type', 1;EXEC sp_OAMethod @ob, 'Open';EXEC sp_OAMethod @ob, 'Write', NULL, 0x{hexdata};EXEC sp_OAMethod @ob, 'SaveToFile', NULL, '{remote}', 2;EXEC sp_OAMethod @ob, 'Close';EXEC sp_OADestroy @ob;"
6379
self.logger.debug(f"Executing query: {query}")
6480
self.mssql_conn.sql_query(query)
65-
self.disable_ole()
81+
self.restore("Ole Automation Procedures")
82+
self.restore("advanced options")
6683
except Exception as e:
6784
self.logger.debug(f"Error uploading via mssqlexec: {e}")
6885

0 commit comments

Comments
 (0)