def load(app):
    # upgrade()
    app.db.create_all()
    CHALLENGE_CLASSES["steam"] = SteamChallenge
    register_plugin_assets_directory(
        app, base_path="/plugins/steam_challenge/assets/"
    )

    register_user_page_menu_bar("Steam Keys", "steamkeys")
    blueprint = Blueprint(
        "steam_challenge",
        __name__,
        template_folder="templates",
        static_folder="assets"
    )
    @blueprint.route("/steamkeys", methods=["GET", "POST"])
    @require_verified_emails
    @authed_only
    def view_keys():
        user = get_current_user()
        chals = SteamChallengeModel.query.filter_by(first_solver=user.account_id).order_by(SteamChallengeModel.id.asc()).all()
        my_keys = []
        for chal in chals:
            d = SteamChallenge.read(chal)
            d["steam_key"] = chal.steam_key
            d["steam_gamename"] = chal.steam_gamename
            my_keys.append(d)

        return render_template("steamkeys.html", keys=my_keys)
    app.register_blueprint(blueprint)
def load(app):
    # upgrade()
    app.db.create_all()
    CHALLENGE_CLASSES['lah'] = LahChallengeClass
    register_plugin_assets_directory(app, base_path='/plugins/lah_challenges/assets/')
    global APP_REF
    APP_REF = app
    scheduler.start()
    atexit.register(lambda: scheduler.shutdown())

    app.register_blueprint(lah_print)
    register_user_page_menu_bar("Unlocking", "/unlock")
    register_plugin_script("/plugins/lah_challenges/assets/lah_challenge_injector.js")
Esempio n. 3
0
def load(app):
    #https://github.com/blueimp/JavaScript-MD5/
    #https://github.com/Caligatio/jsSHA
    #https://github.com/beatgammit/base64-js/
    register_plugin_assets_directory(app,
                                     base_path='/plugins/CTFd-hasher/assets/')

    #abc - only works on modified server.
    #register_user_page_menu_bar(name='Hasher', route='/CTFd-hasher', target='_blank')
    register_user_page_menu_bar(name='Hasher', route='/CTFd-hasher')

    @app.route('/CTFd-hasher', methods=['GET'])
    def hash():
        return render_template('page.html',
                               content="""
<script src='/themes/original/static/js/vendor/jquery.min.js' type='text/javascript'></script>
<script src='/plugins/CTFd-hasher/assets/md5.min.js' type='text/javascript'></script>
<script src='/plugins/CTFd-hasher/assets/base64js.min.js' type='text/javascript'></script>
<script src='/plugins/CTFd-hasher/assets/sha.js' type='text/javascript'></script>
<h1>Hash a value</h1>
<input id='valuetohash' style='width: 80%;'></input>&nbsp;
<button id='hash'>go</button><br/><br/>
<textarea id='output' style='width: 80%;'></textarea>&nbsp;
<button id='copy' style='position:relative; top: -8px;'>copy</button>
<script>
    $(function() {
        $('#hash').click( function()
            {
                var val = $('#valuetohash').val().trim();
                //var hash = md5(val);
                var shaObj = new jsSHA('SHA-256', 'TEXT');
                shaObj.update(val);
                var hash = shaObj.getHash('B64');
                $('#output').html(hash);
            }
        );

        $('#copy').click( function()
            {
                var $temp = $('<input>');
                $('body').append($temp);
                $temp.val($('#output').text()).select();
                document.execCommand('copy');
                $temp.remove();
            }
        );
    });
</script>
""")

    utils.hasher = hash
Esempio n. 4
0
def load(app):
    dir_path = os.path.dirname(os.path.realpath(__file__))

    db.create_all()

    register_plugin_assets_directory(
        app, base_path="/plugins/CTFd-pwn-college-plugin/assets/")

    CHALLENGE_CLASSES["docker"] = DockerChallenge

    FLAG_CLASSES["user"] = UserFlag

    ssh_key_template_path = os.path.join(dir_path, "assets", "ssh_key",
                                         "settings.html")
    override_template("settings.html", open(ssh_key_template_path).read())
    app.view_functions["views.settings"] = ssh_key_settings
    Forms.keys = {"SSHKeyForm": SSHKeyForm}

    scoreboard_template_path = os.path.join(dir_path, "assets", "scoreboard",
                                            "scoreboard.html")
    override_template("scoreboard.html", open(scoreboard_template_path).read())
    app.view_functions["scoreboard.listing"] = scoreboard_listing

    blueprint = Blueprint("pwncollege_api", __name__)
    api = Api(blueprint,
              version="v1",
              doc=current_app.config.get("SWAGGER_UI"))
    api.add_namespace(docker_namespace, "/docker")
    api.add_namespace(user_flag_namespace, "/user_flag")
    api.add_namespace(ssh_key_namespace, "/ssh_key")
    api.add_namespace(download_namespace, "/download")
    api.add_namespace(terminal_namespace, "/terminal")
    api.add_namespace(binary_ninja_namespace, "/binary_ninja")
    api.add_namespace(belts_namespace, "/belts")
    app.register_blueprint(blueprint, url_prefix="/pwncollege_api/v1")

    app.register_blueprint(download)

    app.register_blueprint(terminal)
    register_user_page_menu_bar("Terminal", "/terminal")

    app.register_blueprint(grades)
    register_user_page_menu_bar("Grades", "/grades")
    register_admin_plugin_menu_bar("Grades", "/grades/all")
Esempio n. 5
0
def test_register_user_page_menu_bar():
    """
    Test that the register_user_page_menu_bar() properly inserts into HTML and get_user_page_menu_bar() returns the
    proper list.
    """
    app = create_ctfd()
    with app.app_context():
        register_user_page_menu_bar(title='test_user_menu_link', route='/test_user_href')

        with app.test_client() as client:
            r = client.get('/')

        output = r.get_data(as_text=True)
        assert '/test_user_href' in output
        assert 'test_user_menu_link' in output

        menu_item = get_user_page_menu_bar()[0]
        assert menu_item.title == 'test_user_menu_link'
        assert menu_item.route == '/test_user_href'
    destroy_ctfd(app)
Esempio n. 6
0
def test_register_user_page_menu_bar():
    """
    Test that the register_user_page_menu_bar() properly inserts into HTML and get_user_page_menu_bar() returns the
    proper list.
    """
    app = create_ctfd()
    with app.app_context():
        register_user_page_menu_bar(title="test_user_menu_link",
                                    route="/test_user_href")

        with app.test_client() as client:
            r = client.get("/")
            output = r.get_data(as_text=True)
            assert "/test_user_href" in output
            assert "test_user_menu_link" in output

        with app.test_request_context():
            menu_item = get_user_page_menu_bar()[0]
            assert menu_item.title == "test_user_menu_link"
            assert menu_item.route == "/test_user_href"
    destroy_ctfd(app)
def load(app):
    CTFd_API_v1.add_namespace(cases_namespace, '/acm_chall/cases')
    CTFd_API_v1.add_namespace(submissions_namespace, '/acm_chall/submissions')
    CTFd_API_v1.add_namespace(challenge_namespace, '/acm_chall/challenge')
    app.register_blueprint(
        views, url_prefix='/acm_chall'
    )

    app.db.create_all()
    CHALLENGE_CLASSES["icpc_dynamic"] = DynICPCChallenge
    register_plugin_assets_directory(
        app, base_path="/plugins/ctfd-acm-challenges/assets/"
    )
    register_admin_plugin_menu_bar(
        'ACM Challenges', '/acm_chall/admin/judge_queue'
    )
    register_user_page_menu_bar(
        'ACM Status', '/acm_chall/judge_queue'
    )

    def poll():
        try:
            id, lang, callback = running.get(timeout=1)
            with app.app_context():
                ExecutorBase.get_executor(
                    id, lang, callback
                ).run()
        except Empty:
            pass
        except KeyboardInterrupt:
            pass

    scheduler = APScheduler()
    scheduler.init_app(app)
    scheduler.start()
    scheduler.add_job(id='acm-executor', func=poll, trigger="interval", seconds=10)
Esempio n. 8
0
def load(app):
    app.db.create_all()
    announcements_blueprint = Blueprint('announcements_blueprint',
                                        __name__,
                                        template_folder='templates')
    register_user_page_menu_bar('Announcements', 'announcements')

    @announcements_blueprint.route('/admin/announcements',
                                   methods=['GET', 'POST'])
    @admins_only
    def view_admin_announcements():
        msg = ''
        msg_type = ''
        if (request.form.get('action', '') == 'hide' or request.form.get(
                'action', '') == 'show') and request.form.get('id', '') != '':
            action = request.form['action']
            id = int(request.form['id'])
            announcements_obj = Announcements.query.get(id)
            if announcements_obj:
                if action == 'hide':
                    announcements_obj.hidden = True
                elif action == 'show':
                    announcements_obj.hidden = False
                db.session.commit()
        elif request.form.get(
                'action', '') == 'delete' and request.form.get('id', '') != '':
            action = request.form['action']
            id = int(request.form['id'])
            announcements_obj = Announcements.query.get(id)
            db.session.delete(announcements_obj)
            db.session.commit()
            msg = 'Message deleted.'
            msg_type = 'info'
        elif request.form.get('action', '') == 'add' and request.form.get(
                'headline', '') != '' and request.form.get('body', '') != '':
            if request.form.get('hidden', '') == 'on':
                hidden = True
            else:
                hidden = False
            announcements_obj = Announcements(
                headline=request.form['headline'],
                hidden=hidden,
                body=request.form['body'],
                date=datetime.datetime.now())
            db.session.add(announcements_obj)
            db.session.commit()

            # send e-mail
            if request.form.get('emailnotification', '') == 'on':
                # get team emails
                teams = Teams.query.filter_by()

                body = request.form['headline'] + "\n\n" + request.form['body']
                # send mails to all teams
                if utils.can_send_mail():
                    for team in teams:
                        utils.sendmail(team.email, body)
                    msg += 'E-Mails sent.\n'
                else:
                    msg += 'Can\'t send e-mails. Please check your configuration.\n'
            msg += 'Message added.'
            msg_type = 'info'
        elif request.form.get('action', '') == 'update' and request.form.get(
                'headline', '') != '' and request.form.get(
                    'body', '') != '' and request.form.get('id', '') != '':
            if request.form.get('hidden', '') == 'on':
                hidden = True
            else:
                hidden = False
            if request.form.get('updateDate', '') == 'on':
                update_date = True
            else:
                update_date = False
            id = int(request.form['id'])
            announcements_obj = Announcements.query.get(id)
            if announcements_obj:
                announcements_obj.headline = request.form['headline']
                announcements_obj.hidden = hidden
                announcements_obj.body = request.form['body']
                if update_date:
                    announcements_obj.date = datetime.datetime.now()
                db.session.commit()
                msg = 'Message updated.'
                msg_type = 'info'

        announcements_res = Announcements.query.order_by(
            Announcements.date.desc()).all()
        return render_template('admin_announcements.html',
                               announcements_res=announcements_res,
                               msg=msg,
                               msg_type=msg_type)

    @announcements_blueprint.route('/admin/announcements/edit',
                                   methods=['POST'])
    @admins_only
    def view_admin_announcements_edit():
        if request.form.get('id', '') != '':
            id = int(request.form['id'])
            announcements_obj = Announcements.query.get(id)
            if announcements_obj:
                return render_template('admin_announcements_edit.html',
                                       announcements=announcements_obj)
        return redirect(url_for('admin/announcements'))

    @announcements_blueprint.route('/announcements', methods=['GET', 'POST'])
    def view_announcements():
        announcements_res = Announcements.query.order_by(
            Announcements.date.desc()).all()
        # check if there are any announcements (maybe all hidden)
        no_announcements = True
        for msg in announcements_res:
            if msg.hidden == False:
                no_announcements = False
                break

        return render_template('announcements.html',
                               announcements_res=announcements_res,
                               no_announcements=no_announcements)

    app.register_blueprint(announcements_blueprint)
Esempio n. 9
0
def load(app):
    # Create new locking_challenge table if necessary
    app.db.create_all()

    app.register_blueprint(support_ticket_templates)
    app.register_blueprint(support_ticket_static, url_prefix='/support-ticket')

    register_user_page_menu_bar('Support Ticket', 'support-ticket')
    # register_plugin_assets_directory(app, base_path="/plugins/CTFd_Support_Ticket/static/")

    if not os.path.exists(app.config['UPLOAD_FOLDER'] + '/support_ticket'):
        os.mkdir(app.config['UPLOAD_FOLDER'] + '/support_ticket')
    ticket_upload = (app.config['UPLOAD_FOLDER'] + '/support_ticket/')

    def get_challenges_by_categories():
        user = get_current_user()

        challenges = (Challenges.query.filter(
            and_(Challenges.state != "hidden",
                 Challenges.state != "locked")).order_by(
                     Challenges.value).all())

        if user:
            solve_ids = (Solves.query.with_entities(
                Solves.challenge_id).filter_by(
                    account_id=user.account_id).order_by(
                        Solves.challenge_id.asc()).all())
            solve_ids = set([value for value, in solve_ids])

            # TODO: Convert this into a re-useable decorator
            if is_admin():
                pass
            else:
                if config.is_teams_mode() and get_current_team() is None:
                    abort(403)
        else:
            solve_ids = set()

        response = []
        for challenge in challenges:
            if challenge.requirements:
                requirements = challenge.requirements.get("prerequisites", [])
                anonymize = challenge.requirements.get("anonymize")
                prereqs = set(requirements)
                if solve_ids >= prereqs:
                    pass
                else:
                    if anonymize:
                        response.append({
                            "id": challenge.id,
                            "name": "???",
                            "category": "???"
                        })
                    # Fallthrough to continue
                    continue

            response.append({
                "id": challenge.id,
                "name": challenge.name,
                "category": challenge.category
            })

        # Sort into categories
        categories = set(map(lambda x: x['category'], response))
        cats = []
        for c in categories:
            cats.append({
                'name':
                c,
                'challenges': [j for j in response if j['category'] == c]
            })
        db.session.close()
        return cats

    def get_ticket_for_user():
        user = get_current_user()
        tickets = (SupportTickets.query.filter(
            and_(SupportTickets.user_id == user.account_id)).order_by(
                SupportTickets.state))

        ticket_list = []
        for ticket in tickets:
            ticket_list.append({
                'id': ticket.id,
                'challenge_cat': ticket.challenge_cat,
                'challenge_name': ticket.challenge_name,
                'state': ticket.state
            })
        return ticket_list

    def get_ticket_for_admin():
        tickets = SupportTickets.query.all()
        ticket_list = []
        for ticket in tickets:
            ticket_list.append({
                'id': ticket.id,
                'challenge_cat': ticket.challenge_cat,
                'challenge_name': ticket.challenge_name,
                'creator': ticket.user,
                'state': ticket.state
            })
        return ticket_list

    def get_user_access(user):
        users = Users.query.all()
        admin_users = []
        user_users = []
        for u in users:
            if u.type == "admin":
                admin_users.append(u.name)
            elif u.type == "user":
                user_users.append(u.name)
        if user in admin_users:
            user = user + " (Admin)"
            return user
        elif user in user_users:
            user = user + " (User)"
            return user

    def upload_file(ticket_id, message_id, user, files):
        if not os.path.exists(ticket_upload + str(ticket_id)):
            os.mkdir(ticket_upload + str(ticket_id))
        time = datetime.now().time().strftime("%H:%M")
        for file in files:
            filename_temp = filename = secure_filename(file.filename)
            '''if os.path.exists(ticket_upload + str(ticket_id) + '/' + filename_temp):
                data = {
                    "user_id": user.id,
                    "title": "Upload Failed",
                    "content": "The file that you just uploaded already exist please change the name and try again."
                }
                send_notification(data=data, type="alert")
                return'''
            exist = True
            place = 0
            while exist:
                if os.path.exists(ticket_upload + str(ticket_id) + '/' +
                                  filename_temp):
                    place += 1
                    temp = filename.split('.')
                    filename_temp = '{name}({place}).{ext}'.format(
                        name=temp[0], place=place, ext=temp[1])
                else:
                    filename = filename_temp
                    exist = False
            file.save(ticket_upload + str(ticket_id) + '/' + filename)
            size = os.stat(
                (ticket_upload + str(ticket_id) + '/' + filename)).st_size
            uploaded_file = SupportTicketFiles(
                ticket_id=ticket_id,
                message_id=message_id,
                sender=user.name,
                time_sent=time,
                path=(ticket_upload + str(ticket_id) + '/' + filename),
                filename=filename,
                size=size)
            db.session.add(uploaded_file)
            db.session.commit()

    def send_notification(data, type, sound=True):
        data["sound"] = sound
        data["type"] = type
        schema = NotificationSchema()
        result = schema.load(data)

        if result.errors:
            return {"success": False, "errors": result.errors}, 400

        db.session.add(result.data)
        db.session.commit()

        response = schema.dump(result.data)

        response.data["type"] = type
        response.data["sound"] = sound
        print(response.data)
        current_app.events_manager.publish(data=response.data,
                                           type="notification")
        print("Success")

    @app.route('/support-ticket', methods=['GET', 'POST'])
    @during_ctf_time_only
    @require_verified_emails
    @check_challenge_visibility
    @require_team
    def user_tickets():
        if is_admin():
            return render_template('support_ticket_page.html',
                                   ticket_list=get_ticket_for_admin(),
                                   access="Admin")
        else:
            return render_template('support_ticket_page.html',
                                   ticket_list=get_ticket_for_user(),
                                   access="User")

    @app.route('/support-ticket/new', methods=['GET', 'POST'])
    def new_ticket():
        if request.method == 'POST':
            user = get_current_user()
            category = request.form['category']
            challenge = request.form['challenge']
            issue = request.form['issue']
            files = request.files.getlist('file')
            ticket = SupportTickets(user=user.name,
                                    user_id=user.account_id,
                                    challenge_cat=category,
                                    challenge_name=challenge,
                                    description=issue)
            db.session.add(ticket)
            db.session.commit()
            time = datetime.now().time().strftime("%H:%M")
            initial_message = SupportTicketConversation(ticket_id=ticket.id,
                                                        sender=user.name,
                                                        time_sent=time,
                                                        message=issue)
            db.session.add(initial_message)
            db.session.commit()
            if files[0]:
                files = request.files.getlist('file')
                upload_file(ticket.id, initial_message.id, user, files)
            return redirect('/support-ticket')
        ticket = SupportTickets.query.all()
        ids = []
        for t in ticket:
            ids.append(t.id)
        ticket_id = 1
        for i in range(1, len(ids)):
            if i not in ids:
                ticket_id = i
                break
        return render_template(
            'support_ticket_new_page.html',
            challenge_categories=get_challenges_by_categories(),
            ticket_id=ticket_id)

    @app.route('/support-ticket/view/<int:ticket_id>', methods=['GET', 'POST'])
    def view_ticket(ticket_id):
        if request.method == 'POST':
            ticket = SupportTickets.query.filter_by(id=ticket_id)
            message = request.form['message']
            time = datetime.now().time().strftime("%H:%M")
            user = get_current_user()
            files = request.files.getlist('file')
            for t in ticket:
                if request.form['ticket-state'] != t.state:
                    data = {
                        "user_id":
                        ticket[0].user_id,
                        "title":
                        "Ticket Status Change",
                        "content":
                        "The admins have changed your tickets status to {0}.".
                        format(request.form['ticket-state'])
                        if user.type == "admin" else
                        "A ticket has been changed to {0} by the user.".format(
                            request.form['ticket-state'])
                    }
                    send_notification(data=data, type="alert")
                    t.state = request.form['ticket-state']
                    db.session.commit()
            if message.replace(' ', '').replace('\n', '') != "" or files[0]:
                ticket_message = SupportTicketConversation(ticket_id=ticket_id,
                                                           sender=user.name,
                                                           time_sent=time,
                                                           message=message)
                db.session.add(ticket_message)
                db.session.commit()
                if user.type == "admin":
                    data = {
                        "user_id":
                        ticket[0].user_id,
                        "title":
                        "New Ticket Message",
                        "content":
                        "You have a new message from the admins in one of your tickets."
                    }
                    send_notification(data=data, type="alert")
            if files[0]:
                files = request.files.getlist('file')
                upload_file(ticket_id, ticket_message.id, user, files)
            return redirect(url_for("view_ticket", ticket_id=ticket_id))

        ticket = SupportTickets.query.filter_by(id=ticket_id).first_or_404()
        ticket_message = SupportTicketConversation.query.filter_by(
            ticket_id=ticket_id)
        ticket_info = {}
        ticket_conversation = []
        ticket_info.update({
            "category": ticket.challenge_cat,
            "challenge": ticket.challenge_name,
            "description": ticket.description,
            "state": ticket.state
        })
        for message_info in ticket_message:
            message_files = SupportTicketFiles.query.filter_by(
                message_id=message_info.id).all()
            file_list = []
            for file in message_files:
                file_list.append({file.id: file.filename})
            if message_info.message != '' or len(file_list) > 0:
                ticket_conversation.append({
                    "id":
                    message_info.id,
                    "sender":
                    get_user_access(message_info.sender),
                    "time":
                    message_info.time_sent,
                    "message":
                    message_info.message,
                    "files":
                    file_list
                })
        if is_admin():
            return render_template('support_ticket_view_page.html',
                                   ticket_info=ticket_info,
                                   ticket_conversation=ticket_conversation,
                                   ticket=ticket_id,
                                   access="Admin")
        else:
            return render_template('support_ticket_view_page.html',
                                   ticket_info=ticket_info,
                                   ticket_conversation=ticket_conversation,
                                   ticket=ticket_id,
                                   access="User")

    @app.route('/support-ticket/download-file/<int:file_id>/<string:filename>')
    def download_file(file_id, filename):
        file = SupportTicketFiles.query.filter(
            and_(SupportTicketFiles.id == file_id)).first_or_404()
        return send_file(file.path, attachment_filename=file.filename)

    @app.route('/support-ticket/delete-file/<int:file_id>')
    def delete_file(file_id):
        file = SupportTicketFiles.query.filter_by(id=file_id)
        ticket_id = file[0].ticket_id
        if os.path.exists(file[0].path):
            os.remove(file[0].path)
        file.delete()
        db.session.commit()
        return redirect(url_for("ticket_management", ticket_id=ticket_id))

    @app.route('/admin/plugins/support-ticket', methods=['GET'])
    @admins_only
    def admin_ticket_management():
        return render_template('support_ticket_admin_view.html',
                               ticket_list=get_ticket_for_admin())

    @app.route('/admin/plugins/support-ticket/view/<int:ticket_id>')
    @admins_only
    def ticket_management(ticket_id):
        ticket = SupportTickets.query.filter_by(id=ticket_id).first_or_404()
        ticket_info = {}
        ticket_info.update({
            "id": ticket_id,
            "creator": ticket.user,
            "category": ticket.challenge_cat,
            "challenge": ticket.challenge_name,
            "description": ticket.description,
            "state": ticket.state
        })
        file_info = SupportTicketFiles.query.filter_by(ticket_id=ticket_id)
        file_list = []
        for file in file_info:
            if int(file.size) >= 1000000:
                size = str(int(file.size) / 1000000) + 'MB'
            elif int(file.size) >= 1000:
                size = str(int(file.size) / 1000) + 'KB'
            else:
                size = str(file.size) + 'B'
            file_list.append({
                "id": file.id,
                "filename": file.filename,
                "size": size
            })
        print(file_list)
        return render_template('support_ticket_admin_edit.html',
                               ticket_info=ticket_info,
                               file_list=file_list)

    @app.route('/admin/plugins/support-ticket/delete/<int:ticket_id>',
               methods=['GET'])
    @admins_only
    def delete_ticket(ticket_id):
        files = SupportTicketFiles.query.filter_by(ticket_id=ticket_id).all()
        for file in files:
            delete_file(file.id)
        SupportTicketConversation.query.filter_by(ticket_id=ticket_id).delete()
        db.session.commit()
        SupportTickets.query.filter_by(id=ticket_id).delete()
        db.session.commit()
        return redirect(url_for("admin_ticket_management"))