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 90 commits into
base: master
Choose a base branch
from
Open

Persistence directory #19815

wants to merge 90 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.

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