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

Persistence directory #19815

Open
wants to merge 84 commits into
base: master
Choose a base branch
from
Open

Persistence directory #19815

wants to merge 84 commits into from

Conversation

h00die
Copy link
Contributor

@h00die h00die commented Jan 18, 2025

Fixes #19592 .

Move modules to a persistence directory

TO DO

  • Initial module modernization. To include: (mainly @h00die)
    1. change post modules to Msf::Exploit::Local
    2. add include Msf::Exploit::Local::Persistence, and prepend Msf::Exploit::Remote::AutoCheck
    3. add a check method
    4. rubocop
    5. add link to mitre attack
    6. add Notes field, DisclosureDate field
    7. convert any local path option to WritableDir or deregister it.
    8. add moved_from and Deprecated mixin.
    • modules/exploits/linux/persistence/apt_package_manager.rb
    • modules/exploits/linux/persistence/autostart.rb
    • modules/exploits/linux/persistence/bash_profile.rb
    • modules/exploits/linux/persistence/cron.rb
    • modules/exploits/linux/persistence/motd.rb
    • modules/exploits/linux/persistence/rc_local.rb
    • modules/exploits/linux/persistence/init_openrc.rb
    • modules/exploits/linux/persistence/init_systemd.rb
    • modules/exploits/linux/persistence/init_sysvinit.rb
    • modules/exploits/linux/persistence/init_upstart.rb
    • modules/exploits/linux/persistence/sshkey.rb
    • modules/exploits/linux/persistence/yum_package_manager.rb
    • modules/exploits/multi/persistence/obsidian_plugin.rb
    • modules/exploits/osx/persistence/launch_plist.rb
    • modules/exploits/unix/persistence/at.rb
    • modules/exploits/windows/persistence/persistence_exe.rb
    • modules/exploits/windows/persistence/registry_vbs.rb
    • modules/exploits/windows/persistence/process_exit_debugger.rb
    • modules/exploits/windows/persistence/ps_persist.rb
    • modules/exploits/windows/persistence/registry.rb
    • modules/exploits/windows/persistence/s4u.rb
    • modules/exploits/windows/persistence/service.rb
    • modules/exploits/windows/persistence/sshkey.rb
    • modules/exploits/windows/persistence/sticky_keys.rb
    • modules/exploits/windows/persistence/vss.rb
    • modules/exploits/windows/persistence/wmi.rb
  • Final module conversion: (mainly @dledda-r7)
    1. convert to the install_persistence and cleanup over rc-file
    2. any other code updates when taking a deep look through the run, and doing a run for documentation purposes
    • modules/exploits/linux/persistence/apt_package_manager.rb
    • modules/exploits/linux/persistence/autostart.rb
    • modules/exploits/linux/persistence/bash_profile.rb
    • modules/exploits/linux/persistence/cron.rb
    • modules/exploits/linux/persistence/motd.rb
    • modules/exploits/linux/persistence/rc_local.rb
    • modules/exploits/linux/persistence/init_openrc.rb
    • modules/exploits/linux/persistence/init_systemd.rb
    • modules/exploits/linux/persistence/init_sysvinit.rb
    • modules/exploits/linux/persistence/init_upstart.rb
    • modules/exploits/linux/persistence/sshkey.rb
    • modules/exploits/linux/persistence/yum_package_manager.rb (review the cleanup)
    • modules/exploits/multi/persistence/obsidian_plugin.rb
    • modules/exploits/osx/persistence/launch_plist.rb
    • modules/exploits/unix/persistence/at.rb
    • modules/exploits/windows/persistence/persistence_exe.rb
    • modules/exploits/windows/persistence/registry_vbs.rb
    • modules/exploits/windows/persistence/process_exit_debugger.rb
    • modules/exploits/windows/persistence/ps_persist.rb
    • modules/exploits/windows/persistence/registry.rb
    • modules/exploits/windows/persistence/s4u.rb
    • modules/exploits/windows/persistence/service.rb
    • modules/exploits/windows/persistence/sshkey.rb
    • modules/exploits/windows/persistence/sticky_keys.rb
    • modules/exploits/windows/persistence/vss.rb
    • modules/exploits/windows/persistence/wmi.rb
  • update docs
    1. move the files to the new locations
    2. add the new documentation for actions, options, and show a run (likely erase the old one since the paths and output will be updated)
    • modules/exploits/linux/persistence/apt_package_manager.rb
    • modules/exploits/linux/persistence/autostart.rb
    • modules/exploits/linux/persistence/bash_profile.rb
    • modules/exploits/linux/persistence/cron.rb
    • modules/exploits/linux/persistence/motd.rb
    • modules/exploits/linux/persistence/rc_local.rb
    • modules/exploits/linux/persistence/init_openrc.rb
    • modules/exploits/linux/persistence/init_systemd.rb
    • modules/exploits/linux/persistence/init_sysvinit.rb
    • modules/exploits/linux/persistence/init_upstart.rb
    • modules/exploits/linux/persistence/sshkey.rb
    • modules/exploits/linux/persistence/yum_package_manager.rb
    • modules/exploits/multi/persistence/obsidian_plugin.rb
    • modules/exploits/osx/persistence/launch_plist.rb
    • modules/exploits/unix/persistence/at.rb
    • modules/exploits/windows/persistence/persistence_exe.rb
    • modules/exploits/windows/persistence/registry_vbs.rb
    • modules/exploits/windows/persistence/process_exit_debugger.rb
    • modules/exploits/windows/persistence/ps_persist.rb
    • modules/exploits/windows/persistence/registry.rb
    • modules/exploits/windows/persistence/s4u.rb
    • modules/exploits/windows/persistence/service.rb
    • modules/exploits/windows/persistence/sshkey.rb
    • modules/exploits/windows/persistence/sticky_keys.rb
    • modules/exploits/windows/persistence/vss.rb
    • modules/exploits/windows/persistence/wmi.rb
  • Create an example module to help future devs
  • Create persistence_suggester (done, but sticky_keys seems to be wonky and @h00die doesnt know why)

Future Items

These will be converted to issues to do outside of this big change.

  • windows/registry_vbs.rb, windows/registry.rb, should be combined since they do nearly the same thing. one just drops a VBS script on system, the other writes it all into the registry
  • windows/persistence_exe.rb should be divided up. It can write to the registry, which duplicates the above, it can write a service, which duplicates windows/service.rb, and can make a task.
  • Theres a linux sshkey and windows sshkey, they should be combined and moved to multi.
  • linux/service.rb feels overly complex between the different service systems. I think breaking it into the following would be best: system_v_persistence.rb, upstart_persistence.rb, openrc_persistence.rb, systemd_persistence.rc.Maybe removing the code bits to be in data would help as well, but may not be needed once its broken up?
  • sshkey modules should execute ssh_login_pubkey. While there's a mixin for CheckModule, we may want something like PayloadModule or something similar to avoid rewriting code.

Assistance

Would love assistance and suggestions on this! Mainly at this point figuring out why setting Passive to true in the lib makes the modules exit at the end of code and not keep running (even though theyre running as a job)

@h00die
Copy link
Contributor Author

h00die commented Jan 20, 2025

I'm going to go ahead and mark this as ready for review, even though it's not. I'd like to get some eyes on the non-windows and LIB side of things. that way if there are changes, I can apply them globally instead of doing, redoing and reredoing the work. Docs are not ready, but again I only want to update them once.

@h00die h00die marked this pull request as ready for review January 20, 2025 23:12
@h00die h00die mentioned this pull request Jan 21, 2025
5 tasks
update_info(
info,
'DefaultOptions' => {
'WfsDelay' => 90_000, # 25hrs
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

@smcintyre-r7 smcintyre-r7 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the directory structure makes a lot of sense. Assuming the contents of the files haven't changed too much we should be able to process this pretty quickly. I like the checklist you have going with the modules that make sense to consolidate and agree that'd be a good move but doing so in a dedicated PR would probably help make review easier and faster.

},
# https://github.com/rapid7/metasploit-framework/pull/19676#discussion_r1907594308
'Stance' => Msf::Exploit::Stance::Passive
# 'Passive' => true # XXX when set, ignores wfsdelay and immediately exists after last command
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we'd want WfsDelay to be ignored so the module runs in the background indefinitely or until it's stopped.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with the above, just adding a little bit of extra context:
https://docs.metasploit.com/docs/development/developing-modules/guides/get-started-writing-an-exploit.html#non-required-fields

When setting 'Passive' => true the module will exit but you should be able to see the handler running as a job in the background withjobs -l.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its true and does, but not when the modules are moved to the persistence folder.


register_advanced_options(
[
OptString.new('WritableDir', [true, 'A directory where we can write files', '/tmp/'])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this isn't tied to a specific platform, what if we left the default value blank then determined it at runtime and set it to something sensible based on the target platform.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's fine, is there a way to set the value in the module /wo overwriting all the text? Something like
set_option('WritableDir', '/tmp/') or do I have to overwrite it like:
OptString.new('WritableDir', [true, 'A directory where we can write files', '/tmp/'])

@dledda-r7 dledda-r7 self-assigned this Jan 24, 2025
@dledda-r7
Copy link
Contributor

dledda-r7 commented Jan 28, 2025

Hello @h00die, I've investigated the functionality of the Passive = true.

First of all, looks like the ExploitDriver run as a job if the use_job is set or if the exploit is passive. reference.
The passive? is defined here and is taking in consideration only the Stance.
However this is where it gets interesting. setting the stance to passive will not work because the passive? appears to be overloaded by this: here. This mixin is included in PostMixin which is included inside the Msf::Exploit::Local class that is our base for the Persistences modules.
Besides that, where we can discuss if is correct or not to bypass the Stance for Msf::Exploit::Local modules, I think the final functionality of the background exploit is working as intended right now. Meaning that the payload handler should be running until the exploit is running, to bring an example, in the case of the exploit/multi/handler, the exploit is actually running an infinite loop to keep the handler running. Now my understanding is that you expect an infinite handler running, this cannot be achieved (probably) without adding some sort of infinite loop inside the exploit as the delays will be removed when setting the passive = true. Let me try to modify the Persistence mixin to have something like a background service running. I'll get back to you.

@dledda-r7
Copy link
Contributor

Created and added a persistence suggester, its basically local exploit suggester, just for persistence modules.

Sample run against a kali target:

[*] 111.111.1.111 - Valid modules for session 1:
============================

 #   Name                                           Potentially Vulnerable?  Check Result
 -   ----                                           -----------------------  ------------
 1   exploit/linux/persistence/autostart            Yes                      The service is running, but could not be validated. Xorg is installed, possible desktop install.
 2   exploit/linux/persistence/bash_profile         Yes                      The service is running, but could not be validated. Bash profile exists and is writable: /home/h00die/.bashrc
 3   exploit/linux/persistence/cron                 Yes                      The target appears to be vulnerable. Cron timing is valid, no cron.deny entries found
 4   exploit/linux/persistence/init_systemd         Yes                      The target appears to be vulnerable. /tmp/ is writable and systemd based
 5   exploit/linux/persistence/init_sysvinit        Yes                      The target appears to be vulnerable. /tmp/ is writable and System V based
 6   exploit/multi/persistence/obsidian_plugin      Yes                      The target appears to be vulnerable. Vaults found
 7   exploit/linux/persistence/apt_package_manager  No                       The target is not exploitable. /etc/apt/apt.conf.d/ not writable
 8   exploit/linux/persistence/init_openrc          No                       The target is not exploitable. Likely not an openrc based system
 9   exploit/linux/persistence/init_upstart         No                       The target is not exploitable. Likely not an upstart based system
 10  exploit/linux/persistence/motd                 No                       The target is not exploitable. /etc/update-motd.d/ does not exist
 11  exploit/linux/persistence/rc_local             No                       The target is not exploitable. /etc/rc.local does not exist
 12  exploit/linux/persistence/sshkey               No                       Cannot reliably check exploitability. Pubkey Authentication status unknown
 13  exploit/linux/persistence/yum_package_manager  No                       The target is not exploitable. /usr/local/bin/ not writable


[*] 111.111.1.111 - Current Session Info:
[*] 111.111.1.111 -   Session Type: meterpreter
[*] 111.111.1.111 -   Architecture: x64
[*] 111.111.1.111 -   Platform: linux

[*] 111.111.1.111 - Incompatible modules for session 1:
===================================

 #   Name                                               Reasons                                                                  Platform              Architecture              Session Type
 -   ----                                               -------                                                                  --------              ------------              ------------
 1   exploit/osx/persistence/launch_plist               Not Compatible (platform)                                                OSX                   x64                       meterpreter, shell
 2   exploit/unix/persistence/at                        Not Compatible (platform)                                                Unix                  cmd                       meterpreter, shell
 3   exploit/windows/persistence/persistence_exe        Missing required module options (REXEPATH). Not Compatible (platform)    Windows               cmd                       meterpreter
 4   exploit/windows/persistence/process_exit_debugger  Missing required module options (IMAGE_FILE). Not Compatible (platform)  Windows               x64, x86                  meterpreter
 5   exploit/windows/persistence/ps_persist             Not Compatible (platform)                                                Windows               x64, x86                  meterpreter
 6   exploit/windows/persistence/registry               Not Compatible (platform)                                                Windows               x64, x86                  meterpreter, shell
 7   exploit/windows/persistence/registry_vbs           Not Compatible (platform)                                                Windows               x64, x86                  meterpreter, shell
 8   exploit/windows/persistence/s4u                    Not Compatible (platform)                                                Windows               x64, x86                  meterpreter
 9   exploit/windows/persistence/service                Not Compatible (platform)                                                Windows               x64, x86                  meterpreter
 10  exploit/windows/persistence/sshkey                 Not Compatible (platform)                                                Windows               cmd                       meterpreter, shell
 11  exploit/windows/persistence/sticky_keys            Not Compatible (platform)                                                No defined platforms  No defined architectures  meterpreter, shell
 12  exploit/windows/persistence/vss                    Not Compatible (platform)                                                Windows               x64, x86                  meterpreter
 13  exploit/windows/persistence/wmi                    Not Compatible (platform)                                                Windows               x64, x86                  meterpreter

Unsure why sticky_keys isn't finding an Arch or Platform, they're clearly defined. Maybe @dledda-r7 when you get a chance you can take a look? Or at least back burner it till you get to updating that module

Sure, I am adding the cleanup + the install_persistence and I should be able to work on that.

Comment on lines +47 to +53
logs = ::File.join(Msf::Config.log_directory, 'persistence', Rex::FileUtils.clean_path(host + filenameinfo))
# Create the log directory
::FileUtils.mkdir_p(logs)

# logfile name
clean_rc = logs + ::File::Separator + Rex::FileUtils.clean_path(host + filenameinfo) + '.rc'
file_local_write(clean_rc, @clean_up_rc)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This ends up making folders that feel repetitive, for instance:
/root/.msf4/logs/persistence/111.111.1.11_20250204.4245/111.111.1.11_20250204.4245.rc
Maybe instead we should include the module name?/root/.msf4/logs/persistence/111.111.1.11/apt_package_manager_20250204.4245.rc
feels a little better to me. I don't think we need the Time on both the folder and file, but you may run the same persistence multiple times on a host so that made me think putting it on the file instead of the folder may be better.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good to add the module name on the rc file name, thinking how to do it from the mixin, but should be doable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Todo
Development

Successfully merging this pull request may close these issues.

RFC: establish a separate module category for persistence modules
4 participants