web

Safe Ninja

Punkty: 224
Rozwiązań: 17

Take a look at my service for hosting SAFE websites. Can you hack it?

https://safeninja.ecsc19.hack.cert.pl

If you want to send me something, use this SAFE channel:

https://safeninja.ecsc19.hack.cert.pl/report


Source code:

import binascii
import os
import flask
import bleach

from flask import Flask, render_template, request, abort
from flask_migrate import Migrate
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy.orm.exc import NoResultFound
from werkzeug.utils import secure_filename

app = Flask(__name__)


class Config(object):
    SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or 'sqlite:///app.db'
    SQLALCHEMY_TRACK_MODIFICATIONS = False


UPLOAD_FOLDER = './pages'
basedir = os.path.abspath(os.path.dirname(__file__))
app.config.from_object(Config)
db = SQLAlchemy(app)
migrate = Migrate(app, db)


class Page(db.Model):
    title = db.Column(db.String(1024), index=True)
    folder = db.Column(db.String(256), primary_key=True)
    filename = db.Column(db.String(1024), index=True)


@app.route('/', methods=['GET', 'POST'])
def new_page():
    if request.method == 'POST':
        file = request.files.get('content', None)
        title = request.form.get('title', None)
        if file:
            filename = secure_filename(file.filename)
            ext = filename.split('.')[1]
            if ext in ['htm', 'html', 'xhtml']:
                folder = binascii.b2a_hex(os.urandom(32)).decode('ascii')
                path = os.path.join('./templates', UPLOAD_FOLDER, folder)

                content = file.read().decode('utf8')

                if title:
                    content = '<title>{{ title }}</title>' + content

                bad_characters = ''''"()|'''
                safe_content = bleach.clean(content, tags=bleach.sanitizer.ALLOWED_TAGS+['title'])
                for character in bad_characters:
                    safe_content = safe_content.replace(character, '')

                os.mkdir(path)

                with open(os.path.join(path, filename), 'w') as f:
                    f.write(safe_content)

                p = Page(title=title, folder=folder, filename=filename)
                db.session.add(p)
                db.session.commit()

                return render_template('form.html', page='/page/{}'.format(folder))
    return render_template('form.html')


@app.route('/page/<idx>')
def view_page(idx):
    try:
        page = Page.query.filter(Page.folder == idx).one()
    except NoResultFound:
        abort(404)

    resp = flask.Response(render_template(os.path.join(UPLOAD_FOLDER, page.folder, page.filename), title=page.title))
    resp.headers['Content-Security-Policy'] = "default-src 'self'"
    return resp

Format flagi: ecsc19{litery_cyfry_i_znaki_specjalne}.

Aby wysłać flagę, musisz się zalogować.