# Tokyo Western 2018: pysandbox
__Tags:__ `misc` 
This sandbox uses python's `ast` module to parse the input string to its corresponding _abstract syntax tree_. This is what python uses to represent scripts during runtime.
A quick reading of the server scripts shows that when check encounters a `Call` or `Attribute` in the expression, it will be considered invalid.
```python# Allowed1 + 2[1, 2]
# Not Allowedlen([1, 2])[1, 2].append(3)''.__class__```
The incorrect way to approach this problem is to look for ways to be able to do this __without__ `Call`. Instead, we should look for areas in the tree __not seen by `check`__.
The task was nice enough to put a comment that can be found from python's `ast` [module documentation](https://docs.python.org/2/library/ast.html).
Comment```expr = BoolOp(boolop op, expr* values)        | BinOp(expr left, operator op, expr right)        | UnaryOp(unaryop op, expr operand)        | Lambda(arguments args, expr body)        | IfExp(expr test, expr body, expr orelse)```
Implemented Checks```python    attributes = {            'BoolOp': ['values'],            'BinOp': ['left', 'right'],            'UnaryOp': ['operand'],            'Lambda': ['body'],            'IfExp': ['test', 'body', 'orelse']		...```
These list down the different components of a particular expression, and the `attributes` dictionary shows the parts that `check` traverses. We compare the two and identify several parts that are not checked.
Here are some examples:
| Original                                             | Implemented Checks    | Unchecked parts ||------------------------------------------------------|-----------------------:|-----------------:|| Lambda(arguments args, expr body)                    | 'Lambda': ['body']    | args            || ListComp(expr elt, comprehension* generators)        | 'ListComp': ['elt']   | generators      || Subscript(expr value, slice slice, expr_context ctx) | Subscript': ['value'] | slice, ctx      |
.
Based on this we can infer that any `Call` in those parts will not be checked.
All of the unchecked parts can be used to hide calls. Here are two ways of getting the flags based on the findings above:
### Using List Comprehensions
```[e for e in list(open('flag'))]```
### Using Subscript
```[][sys.stdout.write(open('flag').read())]```
### Note of Flag2
For the second flag, it is really the same thing, but the `attributes` inside the `check` function is more complete.
```python        attributes = {            'BoolOp': ['values'],            'BinOp': ['left', 'right'],            'UnaryOp': ['operand'],            'Lambda': ['body'],            'IfExp': ['test', 'body', 'orelse'],            'Dict': ['keys', 'values'],            'Set': ['elts'],            'ListComp': ['elt', 'generators'],            'SetComp': ['elt', 'generators'],            'DictComp': ['key', 'value', 'generators'],            'GeneratorExp': ['elt', 'generators'],            'Yield': ['value'],            'Compare': ['left', 'comparators'],            'Call': False, # call is not permitted            'Repr': ['value'],            'Num': True,            'Str': True,            'Attribute': False, # attribute is also not permitted            'Subscript': ['value'],            'Name': True,            'List': ['elts'],            'Tuple': ['elts'],            'Expr': ['value'], # root node            'comprehension': ['target', 'iter', 'ifs'],        }
```