Skip to content

Persistence directory #19815

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

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

Persistence directory #19815

wants to merge 116 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
      • Moved to multi/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
      • Doesn't seem to print the cleanup script location
    • 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/yum_package_manager.rb
    • modules/exploits/multi/persistence/at.rb
    • modules/exploits/multi/persistence/sshkey.rb
      • only seems to work when run with pry
    • modules/exploits/multi/persistence/obsidian_plugin.rb
    • modules/exploits/osx/persistence/launch_plist.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/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
    • Make sticky_keys work with this
  • Timeout error when modules are left running (overnight) [-] Exploit failed [timeout-expired]: Timeout::Error execution expired

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.


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
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.

@h00die h00die mentioned this pull request Feb 21, 2025
4 tasks
@dledda-r7
Copy link
Contributor

Hi @h00die,
cron persistence is working for me:

msf6 exploit(multi/persistence/cron) > run
[*] Exploit running as background job 1.
[*] Exploit completed, but no session was created.
msf6 exploit(multi/persistence/cron) > 
[*] Running automatic check ("set AutoCheck false" to disable)
[+] The target appears to be vulnerable. Cron timing is valid, no cron.deny entries found
[+] Payload will be triggered when cron time is reached
[*] Meterpreter-compatible Cleaup RC file: /home/kali/.msf4/logs/persistence/172.25.213.195_20250227.2929/172.25.213.195_20250227.2929.rc

msf6 exploit(multi/persistence/cron) > cat /home/kali/.msf4/logs/persistence/172.25.213.195_20250227.2929/172.25.213.195_20250227.2929.rc
[*] exec: cat /home/kali/.msf4/logs/persistence/172.25.213.195_20250227.2929/172.25.213.195_20250227.2929.rc

upload /home/kali/.msf4/loot/20250227082929_default_172.25.213.195_crontab.root_875823.txt /var/spool/cron/crontabs/root
msf6 exploit(multi/persistence/cron) > 

what action was not working? maybe the OSX one?

Comment on lines 72 to 73
OptEnum.new('TARGET', [true, 'The target binary to add the exploit to.', 'SETHC', ['SETHC', 'UTILMAN', 'OSK', 'DISP']]),
# XXX this should be upgraded to drop a payload of our choosing instead
Copy link
Contributor

@dledda-r7 dledda-r7 Feb 27, 2025

Choose a reason for hiding this comment

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

@h00die, I have also investigated sticky_keys, looks like for some reason the mod.target is nil instead of be something like #<Msf::Module::Target:0x00007fbaf1e83088 @default_options=nil, @name="Automatic", @opts={}, @ret=nil, @save_registers=nil>

EDIT

Found the issue.

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

 #   Name                                       Potentially Vulnerable?  Check Result
 -   ----                                       -----------------------  ------------
 1   exploit/windows/persistence/ps_persist     Yes                      The service is running, but could not be validated. System likely vulnerable
 2   exploit/windows/persistence/registry       Yes                      The target is vulnerable.
 3   exploit/windows/persistence/s4u            Yes                      The service is running, but could not be validated. System likely vulnerable
 4   exploit/windows/persistence/service        Yes                      The target appears to be vulnerable.
 5   exploit/windows/persistence/sticky_keys    Yes                      The target appears to be vulnerable. Target is likely vulnerable
 6   exploit/windows/persistence/vss            Yes                      The target appears to be vulnerable. Target is likely vulnerable
 7   exploit/windows/persistence/wmi            Yes                      The target appears to be vulnerable. Target is likely vulnerable
 8   exploit/multi/persistence/obsidian_plugin  No                       The target is not exploitable. No vaults found
 9   exploit/multi/persistence/sshkey           No                       The target is not exploitable. Unable to read SSH config: /etc/ssh/sshd_config
 10  exploit/windows/persistence/registry_vbs   No                       The target is not exploitable. Path doesn't exists: /tmp/

[*] Post module execution completed
msf6 post(multi/recon/persistence_suggester) > 

This datastore option breaks the target informations.

Suggested change
OptEnum.new('TARGET', [true, 'The target binary to add the exploit to.', 'SETHC', ['SETHC', 'UTILMAN', 'OSK', 'DISP']]),
# XXX this should be upgraded to drop a payload of our choosing instead
OptEnum.new('BIN_TARGET', [true, 'The target binary to add the exploit to.', 'SETHC', ['SETHC', 'UTILMAN', 'OSK', 'DISP']]),
# XXX this should be upgraded to drop a payload of our choosing instead

Copy link
Contributor Author

Choose a reason for hiding this comment

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

good find!

@msutovsky-r7 msutovsky-r7 self-assigned this Apr 8, 2025
@msutovsky-r7
Copy link
Contributor

Hi @h00die, I'll move on with other persistence PRs that have been blocked. You can rebase this PR once it's done. Let me know if you would need help moving forward with this PR!

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
5 participants