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
Module to read/write registry key security descriptor remotely #19115
Module to read/write registry key security descriptor remotely #19115
Conversation
def auxiliary_commands | ||
{ | ||
'read' => 'Read a Windows registry security descriptor', | ||
'write' => 'Write a Windows registry security descriptor' | ||
} | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this be removed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, absolutely, these are not necessary anymore. I also removed it from the template. Thank you!
83d19b4
to
3e351e8
Compare
- This will bring in the GetKeySecurity and SetKeySecurity MS-RRP structures
- remove `#auxiliary_commands`, it is not necessary anymore - move the connection logic to a separate method - make sure the connection to Winreg is setup when using direct `read` and `write` commands - fix wrong method call to `save_to_file`
3e351e8
to
6849e90
Compare
case action.name | ||
when 'READ' | ||
cmd_read | ||
when 'WRITE' | ||
cmd_write | ||
else |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So prefixing these methods with cmd_
means they will be exposed as custom commands. Now when testing them without arguments, they seem to be working just fine, however they should also accept inline datastore options.
See:
metasploit-framework.pr (S:1 J:0) auxiliary(admin/registry_security_descriptor) > write
[+] Security descriptor set for HKLM\SECURITY\Policy\PolEKList
metasploit-framework.pr (S:1 J:0) auxiliary(admin/registry_security_descriptor) > write SECURITY_INFORMAITON=4
[-] Error while running command write: wrong number of arguments (given 1, expected 0)
Call stack:
/home/smcintyre/Repositories/metasploit-framework.pr/modules/auxiliary/admin/registry_security_descriptor.rb:145:in `cmd_write'
/home/smcintyre/Repositories/metasploit-framework.pr/lib/msf/ui/console/module_action_commands.rb:40:in `method_missing'
/home/smcintyre/Repositories/metasploit-framework.pr/lib/rex/ui/text/dispatcher_shell.rb:582:in `run_command'
/home/smcintyre/Repositories/metasploit-framework.pr/lib/rex/ui/text/dispatcher_shell.rb:531:in `block in run_single'
/home/smcintyre/Repositories/metasploit-framework.pr/lib/rex/ui/text/dispatcher_shell.rb:525:in `each'
/home/smcintyre/Repositories/metasploit-framework.pr/lib/rex/ui/text/dispatcher_shell.rb:525:in `run_single'
/home/smcintyre/Repositories/metasploit-framework.pr/lib/rex/ui/text/shell.rb:165:in `block in run'
/home/smcintyre/Repositories/metasploit-framework.pr/lib/rex/ui/text/shell.rb:309:in `block in with_history_manager_context'
/home/smcintyre/Repositories/metasploit-framework.pr/lib/rex/ui/text/shell/history_manager.rb:33:in `with_context'
/home/smcintyre/Repositories/metasploit-framework.pr/lib/rex/ui/text/shell.rb:306:in `with_history_manager_context'
/home/smcintyre/Repositories/metasploit-framework.pr/lib/rex/ui/text/shell.rb:133:in `run'
/home/smcintyre/Repositories/metasploit-framework.pr/lib/metasploit/framework/command/console.rb:54:in `start'
/home/smcintyre/Repositories/metasploit-framework.pr/lib/metasploit/framework/command/base.rb:82:in `start'
./msfconsole:23:in `<main>'
metasploit-framework.pr (S:1 J:0) auxiliary(admin/registry_security_descriptor) >
To fix this, a different prefix should be used. I recommend replacing cmd_
with action_
. With that change in place, this work as expected:
metasploit-framework.pr (S:1 J:0) auxiliary(admin/registry_security_descriptor) > read KEY=HKLM\\Security\\Policy
[*] Using existing session 1
[+] Raw security descriptor for HKLM\Security\Policy: 01000480000000000000000000000000140000000200340002000000000214003f000f00010100000000000512000000000218000000060001020000000000052000000020020000
[*] Auxiliary module execution completed
metasploit-framework.pr (S:1 J:0) auxiliary(admin/registry_security_descriptor) > read KEY=HKLM\\Security\\Policy\\PolEKList
[*] Using existing session 1
[+] Raw security descriptor for HKLM\Security\Policy\PolEKList: 01000480000000000000000000000000140000000200340002000000000214003f000f00010100000000000512000000000218000000060001020000000000052000000020020000
[*] Auxiliary module execution completed
metasploit-framework.pr (S:1 J:0) auxiliary(admin/registry_security_descriptor) >
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! Good catch!
def cmd_read | ||
do_connect unless @winreg | ||
|
||
fail_with(Failure::BadConfig, 'Unknown registry key, please set the `KEY` option') if datastore['KEY'].blank? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
def cmd_read | |
do_connect unless @winreg | |
fail_with(Failure::BadConfig, 'Unknown registry key, please set the `KEY` option') if datastore['KEY'].blank? | |
def action_read | |
fail_with(Failure::BadConfig, 'Unknown registry key, please set the `KEY` option') if datastore['KEY'].blank? |
Once this is renamed, you won't need to call do_connect
yourself because everything will go through the main #run
method. That'll also make sure that the session is disconnected in your ensure
block.
register_options( | ||
[ | ||
OptString.new('KEY', [ false, 'Registry key to read or write' ]), | ||
OptString.new('SD', [ false, 'Security Descriptor to write as a hex string' ], conditions: %w[ACTION == WRITE]), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OptString.new('SD', [ false, 'Security Descriptor to write as a hex string' ], conditions: %w[ACTION == WRITE]), | |
OptString.new('SD', [ false, 'Security Descriptor to write as a hex string' ], conditions: %w[ACTION == WRITE], regex: /^([a-fA-F0-9]{2})+$/), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, everything is looking good to me now. I was able to test a few cases and everything seems to be working as intended. I'll have this landed shortly.
Testing Output
metasploit-framework (S:0 J:0) auxiliary(admin/registry_security_descriptor) > read KEY='HKLM\SECURITY\Policy\PolEKList'
[*] Running module against 3.22.14.197
[+] 3.22.14.197:445 - Raw security descriptor for HKLM\SECURITY\Policy\PolEKList: 01000480480000005800000000000000140000000200340002000000000214003f000f0001010000000000051200000000021800000006000102000000000005200000002002000001020000000000052000000020020000010100000000000512000000
[*] Auxiliary module execution completed
metasploit-framework (S:0 J:0) auxiliary(admin/registry_security_descriptor) > read KEY='HKLM\SECURITY\Policy\PolEKList\DoesNotExist'
[*] Running module against 3.22.14.197
[-] 3.22.14.197:445 - Auxiliary failed: RubySMB::Dcerpc::Error::WinregError Error returned when opening subkey SECURITY\Policy\PolEKList\DoesNotExist: (0x00000002) ERROR_FILE_NOT_FOUND: The system cannot find the file specified.
[-] 3.22.14.197:445 - Call stack:
[-] 3.22.14.197:445 - /home/smcintyre/.rvm/gems/ruby-3.2.3@metasploit-framework/gems/ruby_smb-3.3.7/lib/ruby_smb/dcerpc/winreg.rb:124:in `open_key'
[-] 3.22.14.197:445 - /home/smcintyre/.rvm/gems/ruby-3.2.3@metasploit-framework/gems/ruby_smb-3.3.7/lib/ruby_smb/dcerpc/winreg.rb:466:in `get_key_security_descriptor'
[-] 3.22.14.197:445 - /home/smcintyre/Repositories/metasploit-framework.pr/modules/auxiliary/admin/registry_security_descriptor.rb:133:in `action_read'
[-] 3.22.14.197:445 - /home/smcintyre/Repositories/metasploit-framework.pr/modules/auxiliary/admin/registry_security_descriptor.rb:114:in `run'
[*] Auxiliary module execution completed
metasploit-framework (S:0 J:0) auxiliary(admin/registry_security_descriptor) > write SD=01000480480000005800000000000000140000000200340002000000000214003f000f0001010000000000051200000000021800000006000102000000000005200000002002000001020000000000052000000020020000010100000000000512000000
[*] Running module against 3.22.14.197
[-] 3.22.14.197:445 - Auxiliary aborted due to failure: unknown: Unable to set the security descriptor for HKLM\SECURITY\Policy\PolEKList: Error returned when setting the registry key: (0x00000005) ERROR_ACCESS_DENIED: Access is denied.
[*] Auxiliary module execution completed
metasploit-framework (S:0 J:0) auxiliary(admin/registry_security_descriptor) > write SD=01000480480000005800000000000000140000000200340002000000000214003f000f0001010000000000051200000000021800000006000102000000000005200000002002000001020000000000052000000020020000010100000000000512000000 SECuRITY_INFORMATION=4
[*] Running module against 3.22.14.197
[+] 3.22.14.197:445 - Security descriptor set for HKLM\SECURITY\Policy\PolEKList
[*] Auxiliary module execution completed
metasploit-framework (S:0 J:0) auxiliary(admin/registry_security_descriptor) >
733c014
Release NotesThis adds a module to read and write the security descriptor of Windows registry keys. |
This module reads or writes a Windows registry security descriptor remotely.
In READ mode, the
FILE
option can be set to specify where the security descriptor should be written to.The following format is used:
In WRITE mode, the
FILE
option can be used to specify the information needed to write the security descriptor to the remote registry. The file must follow the same format as described above.DO NOT MERGE YET.
This module is based on this branch will need this PR landed first. This PR only adds two files:
Verification Steps
use auxiliary/admin/registry_security_descriptor
run verbose=true rhost=<host> smbuser=<username> smbpass=<password> key=<registry key>
run verbose=true rhost=<host> smbuser=<username> smbpass=<password> key=<registry key> file=<file path>
run verbose=true rhost=<host> smbuser=<username> smbpass=<password> key=<registry key> action=write sd=<security descriptor as a hex string>
run verbose=true rhost=<host> smbuser=<username> smbpass=<password> file=<file path>
Scenarios
Read against Windows Server 2019
Write against Windows Server 2019
Note that the information security has been set to 4 (DACL_SECURITY_INFORMATION) to avoid an access denied error.
Write against Windows Server 2019 (from file)