Example #1
0
File: views.py Project: ajvpot/CTFd
def tracker():
    if authed():
        if not Tracking.query.filter_by(ip=ip2long(request.remote_addr)).first():
            visit = Tracking(request.remote_addr, session['id'])
            db.session.add(visit)
            db.session.commit()
            db.session.close()
Example #2
0
def topteams(count):
    if get_config('view_scoreboard_if_authed') and not authed():
        return redirect(url_for('auth.login', next=request.path))
    try:
        count = int(count)
    except:
        count = 10
    if count > 20 or count < 0:
        count = 10

    json = {'scores':{}}
    standings = get_standings(count=count)

    for team in standings:
        solves = Solves.query.filter_by(teamid=team.teamid).all()
        awards = Awards.query.filter_by(teamid=team.teamid).all()
        json['scores'][team.name] = []
        scores = []
        for x in solves:
            json['scores'][team.name].append({
                'chal': x.chalid,
                'team': x.teamid,
                'value': x.chal.value,
                'time': unix_time(x.date)
            })
        for award in awards:
            json['scores'][team.name].append({
                'chal': None,
                'team': award.teamid,
                'value': award.value,
                'time': unix_time(award.date)
            })
        json['scores'][team.name] = sorted(json['scores'][team.name], key=lambda k: k['time'])
    return jsonify(json)
Example #3
0
def scores():
    if get_config('view_scoreboard_if_authed') and not authed():
        return redirect(url_for('auth.login', next=request.path))
    score = db.func.sum(Challenges.value).label('score')
    scores = db.session.query(Solves.teamid.label('teamid'), Teams.name.label('name'), score, Solves.date.label('date')) \
        .join(Teams) \
        .join(Challenges) \
        .filter(Teams.banned == None) \
        .group_by(Solves.teamid)

    awards = db.session.query(Teams.id.label('teamid'), Teams.name.label('name'), db.func.sum(Awards.value).label('score'), Awards.date.label('date'))\
        .filter(Teams.id==Awards.teamid)\
        .group_by(Teams.id)

    results = union_all(scores, awards)

    standings = db.session.query(results.columns.teamid, results.columns.name, db.func.sum(results.columns.score).label('score'))\
        .group_by(results.columns.teamid)\
        .order_by(db.func.sum(results.columns.score).desc(), db.func.max(results.columns.date))\
        .all()

    db.session.close()
    json = {'standings':[]}
    for i, x in enumerate(standings):
        json['standings'].append({'pos':i+1, 'id':x.teamid, 'team':x.name,'score':int(x.score)})
    return jsonify(json)
Example #4
0
def solves(teamid=None):
    solves = None
    awards = None
    if teamid is None:
        if is_admin():
            solves = Solves.query.filter_by(teamid=session['id']).all()
        elif authed():
            solves = Solves.query.join(Teams, Solves.teamid == Teams.id).filter(Solves.teamid==session['id'], Teams.banned==None).all()
        else:
            return redirect(url_for('auth.login', next='solves'))
    else:
        solves = Solves.query.filter_by(teamid=teamid).all()
        awards = Awards.query.filter_by(teamid=teamid).all()
    db.session.close()
    json = {'solves':[]}
    for solve in solves:
        json['solves'].append({
            'chal': solve.chal.name,
            'chalid': solve.chalid,
            'team': solve.teamid,
            'value': solve.chal.value,
            'category': solve.chal.category,
            'time': unix_time(solve.date)
        })
    for award in awards:
        json['solves'].append({
            'chal': award.name,
            'chalid': None,
            'team': award.teamid,
            'value': award.value,
            'category': award.category,
            'time': unix_time(award.date)
        })
    json['solves'].sort(key=lambda k: k['time'])
    return jsonify(json)
Example #5
0
def topteams(count):
    if get_config('view_scoreboard_if_authed') and not authed():
        return redirect(url_for('auth.login', next=request.path))
    try:
        count = int(count)
    except:
        count = 10
    if count > 20 or count < 0:
        count = 10

    json = {'scores':{}}

    score = db.func.sum(Challenges.value).label('score')
    quickest = db.func.max(Solves.date).label('quickest')
    teams = db.session.query(Solves.teamid, Teams.name, score)\
        .join(Teams)\
        .join(Challenges)\
        .filter(Teams.banned == None)\
        .group_by(Solves.teamid).order_by(score.desc(), quickest)\
        .limit(count)

    for team in teams:
        solves = Solves.query.filter_by(teamid=team.teamid).all()
        json['scores'][team.name] = []
        for x in solves:
            json['scores'][team.name].append({
                'id': x.teamid,
                'chal': x.chalid,
                'team': x.teamid,
                'value': x.chal.value,
                'time': unix_time(x.date)
            })

    return jsonify(json)
Example #6
0
def scores():
    if get_config('view_scoreboard_if_authed') and not authed():
        return redirect(url_for('auth.login', next=request.path))
    standings = get_standings()
    json = {'standings':[]}
    for i, x in enumerate(standings):
        json['standings'].append({'pos':i+1, 'id':x.teamid, 'team':x.name,'score':int(x.score)})
    return jsonify(json)
Example #7
0
 def logout():
     if authed():
         session.clear()
         try:
             session.regenerate()
         except:
             pass
     return redirect('/')
Example #8
0
def confirm_user(data=None):
    if not utils.get_config('verify_emails'):
        # If the CTF doesn't care about confirming email addresses then redierct to challenges
        return redirect(url_for('challenges.challenges_view'))

    # User is confirming email account
    if data and request.method == "GET":
        try:
            s = Signer(app.config['SECRET_KEY'])
            email = s.unsign(urllib.unquote_plus(data.decode('base64')))
        except BadSignature:
            return render_template('confirm.html', errors=['Your confirmation link seems wrong'])
        except:
            return render_template('confirm.html', errors=['Your link appears broken, please try again.'])
        team = Teams.query.filter_by(email=email).first_or_404()
        team.verified = True
        db.session.commit()
        logger = logging.getLogger('regs')
        logger.warn("[{0}] {1} confirmed {2}".format(time.strftime("%m/%d/%Y %X"), team.name.encode('utf-8'), team.email.encode('utf-8')))
        db.session.close()
        if utils.authed():
            return redirect(url_for('challenges.challenges_view'))
        return redirect(url_for('auth.login'))

    # User is trying to start or restart the confirmation flow
    if not utils.authed():
        return redirect(url_for('auth.login'))

    team = Teams.query.filter_by(id=session['id']).first_or_404()

    if data is None:
        if request.method == "POST":
            # User wants to resend their confirmation email
            if team.verified:
                return redirect(url_for('views.profile'))
            else:
                utils.verify_email(team.email)
            return render_template('confirm.html', team=team, infos=['Your confirmation email has been resent!'])
        elif request.method == "GET":
            # User has been directed to the confirm page
            team = Teams.query.filter_by(id=session['id']).first_or_404()
            if team.verified:
                # If user is already verified, redirect to their profile
                return redirect(url_for('views.profile'))
            return render_template('confirm.html', team=team)
Example #9
0
    def profile():
        if authed():
            if request.method == "POST":
                errors = []

                name = request.form.get('name')
                email = request.form.get('email')
                website = request.form.get('website')
                affiliation = request.form.get('affiliation')
                country = request.form.get('country')

                names = Teams.query.filter_by(name=name).first()
                emails = Teams.query.filter_by(email=email).first()
                valid_email = re.match("[^@]+@[^@]+\.[^@]+", email)
                
                name_len = len(request.form['name']) == 0

                if not bcrypt_sha256.verify(request.form.get('confirm').strip(), names.password):
                    errors.append("Your old password doesn't match what we have.")
                if not valid_email:
                    errors.append("That email doesn't look right")
                if names and name!=session['username']: 
                    errors.append('That team name is already taken')
                if emails and emails.id != session['id']:
                    errors.append('That email has already been used')
                if name_len:
                    errors.append('Pick a longer team name')
                if not validate_url(website):
                    errors.append("That doesn't look like a valid URL")

                if len(errors) > 0:
                    return render_template('profile.html', name=name, email=email, website=website, affiliation=affiliation, country=country, errors=errors)
                else:
                    team = Teams.query.filter_by(id=session['id']).first()
                    team.name = name
                    team.email = email
                    if 'password' in request.form.keys() and not len(request.form['password']) == 0:
                        team.password = bcrypt_sha256.encrypt(request.form.get('password'))
                    team.website = website
                    team.affiliation = affiliation
                    team.country = country
                    db.session.commit()
                    db.session.close()
                    return redirect('/profile')
            else:
                user = Teams.query.filter_by(id=session['id']).first()
                name = user.name
                email = user.email
                website = user.website
                affiliation = user.affiliation
                country = user.country
                return render_template('profile.html', name=name, email=email, website=website, affiliation=affiliation, country=country)
        else:
            return redirect('/login')
Example #10
0
def scoreboard_view():
    if get_config('view_scoreboard_if_authed') and not authed():
        return redirect(url_for('auth.login', next=request.path))
    score = db.func.sum(Challenges.value).label('score')
    quickest = db.func.max(Solves.date).label('quickest')
    teams = db.session.query(Solves.teamid, Teams.name, score)\
        .join(Teams)\
        .join(Challenges)\
        .filter(Teams.banned == None)\
        .group_by(Solves.teamid).order_by(score.desc(), quickest)
    db.session.close()
    return render_template('scoreboard.html', teams=teams)
Example #11
0
def topteams(count):
    if get_config('view_scoreboard_if_authed') and not authed():
        return redirect(url_for('auth.login', next=request.path))
    try:
        count = int(count)
    except:
        count = 10
    if count > 20 or count < 0:
        count = 10

    json = {'scores':{}}

    score = db.func.sum(Challenges.value).label('score')
    scores = db.session.query(Solves.teamid.label('teamid'), Teams.name.label('name'), score, Solves.date.label('date')) \
        .join(Teams) \
        .join(Challenges) \
        .filter(Teams.banned == None) \
        .group_by(Solves.teamid)

    awards = db.session.query(Teams.id.label('teamid'), Teams.name.label('name'),
                              db.func.sum(Awards.value).label('score'), Awards.date.label('date')) \
        .filter(Teams.id == Awards.teamid) \
        .group_by(Teams.id)

    results = union_all(scores, awards)

    standings = db.session.query(results.columns.teamid, results.columns.name,
                                 db.func.sum(results.columns.score).label('score')) \
        .group_by(results.columns.teamid) \
        .order_by(db.func.sum(results.columns.score).desc(), db.func.max(results.columns.date)) \
        .limit(count).all()

    for team in standings:
        solves = Solves.query.filter_by(teamid=team.teamid).all()
        awards = Awards.query.filter_by(teamid=team.teamid).all()
        json['scores'][team.name] = []
        scores = []
        for x in solves:
            json['scores'][team.name].append({
                'chal': x.chalid,
                'team': x.teamid,
                'value': x.chal.value,
                'time': unix_time(x.date)
            })
        for award in awards:
            json['scores'][team.name].append({
                'chal': None,
                'team': award.teamid,
                'value': award.value,
                'time': unix_time(award.date)
            })
        json['scores'][team.name] = sorted(json['scores'][team.name], key=lambda k: k['time'])
    return jsonify(json)
Example #12
0
    def chal(chalid):
        if not ctftime():
            return redirect("/")
        if authed():
            logger = logging.getLogger("keys")
            data = (
                time.strftime("%m/%d/%Y %X"),
                session["username"].encode("utf-8"),
                request.form["key"].encode("utf-8"),
                get_kpm(session["id"]),
            )
            print "[{0}] {1} submitted {2} with kpm {3}".format(*data)
            if get_kpm(session["id"]) > 10:
                wrong = WrongKeys(session["id"], chalid, request.form["key"])
                db.session.add(wrong)
                db.session.commit()
                db.session.close()
                logger.warn("[{0}] {1} submitted {2} with kpm {3} [TOO FAST]".format(*data))
                return "3"  # Submitting too fast
            solves = Solves.query.filter_by(teamid=session["id"], chalid=chalid).first()
            if not solves:
                keys = Keys.query.filter_by(chal=chalid).all()
                key = request.form["key"].strip().lower()
                for x in keys:
                    if x.key_type == 0:  # static key
                        if x.flag.strip().lower() == key:
                            solve = Solves(chalid=chalid, teamid=session["id"], ip=request.remote_addr)
                            db.session.add(solve)
                            db.session.commit()
                            db.session.close()
                            logger.info("[{0}] {1} submitted {2} with kpm {3} [CORRECT]".format(*data))
                            return "1"  # key was correct
                    elif x.key_type == 1:  # regex
                        res = re.match(str(x), key, re.IGNORECASE)
                        if res and res.group() == key:
                            solve = Solves(chalid=chalid, teamid=session["id"], ip=request.remote_addr)
                            db.session.add(solve)
                            db.session.commit()
                            db.session.close()
                            logger.info("[{0}] {1} submitted {2} with kpm {3} [CORRECT]".format(*data))
                            return "1"  # key was correct

                wrong = WrongKeys(session["id"], chalid, request.form["key"])
                db.session.add(wrong)
                db.session.commit()
                db.session.close()
                logger.info("[{0}] {1} submitted {2} with kpm {3} [WRONG]".format(*data))
                return "0"  # key was wrong
            else:
                logger.info("{0} submitted {1} with kpm {2} [ALREADY SOLVED]".format(*data))
                return "2"  # challenge was already solved
        else:
            return "-1"
Example #13
0
def solves(teamid=None):
    if teamid is None:
        if authed():
            solves = Solves.query.filter_by(teamid=session['id']).all()
        else:
            abort(401)
    else:
        solves = Solves.query.filter_by(teamid=teamid).all()
    db.session.close()
    json = {'solves':[]}
    for x in solves:
        json['solves'].append({ 'chal':x.chal.name, 'chalid':x.chalid,'team':x.teamid, 'value': x.chal.value, 'category':x.chal.category, 'time':unix_time(x.date)})
    return jsonify(json)
Example #14
0
def chal(chalid):
    if not ctftime():
        return redirect('/challenges')
    if authed():
        fails = WrongKeys.query.filter_by(team=session['id'],chal=chalid).count()
        logger = logging.getLogger('keys')
        data = (time.strftime("%m/%d/%Y %X"), session['username'].encode('utf-8'), request.form['key'].encode('utf-8'), get_kpm(session['id']))
        print "[{0}] {1} submitted {2} with kpm {3}".format(*data)
        if fails >= int(get_config("max_tries")) and int(get_config("max_tries")) > 0:
            return "4" #too many tries on this challenge
        if get_kpm(session['id']) > 10:
            wrong = WrongKeys(session['id'], chalid, request.form['key'])
            db.session.add(wrong)
            db.session.commit()
            db.session.close()
            logger.warn("[{0}] {1} submitted {2} with kpm {3} [TOO FAST]".format(*data))
            return "3" # Submitting too fast
        solves = Solves.query.filter_by(teamid=session['id'], chalid=chalid).first()
        if not solves:
            keys = Keys.query.filter_by(chal=chalid).all()
            key = request.form['key'].strip().lower()
            for x in keys:
                if x.key_type == 0: #static key
                    if x.flag.strip().lower() == key:
                        solve = Solves(chalid=chalid, teamid=session['id'], ip=request.remote_addr, flag=key)
                        db.session.add(solve)
                        db.session.commit()
                        db.session.close()
                        logger.info("[{0}] {1} submitted {2} with kpm {3} [CORRECT]".format(*data))
                        return "1" # key was correct
                elif x.key_type == 1: #regex
                    res = re.match(str(x), key, re.IGNORECASE)
                    if res and res.group() == key:
                        solve = Solves(chalid=chalid, teamid=session['id'], ip=request.remote_addr, flag=key)
                        db.session.add(solve)
                        db.session.commit()
                        db.session.close()
                        logger.info("[{0}] {1} submitted {2} with kpm {3} [CORRECT]".format(*data))
                        return "1" # key was correct

            wrong = WrongKeys(session['id'], chalid, request.form['key'])
            db.session.add(wrong)
            db.session.commit()
            db.session.close()
            logger.info("[{0}] {1} submitted {2} with kpm {3} [WRONG]".format(*data))
            return '0' # key was wrong
        else:
            logger.info("{0} submitted {1} with kpm {2} [ALREADY SOLVED]".format(*data))
            return "2" # challenge was already solved
    else:
        return "-1"
Example #15
0
def solves(teamid=None):
    solves = None
    awards = None
    if teamid is None:
        if utils.is_admin():
            solves = Solves.query.filter_by(teamid=session['id']).all()
        elif utils.user_can_view_challenges():
            if utils.authed():
                solves = Solves.query.join(Teams, Solves.teamid == Teams.id).filter(Solves.teamid == session['id'], Teams.banned == False).all()
            else:
                return jsonify({'solves': []})
        else:
            return redirect(url_for('auth.login', next='solves'))
    else:
        solves = Solves.query.filter_by(teamid=teamid)
        awards = Awards.query.filter_by(teamid=teamid)

        freeze = utils.get_config('freeze')
        if freeze:
            freeze = utils.unix_time_to_utc(freeze)
            if teamid != session.get('id'):
                solves = solves.filter(Solves.date < freeze)
                awards = awards.filter(Awards.date < freeze)

        solves = solves.all()
        awards = awards.all()
    db.session.close()
    json = {'solves': []}
    for solve in solves:
        json['solves'].append({
            'chal': solve.chal.name,
            'chalid': solve.chalid,
            'team': solve.teamid,
            'value': solve.chal.value,
            'category': solve.chal.category,
            'time': utils.unix_time(solve.date)
        })
    if awards:
        for award in awards:
            json['solves'].append({
                'chal': award.name,
                'chalid': None,
                'team': award.teamid,
                'value': award.value,
                'category': award.category or "Award",
                'time': utils.unix_time(award.date)
            })
    json['solves'].sort(key=lambda k: k['time'])
    return jsonify(json)
Example #16
0
def solves(teamid=None):
    if teamid is None:
        if is_admin():
            solves = Solves.query.filter_by(teamid=session['id']).all()
        elif authed():
            solves = Solves.query.join(Teams, Solves.teamid == Teams.id).filter(Solves.teamid==session['id'], Teams.banned==None).all()
        else:
            return redirect(url_for('auth.login', next='solves'))
    else:
        solves = Solves.query.filter_by(teamid=teamid).all()
    db.session.close()
    json = {'solves':[]}
    for x in solves:
        json['solves'].append({ 'chal':x.chal.name, 'chalid':x.chalid,'team':x.teamid, 'value': x.chal.value, 'category':x.chal.category, 'time':unix_time(x.date)})
    return jsonify(json)
Example #17
0
def scores():
    if get_config('view_scoreboard_if_authed') and not authed():
        return redirect(url_for('auth.login', next=request.path))
    score = db.func.sum(Challenges.value).label('score')
    quickest = db.func.max(Solves.date).label('quickest')
    teams = db.session.query(Solves.teamid, Teams.name, score)\
        .join(Teams)\
        .join(Challenges)\
        .filter(Teams.banned == None)\
        .group_by(Solves.teamid).order_by(score.desc(), quickest)
    db.session.close()
    json = {'standings':[]}
    for i, x in enumerate(teams):
        json['standings'].append({'pos':i+1, 'id':x.teamid, 'team':x.name,'score':int(x.score)})
    return jsonify(json)
Example #18
0
def team(teamid):
    if get_config('view_scoreboard_if_authed') and not authed():
        return redirect(url_for('auth.login', next=request.path))
    user = Teams.query.filter_by(id=teamid).first()
    solves = Solves.query.filter_by(teamid=teamid).all()
    score = user.score()
    place = user.place()
    db.session.close()

    if request.method == 'GET':
        return render_template('team.html', solves=solves, team=user, score=score, place=place)
    elif request.method == 'POST':
        json = {'solves':[]}
        for x in solves:
            json['solves'].append({'id':x.id, 'chal':x.chalid, 'team':x.teamid})
        return jsonify(json)
Example #19
0
def submit_flag():
    result = {}
    cur_round = get_current_round()

    if not ctftime():
        return redirect('/challenges')

    if authed():
        submitkey = str(request.form['flag'].strip().lower())
        teamid = session['id']
        request_ip = request.remote_addr
        querykey = Keys.query.filter_by(flag=submitkey, round=cur_round).first()
        if querykey:
            # Right flag
            if Gameboxs.query.filter_by(id=querykey.gameboxid).first().teamid == teamid:
                # Self flag
                result['status'] = 2
                result['msg'] = 'Self flag'
            else:
                querysolve = Solves.query.filter_by(keyid=querykey.id, teamid=teamid).first()
                if querysolve:
                    # Already submitted
                    result['status'] = 2
                    result['msg'] = 'Already submitted'
                else:
                    # Right flag
                    newsolve = Solves(querykey.id, teamid, querykey.chalid ,querykey.round, request_ip)
                    db.session.add(newsolve)
                    db.session.commit()
                    result['status'] = 1
                    result['msg'] = 'Right Flag'
        else:
            # Wrong flag
            result['status'] = 0
            result['msg'] = 'Wrong Flag'
    else:
        result['status'] = -1
        result['msg'] = 'Login First'

    db.session.close()
    return jsonify(result)
Example #20
0
def confirm_user(data=None):
    if not get_config('verify_emails'):
        return redirect(url_for('challenges.challenges_view'))
    if data and request.method == "GET":  ## User is confirming email account
        try:
            s = Signer(app.config['SECRET_KEY'])
            email = s.unsign(data.decode('base64'))
        except BadSignature:
            return render_template('confirm.html', errors=['Your confirmation link seems wrong'])
        team = Teams.query.filter_by(email=email).first()
        team.verified = True
        db.session.commit()
        db.session.close()
        if authed():
            return redirect(url_for('challenges.challenges_view'))
        return redirect(url_for('auth.login'))
    if not data and request.method == "GET": ## User has been directed to the confirm page because his account is not verified
        team = Teams.query.filter_by(id=session['id']).first()
        if team.verified:
            return redirect(url_for('views.profile'))
        return render_template('confirm.html', team=team)
Example #21
0
 def solves(teamid=None):
     if teamid is None:
         if authed():
             solves = Solves.query.filter_by(teamid=session["id"]).all()
         else:
             abort(401)
     else:
         solves = Solves.query.filter_by(teamid=teamid).all()
     db.session.close()
     json = {"solves": []}
     for x in solves:
         json["solves"].append(
             {
                 "id": x.id,
                 "chal": x.chal.name,
                 "chalid": x.chalid,
                 "team": x.teamid,
                 "value": x.chal.value,
                 "category": x.chal.category,
                 "time": unix_time(x.date),
             }
         )
     return jsonify(json)
Example #22
0
def scoreboard_view():
    if get_config('view_scoreboard_if_authed') and not authed():
        return redirect(url_for('auth.login', next=request.path))
    score = db.func.sum(Challenges.value).label('score')
    scores = db.session.query(Solves.teamid.label('teamid'), Teams.name.label('name'), score, Solves.date.label('date')) \
        .join(Teams) \
        .join(Challenges) \
        .filter(Teams.banned == None) \
        .group_by(Solves.teamid)

    awards = db.session.query(Teams.id.label('teamid'), Teams.name.label('name'),
                              db.func.sum(Awards.value).label('score'), Awards.date.label('date')) \
        .filter(Teams.id == Awards.teamid) \
        .group_by(Teams.id)

    results = union_all(scores, awards)

    standings = db.session.query(results.columns.teamid, results.columns.name,
                                 db.func.sum(results.columns.score).label('score')) \
        .group_by(results.columns.teamid) \
        .order_by(db.func.sum(results.columns.score).desc(), db.func.max(results.columns.date)) \
        .all()
    db.session.close()
    return render_template('scoreboard.html', teams=standings)
Example #23
0
def team(teamid):
    if utils.get_config('view_scoreboard_if_utils.authed') and not utils.authed():
        return redirect(url_for('auth.login', next=request.path))
    errors = []
    freeze = utils.get_config('freeze')
    user = Teams.query.filter_by(id=teamid).first_or_404()
    solves = Solves.query.filter_by(teamid=teamid)
    awards = Awards.query.filter_by(teamid=teamid)

    place = user.place()
    score = user.score()

    if freeze:
        freeze = utils.unix_time_to_utc(freeze)
        if teamid != session.get('id'):
            solves = solves.filter(Solves.date < freeze)
            awards = awards.filter(Awards.date < freeze)

    solves = solves.all()
    awards = awards.all()

    db.session.close()

    if utils.hide_scores() and teamid != session.get('id'):
        errors.append('Scores are currently hidden')

    if errors:
        return render_template('team.html', team=user, errors=errors)

    if request.method == 'GET':
        return render_template('team.html', solves=solves, awards=awards, team=user, score=score, place=place, score_frozen=utils.is_scoreboard_frozen())
    elif request.method == 'POST':
        json = {'solves': []}
        for x in solves:
            json['solves'].append({'id': x.id, 'chal': x.chalid, 'team': x.teamid})
        return jsonify(json)
Example #24
0
def profile():
    if authed():
        if request.method == "POST":
            errors = []

            name = request.form.get("name")
            email = request.form.get("email")
            website = request.form.get("website")
            affiliation = request.form.get("affiliation")
            country = request.form.get("country")

            user = Teams.query.filter_by(id=session["id"]).first()

            if not get_config("prevent_name_change"):
                names = Teams.query.filter_by(name=name).first()
                name_len = len(request.form["name"]) == 0

            emails = Teams.query.filter_by(email=email).first()
            valid_email = re.match("[^@]+@[^@]+\.[^@]+", email)

            if ("password" in request.form.keys() and not len(request.form["password"]) == 0) and (
                not bcrypt_sha256.verify(request.form.get("confirm").strip(), user.password)
            ):
                errors.append("Your old password doesn't match what we have.")
            if not valid_email:
                errors.append("That email doesn't look right")
            if not get_config("prevent_name_change") and names and name != session["username"]:
                errors.append("That team name is already taken")
            if emails and emails.id != session["id"]:
                errors.append("That email has already been used")
            if not get_config("prevent_name_change") and name_len:
                errors.append("Pick a longer team name")
            if website.strip() and not validate_url(website):
                errors.append("That doesn't look like a valid URL")

            if len(errors) > 0:
                return render_template(
                    "profile.html",
                    name=name,
                    email=email,
                    website=website,
                    affiliation=affiliation,
                    country=country,
                    errors=errors,
                )
            else:
                team = Teams.query.filter_by(id=session["id"]).first()
                if not get_config("prevent_name_change"):
                    team.name = name
                team.email = email
                session["username"] = team.name

                if "password" in request.form.keys() and not len(request.form["password"]) == 0:
                    team.password = bcrypt_sha256.encrypt(request.form.get("password"))
                team.website = website
                team.affiliation = affiliation
                team.country = country
                db.session.commit()
                db.session.close()
                return redirect("/profile")
        else:
            user = Teams.query.filter_by(id=session["id"]).first()
            name = user.name
            email = user.email
            website = user.website
            affiliation = user.affiliation
            country = user.country
            prevent_name_change = get_config("prevent_name_change")
            return render_template(
                "profile.html",
                name=name,
                email=email,
                website=website,
                affiliation=affiliation,
                country=country,
                prevent_name_change=prevent_name_change,
            )
    else:
        return redirect("/login")
Example #25
0
def chal(chalid):
    if not ctftime():
        return redirect(url_for('challenges.challenges_view'))
    if authed():
        fails = WrongKeys.query.filter_by(teamid=session['id'], chalid=chalid).count()
        logger = logging.getLogger('keys')
        data = (time.strftime("%m/%d/%Y %X"), session['username'].encode('utf-8'), request.form['key'].encode('utf-8'), get_kpm(session['id']))
        print("[{0}] {1} submitted {2} with kpm {3}".format(*data))

        # Hit max attempts
        if fails >= int(get_config("max_tries")) and int(get_config("max_tries")) > 0:
            return "4" #too many tries on this challenge

        # Anti-bruteforce / submitting keys too quickly
        if get_kpm(session['id']) > 10:
            wrong = WrongKeys(session['id'], chalid, request.form['key'])
            db.session.add(wrong)
            db.session.commit()
            db.session.close()
            logger.warn("[{0}] {1} submitted {2} with kpm {3} [TOO FAST]".format(*data))
            return "3" # Submitting too fast

        solves = Solves.query.filter_by(teamid=session['id'], chalid=chalid).first()

        # Challange not solved yet
        if not solves:
            chal = Challenges.query.filter_by(id=chalid).first()
            key = str(request.form['key'].strip().lower())
            keys = json.loads(chal.flags)
            for x in keys:
                if x['type'] == 0: #static key
                    print(x['flag'], key.strip().lower())
                    if x['flag'] and x['flag'].strip().lower() == key.strip().lower():
                        solve = Solves(chalid=chalid, teamid=session['id'], ip=get_ip(), flag=key)
                        db.session.add(solve)
                        db.session.commit()
                        db.session.close()
                        logger.info("[{0}] {1} submitted {2} with kpm {3} [CORRECT]".format(*data))
                        return "1" # key was correct
                elif x['type'] == 1: #regex
                    res = re.match(str(x['flag']), key, re.IGNORECASE)
                    if res and res.group() == key:
                        solve = Solves(chalid=chalid, teamid=session['id'], ip=get_ip(), flag=key)
                        db.session.add(solve)
                        db.session.commit()
                        db.session.close()
                        logger.info("[{0}] {1} submitted {2} with kpm {3} [CORRECT]".format(*data))
                        return "1" # key was correct

            wrong = WrongKeys(session['id'], chalid, request.form['key'])
            db.session.add(wrong)
            db.session.commit()
            db.session.close()
            logger.info("[{0}] {1} submitted {2} with kpm {3} [WRONG]".format(*data))
            return '0' # key was wrong

        # Challenge already solved
        else:
            logger.info("{0} submitted {1} with kpm {2} [ALREADY SOLVED]".format(*data))
            return "2" # challenge was already solved
    else:
        return "-1"
Example #26
0
def profile():
    if authed():
        if request.method == "POST":
            errors = []

            name = request.form.get('name')
            email = request.form.get('email')
            schoolCode = request.form.get('schoolCode')
            website = request.form.get('website')
            affiliation = request.form.get('affiliation')
            country = request.form.get('country')

            user = Teams.query.filter_by(id=session['id']).first()

            if not get_config('prevent_name_change'):
                names = Teams.query.filter_by(name=name).first()
                name_len = len(request.form['name']) == 0

            emails = Teams.query.filter_by(email=email).first()
            valid_email = re.match("[^@]+@[^@]+\.[^@]+", email)

            if ('password' in request.form.keys() and not len(request.form['password']) == 0) and \
                    (not bcrypt_sha256.verify(request.form.get('confirm').strip(), user.password)):
                errors.append("Your old password doesn't match what we have.")
            if not valid_email:
                errors.append("That email doesn't look right")
            if not get_config('prevent_name_change') and names and name!=session['username']:
                errors.append('That team name is already taken')
            if emails and emails.id != session['id']:
                errors.append('That email has already been used')
            if not get_config('prevent_name_change') and name_len:
                errors.append('Pick a longer team name')
            if website.strip() and not validate_url(website):
                errors.append("That doesn't look like a valid URL")

            if len(errors) > 0:
                return render_template('profile.html', name=name, email=email, schoolCode=schoolCode, website=website,
                                       affiliation=affiliation, country=country, errors=errors)
            else:
                team = Teams.query.filter_by(id=session['id']).first()
                if not get_config('prevent_name_change'):
                    team.name = name
                if team.email != email.lower():
                    team.email = email.lower()
                    if get_config('verify_emails'):
                        team.verified = False
                session['username'] = team.name

                if 'password' in request.form.keys() and not len(request.form['password']) == 0:
                    team.password = bcrypt_sha256.encrypt(request.form.get('password'))
                team.schoolCode = schoolCode
                team.website = website
                team.affiliation = affiliation
                team.country = country
                db.session.commit()
                db.session.close()
                return redirect(url_for('views.profile'))
        else:
            user = Teams.query.filter_by(id=session['id']).first()
            name = user.name
            email = user.email
            schoolCode = user.schoolCode
            website = user.website
            affiliation = user.affiliation
            country = user.country
            prevent_name_change = get_config('prevent_name_change')
            confirm_email = get_config('verify_emails') and not user.verified
            return render_template('profile.html', name=name, email=email, schoolCode=schoolCode, website=website, affiliation=affiliation,
                                   country=country, prevent_name_change=prevent_name_change, confirm_email=confirm_email)
    else:
        return redirect(url_for('auth.login'))
Example #27
0
def profile():
    if utils.authed():
        if request.method == "POST":
            errors = []

            name = request.form.get('name').strip()
            country = request.form.get('country').strip()

            user = Teams.query.filter_by(id=session['id']).first()

            if not utils.get_config('prevent_name_change'):
                names = Teams.query.filter_by(name=name).first()
                name_len = len(request.form['name']) == 0


            if ('password' in request.form.keys() and not len(request.form['password']) == 0) and \
                    (not bcrypt_sha256.verify(request.form.get('confirm').strip(), user.password)):
                errors.append("当前密码不正确")
            if not utils.get_config(
                    'prevent_name_change'
            ) and names and name != session['username']:
                errors.append('That team name is already taken')
            if not utils.get_config('prevent_name_change') and name_len:
                errors.append('Pick a longer team name')

            if len(errors) > 0:
                return render_template('profile.html',
                                       name=name,
                                       country=country,
                                       errors=errors)
            else:
                team = Teams.query.filter_by(id=session['id']).first()
                if team.name != name:
                    if not utils.get_config('prevent_name_change'):
                        team.name = name
                        session['username'] = team.name

                if 'password' in request.form.keys() and not len(
                        request.form['password']) == 0:
                    team.password = bcrypt_sha256.encrypt(
                        request.form.get('password'))

                team.country = country
                db.session.commit()
                db.session.close()
                return redirect(url_for('views.profile'))
        else:
            user = Teams.query.filter_by(id=session['id']).first()
            name = user.name
            website = user.website
            affiliation = user.affiliation
            country = user.country
            prevent_name_change = utils.get_config('prevent_name_change')
            return render_template('profile.html',
                                   name=name,
                                   website=website,
                                   affiliation=affiliation,
                                   country=country,
                                   prevent_name_change=prevent_name_change)
    else:
        return redirect(url_for('auth.login'))
Example #28
0
def profile():
    if utils.authed():
        if request.method == "POST":
            errors = []

            name = request.form.get('name')
            email = request.form.get('email')
            website = request.form.get('website')
            affiliation = request.form.get('affiliation')
            country = request.form.get('country')

            user = Teams.query.filter_by(id=session['id']).first()

            if not utils.get_config('prevent_name_change'):
                names = Teams.query.filter_by(name=name).first()
                name_len = len(request.form['name']) == 0

            emails = Teams.query.filter_by(email=email).first()
            valid_email = re.match(
                r"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)", email)

            if ('password' in request.form.keys() and not len(request.form['password']) == 0) and \
                    (not bcrypt_sha256.verify(request.form.get('confirm').strip(), user.password)):
                errors.append("Your old password doesn't match what we have.")
            if not valid_email:
                errors.append("That email doesn't look right")
            if not utils.get_config(
                    'prevent_name_change'
            ) and names and name != session['username']:
                errors.append('That team name is already taken')
            if emails and emails.id != session['id']:
                errors.append('That email has already been used')
            if not utils.get_config('prevent_name_change') and name_len:
                errors.append('Pick a longer team name')
            if website.strip() and not utils.validate_url(website):
                errors.append("That doesn't look like a valid URL")

            if len(errors) > 0:
                return render_template('profile.html',
                                       name=name,
                                       email=email,
                                       website=website,
                                       affiliation=affiliation,
                                       country=country,
                                       errors=errors)
            else:
                team = Teams.query.filter_by(id=session['id']).first()
                if not utils.get_config('prevent_name_change'):
                    team.name = name
                if team.email != email.lower():
                    team.email = email.lower()
                    if utils.get_config('verify_emails'):
                        team.verified = False
                session['username'] = team.name

                if 'password' in request.form.keys() and not len(
                        request.form['password']) == 0:
                    team.password = bcrypt_sha256.encrypt(
                        request.form.get('password'))
                team.website = website
                team.affiliation = affiliation
                team.country = country
                db.session.commit()
                db.session.close()
                return redirect(url_for('views.profile'))
        else:
            user = Teams.query.filter_by(id=session['id']).first()
            name = user.name
            email = user.email
            website = user.website
            affiliation = user.affiliation
            country = user.country
            prevent_name_change = utils.get_config('prevent_name_change')
            confirm_email = utils.get_config(
                'verify_emails') and not user.verified
            return render_template('profile.html',
                                   name=name,
                                   email=email,
                                   website=website,
                                   affiliation=affiliation,
                                   country=country,
                                   prevent_name_change=prevent_name_change,
                                   confirm_email=confirm_email)
    else:
        return redirect(url_for('auth.login'))
Example #29
0
    def new_reset_pass():
        if utils.authed():
            if request.method == "POST":
                errors = []

                name = request.form.get('name').strip()
                email = request.form.get('email').strip()
                website = request.form.get('website').strip()
                affiliation = request.form.get('affiliation').strip()
                country = request.form.get('country').strip()

                user = Teams.query.filter_by(id=session['id']).first()

                if not utils.get_config('prevent_name_change'):
                    names = Teams.query.filter_by(name=name).first()
                    name_len = len(request.form['name']) == 0

                emails = Teams.query.filter_by(email=email).first()
                valid_email = utils.check_email_format(email)

                if utils.check_email_format(name) is True:
                    errors.append('Team name cannot be an email address')

                if ('password' in request.form.keys() and not len(request.form['password']) == 0) and \
                        (not bcrypt_sha256.verify(request.form.get('confirm').strip(), user.password)):
                    errors.append(
                        "Your old password doesn't match what we have.")
                if not valid_email:
                    errors.append("That email doesn't look right")
                if not utils.get_config(
                        'prevent_name_change'
                ) and names and name != session['username']:
                    errors.append('That team name is already taken')
                if emails and emails.id != session['id']:
                    errors.append('That email has already been used')
                if not utils.get_config('prevent_name_change') and name_len:
                    errors.append('Pick a longer team name')
                if website.strip() and not utils.validate_url(website):
                    errors.append("That doesn't look like a valid URL")

                if len(errors) > 0:
                    return render_template('profile.html',
                                           name=name,
                                           email=email,
                                           website=website,
                                           affiliation=affiliation,
                                           country=country,
                                           errors=errors)

                else:
                    team = Teams.query.filter_by(id=session['id']).first()
                    if team.name != name:
                        if not utils.get_config('prevent_name_change'):
                            team.name = name
                            session['username'] = team.name
                    if team.email != email.lower():
                        team.email = email.lower()
                        if utils.get_config('verify_emails'):
                            team.verified = False

                    if 'password' in request.form.keys() and not len(
                            request.form['password']) == 0:
                        team.password = bcrypt_sha256.encrypt(
                            request.form.get('password'))
                        message = json.dumps(["change", name, password])

                        channel.basic_publish(
                            exchange='',
                            routing_key='shell_queue',
                            body=message,
                            properties=pika.BasicProperties(
                                delivery_mode=2,  # make message persistent
                            ))

                    team.website = website
                    team.affiliation = affiliation
                    team.country = country
                    db.session.commit()
                    db.session.close()

                    return redirect(url_for('views.profile'))
            else:
                user = Teams.query.filter_by(id=session['id']).first()
                name = user.name
                email = user.email
                website = user.website
                affiliation = user.affiliation
                country = user.country
                prevent_name_change = utils.get_config('prevent_name_change')
                confirm_email = utils.get_config(
                    'verify_emails') and not user.verified
                return render_template('profile.html',
                                       name=name,
                                       email=email,
                                       website=website,
                                       affiliation=affiliation,
                                       country=country,
                                       prevent_name_change=prevent_name_change,
                                       confirm_email=confirm_email)
        else:
            return redirect(url_for('auth.login'))
Example #30
0
    def anonchal():
        if utils.ctf_paused():
            return jsonify({
                'status': 3,
                'message': '{} is paused'.format(utils.ctf_name())
            })

        if utils.is_admin() or (utils.authed() and utils.is_verified() and
                                (utils.ctf_started()
                                 or utils.view_after_ctf())):

            team = Teams.query.filter_by(id=session['id']).first()
            provided_key = request.form['key'].strip()
            logger = logging.getLogger('keys')
            data = (time.strftime("%m/%d/%Y %X"),
                    session['username'].encode('utf-8'),
                    provided_key.encode('utf-8'), utils.get_kpm(session['id']))

            # Anti-bruteforce / KPM is based on last failed key (not logged), so sleep instead.
            time.sleep(2)

            # Find challenge by looking up the provided flag
            key = db.session.query(Keys).\
                join(AnonymousChallenge).\
                filter(Keys.flag == provided_key).first()

            if not key:
                logger.info(
                    "[{0}] {1} submitted {2} with kpm {3} [WRONG]".format(
                        *data))
                return jsonify({'status': 0, 'message': 'Invalid Flag'})

            chal = AnonymousChallenge.query.filter_by(id=key.chal).first()

            chal_class = get_chal_class(chal.type)
            solves = Solves.query.filter_by(teamid=session['id'],
                                            chalid=chal.id).first()

            # If team hasn't solved challenge yet, save the solve
            if not solves:
                # We already know the flag is correct because we checked it already
                chal_class.solve(team=team, chal=chal, request=request)
                logger.info(
                    "[{0}] {1} submitted {2} with kpm {3} [CORRECT]".format(
                        *data))
                return jsonify({'status': 1, 'message': "Correct"})

            # Otherwise, raise an error
            else:
                logger.info(
                    "{0} submitted {1} with kpm {2} [ALREADY SOLVED]".format(
                        *data))
                return jsonify({
                    'status': 2,
                    'message': 'You already solved this'
                })
        else:
            return jsonify({
                'status':
                -1,
                'message':
                "You must be logged in to solve a challenge"
            })
Example #31
0
 def csrf():
     if authed() and request.method == "POST":
         if session['nonce'] != request.form.get('nonce'):
             abort(403)
Example #32
0
    def shell_view():
        if not authed():
            return redirect(url_for('auth.login', next=request.path))

        return render_template('shell.html', root=request.script_root)
Example #33
0
def chal(chalid):
    if utils.ctf_paused():
        return jsonify({
            'status': 3,
            'message': '{} is paused'.format(utils.ctf_name())
        })
    if (utils.authed() and utils.is_verified() and (utils.ctf_started() or utils.view_after_ctf())) or utils.is_admin():
        team = Teams.query.filter_by(id=session['id']).first()
        fails = WrongKeys.query.filter_by(teamid=session['id'], chalid=chalid).count()
        logger = logging.getLogger('keys')
        data = (time.strftime("%m/%d/%Y %X"), session['username'].encode('utf-8'), request.form['key'].encode('utf-8'), utils.get_kpm(session['id']))
        print("[{0}] {1} submitted {2} with kpm {3}".format(*data))

        chal = Challenges.query.filter_by(id=chalid).first_or_404()
        if chal.hidden:
            abort(404)
        chal_class = get_chal_class(chal.type)

        # Anti-bruteforce / submitting keys too quickly
        if utils.get_kpm(session['id']) > 10:
            if utils.ctftime():
                chal_class.fail(team=team, chal=chal, request=request)
            logger.warn("[{0}] {1} submitted {2} with kpm {3} [TOO FAST]".format(*data))
            # return '3' # Submitting too fast
            return jsonify({'status': 3, 'message': "You're submitting keys too fast. Slow down."})

        solves = Solves.query.filter_by(teamid=session['id'], chalid=chalid).first()

        # Challange not solved yet
        if not solves:
            provided_key = request.form['key'].strip()
            saved_keys = Keys.query.filter_by(chal=chal.id).all()

            # Hit max attempts
            max_tries = chal.max_attempts
            if max_tries and fails >= max_tries > 0:
                return jsonify({
                    'status': 0,
                    'message': "You have 0 tries remaining"
                })

            status, message = chal_class.attempt(chal, request)
            if status:  # The challenge plugin says the input is right
                if utils.ctftime() or utils.is_admin():
                    chal_class.solve(team=team, chal=chal, request=request)
                logger.info("[{0}] {1} submitted {2} with kpm {3} [CORRECT]".format(*data))
		filter = Challenges.query.filter_by(id = chalid).all()
        	chalname = filter[0].name
		teams = Teams.query.filter_by(id=session['id'])
        	chal_category = filter[0].category
        	chal_value = filter[0].value
		t = datetime.datetime.fromtimestamp(time.time()).strftime('%c').split(' ')[3]
        	broadcast(t + ": Đội " + teams[0].name + " đã giải được "+ chal_category + str(chal_value) + ": " + chalname)
                return jsonify({'status': 1, 'message': message})
            else:  # The challenge plugin says the input is wrong
                if utils.ctftime() or utils.is_admin():
                    chal_class.fail(team=team, chal=chal, request=request)
                logger.info("[{0}] {1} submitted {2} with kpm {3} [WRONG]".format(*data))
                # return '0' # key was wrong
                if max_tries:
                    attempts_left = max_tries - fails - 1  # Off by one since fails has changed since it was gotten
                    tries_str = 'tries'
                    if attempts_left == 1:
                        tries_str = 'try'
                    if message[-1] not in '!().;?[]\{\}':  # Add a punctuation mark if there isn't one
                        message = message + '.'
                    return jsonify({'status': 0, 'message': '{} You have {} {} remaining.'.format(message, attempts_left, tries_str)})
                else:
                    return jsonify({'status': 0, 'message': message})

        # Challenge already solved
        else:
            logger.info("{0} submitted {1} with kpm {2} [ALREADY SOLVED]".format(*data))
            # return '2' # challenge was already solved
            return jsonify({'status': 2, 'message': 'You already solved this'})
    else:
        return jsonify({
            'status': -1,
            'message': "You must be logged in to solve a challenge"
        })
Example #34
0
    def chals_linearunlocked():
        # Get solved challenge ids
        solves = []
        if utils.is_admin():
            solves = Solves.query.filter_by(teamid=session['id']).all()
        elif utils.user_can_view_challenges():
            if utils.authed():
                solves = Solves.query\
                    .join(Teams, Solves.teamid == Teams.id)\
                    .filter(Solves.teamid == session['id'])\
                    .all()
        solve_ids = []
        for solve in solves:
            solve_ids.append(solve.chalid)

        db_chals = Challenges.query.filter(
            or_(Challenges.hidden != True,
                Challenges.hidden == None)).order_by(Challenges.value).all()
        response = {'game': []}
        linearunlock_games = {}
        other_games = []

        for chal in db_chals:
            # Skip if is linear locked and should be hidden
            lu_id = -1
            lu_name = "__NOT_IN_ANY_CHAIN__"
            lu_position = -1
            is_hidden = False
            lu_entries = LinearUnlockingEntry.query.filter_by(
                chalid=chal.id).all()
            for lu_entry in lu_entries:
                # Initialize lu_id if possible, used for sorting the challenges later
                if lu_id == -1:
                    lu_model = LinearUnlockingModel.query.filter_by(
                        id=lu_entry.linearunlockid).first()
                    lu_id = lu_model.id
                    lu_name = lu_model.name
                    lu_position = lu_entry.position

                if lu_entry.requires_chalid > -1 and lu_entry.requires_chalid not in solve_ids:
                    lu_model = LinearUnlockingModel.query.filter_by(
                        id=lu_entry.linearunlockid).first()
                    if lu_model.is_hidden:
                        is_hidden = True
                        break
            if is_hidden:
                continue

            tags = [
                tag.tag for tag in Tags.query.add_columns('tag').filter_by(
                    chal=chal.id).all()
            ]
            chal_type = get_chal_class(chal.type)

            game = {
                'id': chal.id,
                'type': chal_type.name,
                'name': chal.name,
                'value': chal.value,
                'category': chal.category,
                'tags': tags,
                'template': chal_type.templates['modal'],
                'script': chal_type.scripts['modal'],
                # Add more info for chain presentation
                'chainid': lu_id,
                'chainname': lu_name,
                'chainposition': lu_position,
            }
            if lu_id > -1:
                if lu_id not in linearunlock_games:
                    linearunlock_games[lu_id] = []
                linearunlock_games[lu_id].append(game)
            else:
                other_games.append(game)

        # Add all linear unlock chain challenges in sorted order first
        for lu_id, lu_chain_games in linearunlock_games.iteritems():
            lu_chain_games.sort(key=lambda x: x['chainposition'])
            response['game'].extend(lu_chain_games)
        # Then add all other games that are not in any chain
        response['game'].extend(other_games)

        db.session.close()
        return jsonify(response)
Example #35
0
def chal(chalid):
    if utils.ctf_paused():
        return jsonify({
            'status': 3,
            'message': '{} is paused'.format(utils.ctf_name())
        })
    if utils.ctf_ended() and not utils.view_after_ctf():
        abort(403)
    if not utils.user_can_view_challenges():
        return redirect(url_for('auth.login', next=request.path))
    if (utils.authed() and utils.is_verified() and
        (utils.ctf_started() or utils.view_after_ctf())) or utils.is_admin():
        team = Teams.query.filter_by(id=session['id']).first()
        fails = WrongKeys.query.filter_by(teamid=session['id'],
                                          chalid=chalid).count()
        logger = logging.getLogger('keys')
        data = (time.strftime("%m/%d/%Y %X"),
                session['username'].encode('utf-8'),
                request.form['key'].encode('utf-8'),
                utils.get_kpm(session['id']))
        print("[{0}] {1} submitted {2} with kpm {3}".format(*data))

        chal = Challenges.query.filter_by(id=chalid).first_or_404()
        if chal.hidden:
            abort(404)
        chal_class = get_chal_class(chal.type)

        # Anti-bruteforce / submitting keys too quickly
        if utils.get_kpm(session['id']) > 10:
            if utils.ctftime():
                chal_class.fail(team=team, chal=chal, request=request)
            logger.warn(
                "[{0}] {1} submitted {2} with kpm {3} [TOO FAST]".format(
                    *data))
            # return '3' # Submitting too fast
            return jsonify({
                'status':
                3,
                'message':
                "You're submitting keys too fast. Slow down."
            })

        solves = Solves.query.filter_by(teamid=session['id'],
                                        chalid=chalid).first()

        # Challange not solved yet
        if not solves:
            provided_key = request.form['key'].strip()
            saved_keys = Keys.query.filter_by(chal=chal.id).all()

            # Hit max attempts
            max_tries = chal.max_attempts
            if max_tries and fails >= max_tries > 0:
                return jsonify({
                    'status': 0,
                    'message': "You have 0 tries remaining"
                })

            status, message = chal_class.attempt(chal, request)
            if status:  # The challenge plugin says the input is right
                if utils.ctftime() or utils.is_admin():
                    chal_class.solve(team=team, chal=chal, request=request)
                logger.info(
                    "[{0}] {1} submitted {2} with kpm {3} [CORRECT]".format(
                        *data))
                return jsonify({'status': 1, 'message': message})
            else:  # The challenge plugin says the input is wrong
                if isinstance(
                        message,
                        int):  # This means someone submitted others' flag
                    if utils.ctftime() or utils.is_admin():
                        chal_class.penalty(
                            team1=team,
                            team2=Teams.query.filter_by(id=message).first(),
                            chal=chal,
                            request=request)
                    logger.info(
                        "[{0}] {1} submitted {2} with kpm {3} [CHEAT]".format(
                            *data))
                    message = "Incorrect(Warning!You are trying to submit other team's flag)"
                else:
                    if utils.ctftime() or utils.is_admin():
                        chal_class.fail(team=team, chal=chal, request=request)
                    logger.info(
                        "[{0}] {1} submitted {2} with kpm {3} [WRONG]".format(
                            *data))
                # return '0' # key was wrong
                if max_tries:
                    attempts_left = max_tries - fails - 1  # Off by one since fails has changed since it was gotten
                    tries_str = 'tries'
                    if attempts_left == 1:
                        tries_str = 'try'
                    if message[
                            -1] not in '!().;?[]\{\}':  # Add a punctuation mark if there isn't one
                        message = message + '.'
                    return jsonify({
                        'status':
                        0,
                        'message':
                        '{} You have {} {} remaining.'.format(
                            message, attempts_left, tries_str)
                    })
                else:
                    return jsonify({'status': 0, 'message': message})

        # Challenge already solved
        else:
            logger.info(
                "{0} submitted {1} with kpm {2} [ALREADY SOLVED]".format(
                    *data))
            # return '2' # challenge was already solved
            return jsonify({'status': 2, 'message': 'You already solved this'})
    else:
        return jsonify({
            'status': -1,
            'message': "You must be logged in to solve a challenge"
        })
Example #36
0
def scoreboard_view():
    if get_config('view_scoreboard_if_authed') and not authed():
        return redirect(url_for('auth.login', next=request.path))
    standings = get_standings()
    return render_template('scoreboard.html', teams=standings)
Example #37
0
 def restart():
     if authed():
         session.clear()
     return redirect('/home')
Example #38
0
 def inject_user():
     if authed():
         return dict(session)
     return dict()
Example #39
0
def chal(chalid):
    if utils.ctf_ended() and not utils.view_after_ctf():
        return redirect(url_for('challenges.challenges_view'))
    if not utils.user_can_view_challenges():
        return redirect(url_for('auth.login', next=request.path))
    if utils.authed() and utils.is_verified() and (utils.ctf_started()
                                                   or utils.view_after_ctf()):
        fails = WrongKeys.query.filter_by(teamid=session['id'],
                                          chalid=chalid).count()
        logger = logging.getLogger('keys')
        data = (time.strftime("%m/%d/%Y %X"),
                session['username'].encode('utf-8'),
                request.form['key'].encode('utf-8'),
                utils.get_kpm(session['id']))
        print("[{0}] {1} submitted {2} with kpm {3}".format(*data))

        # Anti-bruteforce / submitting keys too quickly
        if utils.get_kpm(session['id']) > 10:
            if utils.ctftime():
                wrong = WrongKeys(session['id'], chalid, request.form['key'])
                db.session.add(wrong)
                db.session.commit()
                db.session.close()
            logger.warn(
                "[{0}] {1} submitted {2} with kpm {3} [TOO FAST]".format(
                    *data))
            # return '3' # Submitting too fast
            return jsonify({
                'status':
                '3',
                'message':
                "You're submitting keys too fast. Slow down."
            })

        solves = Solves.query.filter_by(teamid=session['id'],
                                        chalid=chalid).first()

        # Challange not solved yet
        if not solves:
            chal = Challenges.query.filter_by(id=chalid).first_or_404()
            provided_key = unicode(request.form['key'].strip())
            saved_keys = Keys.query.filter_by(chal=chal.id).all()

            # Hit max attempts
            max_tries = chal.max_attempts
            if max_tries and fails >= max_tries > 0:
                return jsonify({
                    'status': '0',
                    'message': "You have 0 tries remaining"
                })

            chal_class = get_chal_class(chal.type)
            if chal_class.solve(chal, provided_key):
                if utils.ctftime():
                    solve = Solves(chalid=chalid,
                                   teamid=session['id'],
                                   ip=utils.get_ip(),
                                   flag=provided_key)
                    db.session.add(solve)
                    db.session.commit()
                    db.session.close()
                logger.info(
                    "[{0}] {1} submitted {2} with kpm {3} [CORRECT]".format(
                        *data))
                return jsonify({'status': '1', 'message': 'Correct'})

            if utils.ctftime():
                wrong = WrongKeys(teamid=session['id'],
                                  chalid=chalid,
                                  flag=provided_key)
                db.session.add(wrong)
                db.session.commit()
                db.session.close()
            logger.info(
                "[{0}] {1} submitted {2} with kpm {3} [WRONG]".format(*data))
            # return '0' # key was wrong
            if max_tries:
                attempts_left = max_tries - fails - 1  # Off by one since fails has changed since it was gotten
                tries_str = 'tries'
                if attempts_left == 1:
                    tries_str = 'try'
                return jsonify({
                    'status':
                    '0',
                    'message':
                    'Incorrect. You have {} {} remaining.'.format(
                        attempts_left, tries_str)
                })
            else:
                return jsonify({'status': '0', 'message': 'Incorrect'})

        # Challenge already solved
        else:
            logger.info(
                "{0} submitted {1} with kpm {2} [ALREADY SOLVED]".format(
                    *data))
            # return '2' # challenge was already solved
            return jsonify({
                'status': '2',
                'message': 'You already solved this'
            })
    else:
        return jsonify({
            'status': '-1',
            'message': "You must be logged in to solve a challenge"
        })
Example #40
0
def team_management():
    if authed():
        user = Users.query.filter_by(id=session.get('id')).first_or_404()
        if user.teamid:  ## Already has team
            s = Signer(app.config['SECRET_KEY'])
            team = Teams.query.filter_by(id=user.teamid).first_or_404()
            users = Users.query.filter_by(teamid=user.teamid)
            secret = urllib.quote_plus(s.sign(str(team.id)).encode('base64'))
            if request.method == "POST":
                errors = []
                if team.captain == user.id:
                    website = request.form.get('website')
                    affiliation = request.form.get('affiliation')
                    country = request.form.get('country')

                    if website.strip() and not validate_url(website):
                        errors.append("That doesn't look like a valid URL")

                    team.website = website
                    team.affiliation = affiliation
                    team.country = country
                else:
                    errors.append(
                        'Only team captains can change this information.')
                if errors:
                    return render_template('view_team.html',
                                           team=team,
                                           users=users,
                                           secret=secret,
                                           errors=errors)
                db.session.commit()
                db.session.close()
                return redirect(url_for('views.team_management'))
            else:
                captain = False
                if team.captain == user.id:
                    captain = True
                return render_template('view_team.html',
                                       team=team,
                                       users=users,
                                       secret=secret,
                                       captain=captain)
        else:  ## Needs a team
            if request.method == "POST":
                name = request.form.get('name')
                captain = session.get('id')
                team = Teams.query.filter_by(name=name).first()
                errors = []
                if team:
                    errors.append('That team name is already taken')

                t = Teams(name, captain)

                if errors:
                    return render_template('create_team.html',
                                           errors=errors,
                                           team=t)

                db.session.add(t)
                db.session.flush()

                user.teamid = t.id
                db.session.commit()
                db.session.close()
                return redirect(url_for('views.team_management'))
            else:
                return render_template('create_team.html')
    else:
        return redirect(url_for('auth.login'))
Example #41
0
 def logout():
     if authed():
         session.clear()
     return redirect('/')
Example #42
0
 def inject_user():
     if authed():
         return dict(session)
     return dict()
Example #43
0
def profile():
    if utils.authed():
        if request.method == "POST":
            errors = []

            name = request.form.get('name').strip()
            email = request.form.get('email').strip()
            affiliation = request.form.get('grade').strip()
            website = request.form.get('major').strip()
            country = request.form.get('college').strip()

            user = Teams.query.filter_by(id=session['id']).first()

            if not utils.get_config('prevent_name_change'):
                names = Teams.query.filter_by(name=name).first()
                name_len = len(request.form['name']) == 0

            emails = Teams.query.filter_by(email=email).first()
            valid_email = utils.check_email_format(email)

            if utils.check_email_format(name) is True:
                errors.append('用户名不能和邮箱一样')

            if ('password' in request.form.keys() and not len(request.form['password']) == 0) and \
                    (not bcrypt_sha256.verify(request.form.get('confirm').strip(), user.password)):
                errors.append("旧密码错误")
            if not valid_email:
                errors.append("邮箱格式不对")
            if not utils.get_config(
                    'prevent_name_change'
            ) and names and name != session['username']:
                errors.append('用户名已被其他用户使用')
            if emails and emails.id != session['id']:
                errors.append('邮箱已被其他用户使用')
            if not utils.get_config('prevent_name_change') and name_len:
                errors.append('用户名长度不够')
            #if website.strip() and not utils.validate_url(website):
            #errors.append("That doesn't look like a valid URL")

            if len(errors) > 0:
                return render_template('profile.html',
                                       name=name,
                                       email=email,
                                       website=website,
                                       affiliation=affiliation,
                                       country=country,
                                       errors=errors)
            else:
                team = Teams.query.filter_by(id=session['id']).first()
                if team.name != name:
                    if not utils.get_config('prevent_name_change'):
                        team.name = name
                        session['username'] = team.name
                if team.email != email.lower():
                    team.email = email.lower()
                    if utils.get_config('verify_emails'):
                        team.verified = False

                if 'password' in request.form.keys() and not len(
                        request.form['password']) == 0:
                    team.password = bcrypt_sha256.encrypt(
                        request.form.get('password'))
                team.website = website
                team.affiliation = affiliation
                team.country = country
                db.session.commit()
                db.session.close()
                return redirect(url_for('views.profile'))
        else:
            user = Teams.query.filter_by(id=session['id']).first()
            name = user.name
            email = user.email
            website = user.website
            affiliation = user.affiliation
            country = user.country
            prevent_name_change = utils.get_config('prevent_name_change')
            confirm_email = utils.get_config(
                'verify_emails') and not user.verified
            return render_template('profile.html',
                                   name=name,
                                   email=email,
                                   major=website,
                                   grade=affiliation,
                                   college=country,
                                   prevent_name_change=prevent_name_change,
                                   confirm_email=confirm_email)
    else:
        return redirect(url_for('auth.login'))
Example #44
0
def chal(chalid):
    if utils.ctf_ended() and not utils.view_after_ctf():
        return redirect(url_for('challenges.challenges_view'))
    if not utils.user_can_view_challenges():
        return redirect(url_for('auth.login', next=request.path))
    if utils.authed() and utils.is_verified() and (utils.ctf_started()
                                                   or utils.view_after_ctf()):
        fails = WrongKeys.query.filter_by(teamid=session['id'],
                                          chalid=chalid).count()
        logger = logging.getLogger('keys')
        data = (time.strftime("%m/%d/%Y %X"),
                session['username'].encode('utf-8'),
                request.form['key'].encode('utf-8'),
                utils.get_kpm(session['id']))
        print("[{0}] {1} submitted {2} with kpm {3}".format(*data))

        # Anti-bruteforce / submitting keys too quickly
        if utils.get_kpm(session['id']) > 10:
            if utils.ctftime():
                wrong = WrongKeys(teamid=session['id'],
                                  chalid=chalid,
                                  ip=utils.get_ip(),
                                  flag=request.form['key'].strip())
                db.session.add(wrong)
                db.session.commit()
                db.session.close()
            logger.warn(
                "[{0}] {1} submitted {2} with kpm {3} [TOO FAST]".format(
                    *data))
            # return '3' # Submitting too fast
            return jsonify({
                'status':
                3,
                'message':
                "You're submitting keys too fast. Slow down."
            })

        solves = Solves.query.filter_by(teamid=session['id'],
                                        chalid=chalid).first()

        # Challange not solved yet
        if not solves:
            chal = Challenges.query.filter_by(id=chalid).first_or_404()
            provided_key = request.form['key'].strip()
            saved_keys = Keys.query.filter_by(chal=chal.id).all()

            # Hit max attempts
            max_tries = chal.max_attempts
            if max_tries and fails >= max_tries > 0:
                return jsonify({
                    'status': 0,
                    'message': "You have 0 tries remaining"
                })

            chal_class = get_chal_class(chal.type)
            status, message = chal_class.solve(chal, provided_key)
            if status:  # The challenge plugin says the input is right
                # TODO: if auth flag success, add gamble point
                if utils.ctftime():
                    score = chal.value
                    original_score = chal.original_value

                    solved_problem = Solves.query.filter_by(
                        chalid=chalid).count()
                    solved_team = Solves.query.filter_by(chalid=chalid).all()

                    challenge = Challenges.query.filter_by(id=chalid).first()

                    solve = Solves(teamid=session['id'],
                                   chalid=chalid,
                                   ip=utils.get_ip(),
                                   flag=provided_key)
                    gamble = Gamble(teamid=session['id'],
                                    chalid=chalid,
                                    value=original_score)
                    gamble.name = "gamble point"

                    # result = (original_score * ((solved_problem * 10) / 100))
                    result = (original_score * (1 / 10))

                    failed = False
                    try:
                        if solved_problem == 0:
                            challenge.original_value = score

                        if solved_problem >= 1:
                            challenge.value -= result
                            db.session.add(challenge)
                            db.session.commit()

                        db.session.add(solve)
                        db.session.commit()

                        db.session.add(gamble)
                        db.session.commit()

                        db.session.close()

                    except Exception as e:
                        db.session.rollback()
                        db.session.flush()
                        failed = True

                logger.info(
                    "[{0}] {1} submitted {2} with kpm {3} [CORRECT]".format(
                        *data))
                return jsonify({'status': 1, 'message': message})
            else:  # The challenge plugin says the input is wrong
                if utils.ctftime():
                    wrong = WrongKeys(teamid=session['id'],
                                      chalid=chalid,
                                      ip=utils.get_ip(),
                                      flag=provided_key)
                    db.session.add(wrong)
                    db.session.commit()
                    db.session.close()
                logger.info(
                    "[{0}] {1} submitted {2} with kpm {3} [WRONG]".format(
                        *data))
                # return '0' # key was wrong
                if max_tries:
                    attempts_left = max_tries - fails - 1  # Off by one since fails has changed since it was gotten
                    tries_str = 'tries'
                    if attempts_left == 1:
                        tries_str = 'try'
                    if message[
                            -1] not in '!().;?[]\{\}':  # Add a punctuation mark if there isn't one
                        message = message + '.'
                    return jsonify({
                        'status':
                        0,
                        'message':
                        '{} You have {} {} remaining.'.format(
                            message, attempts_left, tries_str)
                    })
                else:
                    return jsonify({'status': 0, 'message': message})

        # Challenge already solved
        else:
            logger.info(
                "{0} submitted {1} with kpm {2} [ALREADY SOLVED]".format(
                    *data))
            # return '2' # challenge was already solved
            return jsonify({'status': 2, 'message': 'You already solved this'})
    else:
        return jsonify({
            'status': -1,
            'message': "You must be logged in to solve a challenge"
        })
Example #45
0
def logout():
    if utils.authed():
        session.clear()
    return redirect(url_for('views.index'))
Example #46
0
def logout():
    if utils.authed():
        session.clear()
    return redirect(url_for('views.static_html'))
Example #47
0
def chals():
    if not utils.is_admin():
        if not utils.ctftime():
            if utils.view_after_ctf():
                pass
            else:
                abort(403)

    if utils.get_config('verify_emails'):
        if utils.authed():
            if utils.is_admin() is False and utils.is_verified(
            ) is False:  # User is not confirmed
                abort(403)

    if utils.user_can_view_challenges() and (utils.ctf_started()
                                             or utils.is_admin()):
        teamid = session.get('id')
        chals = Challenges.query.filter(
            or_(Challenges.hidden != True,
                Challenges.hidden == None)).order_by(Challenges.value).all()
        json = {'game': []}
        for x in chals:
            tags = [
                tag.tag for tag in Tags.query.add_columns('tag').filter_by(
                    chal=x.id).all()
            ]
            files = [
                str(f.location)
                for f in Files.query.filter_by(chal=x.id).all()
            ]
            unlocked_hints = set([
                u.itemid
                for u in Unlocks.query.filter_by(model='hints', teamid=teamid)
            ])
            hints = []
            for hint in Hints.query.filter_by(chal=x.id).all():
                if hint.id in unlocked_hints or utils.ctf_ended():
                    hints.append({
                        'id': hint.id,
                        'cost': hint.cost,
                        'hint': hint.hint
                    })
                else:
                    hints.append({'id': hint.id, 'cost': hint.cost})
            chal_type = get_chal_class(x.type)
            json['game'].append({
                'id': x.id,
                'type': chal_type.name,
                'name': x.name,
                'value': x.value,
                'description': x.description,
                'category': x.category,
                'files': files,
                'tags': tags,
                'hints': hints,
                'template': chal_type.templates['modal'],
                'script': chal_type.scripts['modal'],
            })

        db.session.close()
        return jsonify(json)
    else:
        db.session.close()
        abort(403)
Example #48
0
 def csrf():
     if authed() and request.method == "POST":
         if session['nonce'] != request.form.get('nonce'):
             abort(403)
Example #49
0
def solves(teamid=None):
    solves = None
    awards = None
    if teamid is None:
        if utils.is_admin():
            solves = Solves.query.filter_by(teamid=session['id']).all()
        elif utils.user_can_view_challenges():
            if utils.authed():
                solves = Solves.query.join(Teams,
                                           Solves.teamid == Teams.id).filter(
                                               Solves.teamid == session['id'],
                                               Teams.banned == False).all()
            else:
                return jsonify({'solves': []})
        else:
            return redirect(url_for('auth.login', next='solves'))
    else:
        if utils.authed() and session['id'] == teamid:
            solves = Solves.query.filter_by(teamid=teamid)
            awards = Awards.query.filter_by(teamid=teamid)

            freeze = utils.get_config('freeze')
            if freeze:
                freeze = utils.unix_time_to_utc(freeze)
                if teamid != session.get('id'):
                    solves = solves.filter(Solves.date < freeze)
                    awards = awards.filter(Awards.date < freeze)

            solves = solves.all()
            awards = awards.all()
        elif utils.hide_scores():
            # Use empty values to hide scores
            solves = []
            awards = []
        else:
            solves = Solves.query.filter_by(teamid=teamid)
            awards = Awards.query.filter_by(teamid=teamid)

            freeze = utils.get_config('freeze')
            if freeze:
                freeze = utils.unix_time_to_utc(freeze)
                if teamid != session.get('id'):
                    solves = solves.filter(Solves.date < freeze)
                    awards = awards.filter(Awards.date < freeze)

            solves = solves.all()
            awards = awards.all()
    db.session.close()
    json = {'solves': []}
    for solve in solves:
        json['solves'].append({
            'chal': solve.chal.name,
            'chalid': solve.chalid,
            'team': solve.teamid,
            'value': solve.chal.value,
            'category': solve.chal.category,
            'time': utils.unix_time(solve.date)
        })
    if awards:
        for award in awards:
            json['solves'].append({
                'chal': award.name,
                'chalid': None,
                'team': award.teamid,
                'value': award.value,
                'category': award.category or "Award",
                'time': utils.unix_time(award.date)
            })
    json['solves'].sort(key=lambda k: k['time'])
    return jsonify(json)
Example #50
0
    def profile():
        if authed():
            if request.method == "POST":
                errors = []

                name = request.form.get('name')
                email = request.form.get('email')
                website = request.form.get('website')
                affiliation = request.form.get('affiliation')
                country = request.form.get('country')

                names = Teams.query.filter_by(name=name).first()
                emails = Teams.query.filter_by(email=email).first()
                valid_email = re.match("[^@]+@[^@]+\.[^@]+", email)

                name_len = len(request.form['name']) == 0

                if not bcrypt_sha256.verify(
                        request.form.get('confirm').strip(), names.password):
                    errors.append(
                        "Your old password doesn't match what we have.")
                if not valid_email:
                    errors.append("That email doesn't look right")
                if names and name != session['username']:
                    errors.append('That team name is already taken')
                if emails and emails.id != session['id']:
                    errors.append('That email has already been used')
                if name_len:
                    errors.append('Pick a longer team name')

                if len(errors) > 0:
                    return render_template('profile.html',
                                           name=name,
                                           email=email,
                                           website=website,
                                           affiliation=affiliation,
                                           country=country,
                                           errors=errors)
                else:
                    team = Teams.query.filter_by(id=session['id']).first()
                    team.name = name
                    team.email = email
                    if 'password' in request.form.keys() and not len(
                            request.form['password']) == 0:
                        team.password = bcrypt_sha256.encrypt(
                            request.form.get('password'))
                    team.website = website
                    team.affiliation = affiliation
                    team.country = country
                    db.session.commit()
                    db.session.close()
                    return redirect('/profile')
            else:
                user = Teams.query.filter_by(id=session['id']).first()
                name = user.name
                email = user.email
                website = user.website
                affiliation = user.affiliation
                country = user.country
                return render_template('profile.html',
                                       name=name,
                                       email=email,
                                       website=website,
                                       affiliation=affiliation,
                                       country=country)
        else:
            return redirect('/login')
Example #51
0
def chal(chalid):
    if utils.ctf_paused():
        return jsonify({
            'status': 3,
            'message': get_tip('IS_PAUSED').format(utils.ctf_name())
        })
    if utils.ctf_ended() and not utils.view_after_ctf():
        abort(403)
    if not utils.user_can_view_challenges():
        return redirect(url_for('auth.login', next=request.path))
    if (utils.authed() and utils.is_verified() and
        (utils.ctf_started() or utils.view_after_ctf())) or utils.is_admin():
        team = Teams.query.filter_by(id=session['id']).first()
        fails = WrongKeys.query.filter_by(teamid=session['id'],
                                          chalid=chalid).count()
        logger = logging.getLogger('keys')
        data = (time.strftime("%m/%d/%Y %X"),
                session['username'].encode('utf-8'),
                request.form['key'].encode('utf-8'),
                utils.get_kpm(session['id']))
        print("[{0}] {1} submitted {2} with kpm {3}".format(*data))

        chal = Challenges.query.filter_by(id=chalid).first_or_404()
        if chal.hidden:
            abort(404)
        chal_class = get_chal_class(chal.type)

        # Anti-bruteforce / submitting keys too quickly
        if utils.get_kpm(session['id']) > 10:
            if utils.ctftime():
                chal_class.fail(team=team, chal=chal, request=request)
            logger.warn(
                "[{0}] {1} submitted {2} with kpm {3} [TOO FAST]".format(
                    *data))
            # return '3' # Submitting too fast
            return jsonify({
                'status': 3,
                'message': get_tip('SUBMIT_TOO_FAST')
            })

        solves = Solves.query.filter_by(teamid=session['id'],
                                        chalid=chalid).first()

        # Challange not solved yet
        if not solves:
            provided_key = request.form['key'].strip()
            saved_keys = Keys.query.filter_by(chal=chal.id).all()

            # Hit max attempts
            max_tries = chal.max_attempts
            if max_tries and fails >= max_tries > 0:
                return jsonify({
                    'status': 0,
                    'message': get_tip('ZERO_CAN_TRY')
                })

            status, message = chal_class.attempt(chal, request)
            if status:  # The challenge plugin says the input is right
                if utils.ctftime() or utils.is_admin():
                    chal_class.solve(team=team, chal=chal, request=request)
                logger.info(
                    "[{0}] {1} submitted {2} with kpm {3} [CORRECT]".format(
                        *data))
                return jsonify({'status': 1, 'message': message})
            else:  # The challenge plugin says the input is wrong
                if utils.ctftime() or utils.is_admin():
                    chal_class.fail(team=team, chal=chal, request=request)
                logger.info(
                    "[{0}] {1} submitted {2} with kpm {3} [WRONG]".format(
                        *data))
                # return '0' # key was wrong
                if max_tries:
                    attempts_left = max_tries - fails - 1  # Off by one since fails has changed since it was gotten
                    tries_str = 'tries'
                    if attempts_left == 1:
                        tries_str = 'try'
                    if message[
                            -1] not in '!().;?[]\{\}':  # Add a punctuation mark if there isn't one
                        message = message + '.'
                    return jsonify({
                        'status':
                        0,
                        'message':
                        get_tip('MANY_CAN_TRY').format(message, attempts_left,
                                                       tries_str)
                    })
                else:
                    return jsonify({'status': 0, 'message': message})

        # Challenge already solved
        else:
            logger.info(
                "{0} submitted {1} with kpm {2} [ALREADY SOLVED]".format(
                    *data))
            # return '2' # challenge was already solved
            return jsonify({'status': 2, 'message': get_tip('HAVE_SOLVE')})
    else:
        return jsonify({'status': -1, 'message': get_tip('MUST_LOGGED')})
Example #52
0
def chal(chalid):
    if not ctftime():
        return redirect(url_for('challenges.challenges_view'))
    if authed():
        fails = WrongKeys.query.filter_by(teamid=session['id'], chalid=chalid).count()
        logger = logging.getLogger('keys')
        data = (time.strftime("%m/%d/%Y %X"), session['username'].encode('utf-8'), request.form['key'].encode('utf-8'), get_kpm(session['id']))
        print("[{0}] {1} submitted {2} with kpm {3}".format(*data))

        # Hit max attempts
        if fails >= int(get_config("max_tries")) and int(get_config("max_tries")) > 0:
            return "4" #too many tries on this challenge

        # Anti-bruteforce / submitting keys too quickly
        if get_kpm(session['id']) > 10:
            wrong = WrongKeys(session['id'], chalid, request.form['key'])
            db.session.add(wrong)
            db.session.commit()
            db.session.close()
            logger.warn("[{0}] {1} submitted {2} with kpm {3} [TOO FAST]".format(*data))
            return "3" # Submitting too fast

        solves = Solves.query.filter_by(teamid=session['id'], chalid=chalid).first()

        # Challange not solved yet
        if not solves:
            chal = Challenges.query.filter_by(id=chalid).first()
            key = str(request.form['key'].strip().lower())
            keys = json.loads(chal.flags)
            for x in keys:
                if x['type'] == 0: #static key
                    print(x['flag'], key.strip().lower())
                    if x['flag'] and x['flag'].strip().lower() == key.strip().lower():
                        solve = Solves(chalid=chalid, teamid=session['id'], ip=get_ip(), flag=key)
                        db.session.add(solve)
                        db.session.commit()
                        db.session.close()
                        logger.info("[{0}] {1} submitted {2} with kpm {3} [CORRECT]".format(*data))
                        return "1" # key was correct
                elif x['type'] == 1: #regex
                    res = re.match(str(x['flag']), key, re.IGNORECASE)
                    if res and res.group() == key:
                        solve = Solves(chalid=chalid, teamid=session['id'], ip=get_ip(), flag=key)
                        db.session.add(solve)
                        db.session.commit()
                        db.session.close()
                        logger.info("[{0}] {1} submitted {2} with kpm {3} [CORRECT]".format(*data))
                        return "1" # key was correct

            wrong = WrongKeys(session['id'], chalid, request.form['key'])
            db.session.add(wrong)
            db.session.commit()
            db.session.close()
            logger.info("[{0}] {1} submitted {2} with kpm {3} [WRONG]".format(*data))
            return '0' # key was wrong

        # Challenge already solved
        else:
            logger.info("{0} submitted {1} with kpm {2} [ALREADY SOLVED]".format(*data))
            return "2" # challenge was already solved
    else:
        return "-1"
Example #53
0
def chal_custom(chalid):
    if utils.ctf_paused():
        return jsonify({
            'status': 3,
            'message': '{} is paused'.format(utils.ctf_name())
        })
    if (utils.authed() and utils.is_verified() and
        (utils.ctf_started() or utils.view_after_ctf())) or utils.is_admin():
        team = Teams.query.filter_by(id=session['id']).first()
        fails = WrongKeys.query.filter_by(teamid=session['id'],
                                          chalid=chalid).count()
        logger = logging.getLogger('keys')
        data = (time.strftime("%m/%d/%Y %X"),
                session['username'].encode('utf-8'),
                request.form['key'].encode('utf-8'),
                utils.get_kpm(session['id']))
        print("[{0}] {1} submitted {2} with kpm {3}".format(*data))

        chal = Challenges.query.filter_by(id=chalid).first_or_404()
        if chal.hidden:
            abort(404)
        chal_class = get_chal_class(chal.type)

        # Anti-bruteforce / submitting keys too quickly
        if utils.get_kpm(session['id']) > 10:
            if utils.ctftime():
                chal_class.fail(team=team, chal=chal, request=request)
            logger.warn(
                "[{0}] {1} submitted {2} with kpm {3} [TOO FAST]".format(
                    *data))
            # return '3' # Submitting too fast
            return jsonify({
                'status':
                3,
                'message':
                "You're submitting keys too fast. Slow down."
            })

        solves = Solves.query.filter_by(teamid=session['id'],
                                        chalid=chalid).first()

        # Challange not solved yet
        if not solves:
            provided_key = request.form['key'].strip()
            saved_keys = Keys.query.filter_by(chal=chal.id).all()

            # Hit max attempts
            max_tries = chal.max_attempts
            if max_tries and fails >= max_tries > 0:
                return jsonify({
                    'status': 0,
                    'message': "You have 0 tries remaining"
                })

            status, message = chal_class.attempt(chal, request)
            if status:  # The challenge plugin says the input is right
                if utils.ctftime() or utils.is_admin():
                    chal_class.solve(team=team, chal=chal, request=request)
                logger.info(
                    "[{0}] {1} submitted {2} with kpm {3} [CORRECT]".format(
                        *data))

                if "SmartCity" in str(chal_class):
                    print(session['id'])
                    smart_color = SmartCityTeam.query.filter_by(
                        teamId=session['id']).first().color
                    smart_buildingId = SmartCityChallenge.query.filter_by(
                        id=chalid).first().buildingId
                    smart_soundId = SmartCityChallenge.query.filter_by(
                        id=chalid).first().soundId
                    smart_image = SmartCityTeam.query.filter_by(
                        teamId=session['id']).first().image
                    b = smart_buildingId.split('\', \'')
                    b[0] = b[0][2:]
                    b[-1] = b[-1][:-2]
                    print("Team with color " + str(smart_color) +
                          " and image " + str(smart_image) +
                          " solved challenege with buildingId " + str(b) +
                          "and sound " + smart_soundId)
                    smartSession = SmartTable(b, smart_color, smart_image,
                                              smart_soundId)
                    createSmartCityTableSession2(smartSession)

                return jsonify({'status': 1, 'message': message})
            else:  # The challenge plugin says the input is wrong
                if utils.ctftime() or utils.is_admin():
                    chal_class.fail(team=team, chal=chal, request=request)
                logger.info(
                    "[{0}] {1} submitted {2} with kpm {3} [WRONG]".format(
                        *data))
                # return '0' # key was wrong
                if max_tries:
                    attempts_left = max_tries - fails - 1  # Off by one since fails has changed since it was gotten
                    tries_str = 'tries'
                    if attempts_left == 1:
                        tries_str = 'try'
                    if message[
                            -1] not in '!().;?[]\{\}':  # Add a punctuation mark if there isn't one
                        message = message + '.'
                    return jsonify({
                        'status':
                        0,
                        'message':
                        '{} You have {} {} remaining.'.format(
                            message, attempts_left, tries_str)
                    })
                else:
                    return jsonify({'status': 0, 'message': message})

        # Challenge already solved
        else:
            logger.info(
                "{0} submitted {1} with kpm {2} [ALREADY SOLVED]".format(
                    *data))
            # return '2' # challenge was already solved
            return jsonify({'status': 2, 'message': 'You already solved this'})
    else:
        return jsonify({
            'status': -1,
            'message': "You must be logged in to solve a challenge"
        })
Example #54
0
def confirm_user(data=None):
    if not utils.get_config('verify_emails'):
        # If the CTF doesn't care about confirming email addresses then redierct to challenges
        return redirect(url_for('challenges.challenges_view'))

    logger = logging.getLogger('regs')
    # User is confirming email account
    if data and request.method == "GET":
        try:
            s = TimedSerializer(app.config['SECRET_KEY'])
            email = s.loads(utils.base64decode(data, urldecode=True),
                            max_age=1800)
        except BadTimeSignature:
            return render_template(
                'confirm.html', errors=['Your confirmation link has expired'])
        except (BadSignature, TypeError, base64.binascii.Error):
            return render_template(
                'confirm.html', errors=['Your confirmation token is invalid'])
        team = Teams.query.filter_by(email=email).first_or_404()
        team.verified = True
        db.session.commit()
        logger.warn(
            "[{date}] {ip} - {username} confirmed their account".format(
                date=time.strftime("%m/%d/%Y %X"),
                ip=utils.get_ip(),
                username=team.name.encode('utf-8'),
                email=team.email.encode('utf-8')))
        db.session.close()
        if utils.authed():
            return redirect(url_for('challenges.challenges_view'))
        return redirect(url_for('auth.login'))

    # User is trying to start or restart the confirmation flow
    if not utils.authed():
        return redirect(url_for('auth.login'))

    team = Teams.query.filter_by(id=session['id']).first_or_404()

    if data is None:
        if request.method == "POST":
            # User wants to resend their confirmation email
            if team.verified:
                return redirect(url_for('views.profile'))
            else:
                utils.verify_email(team.email)
                logger.warn(
                    "[{date}] {ip} - {username} initiated a confirmation email resend"
                    .format(date=time.strftime("%m/%d/%Y %X"),
                            ip=utils.get_ip(),
                            username=team.name.encode('utf-8'),
                            email=team.email.encode('utf-8')))
            return render_template(
                'confirm.html',
                team=team,
                infos=['Your confirmation email has been resent!'])
        elif request.method == "GET":
            # User has been directed to the confirm page
            team = Teams.query.filter_by(id=session['id']).first_or_404()
            if team.verified:
                # If user is already verified, redirect to their profile
                return redirect(url_for('views.profile'))
            return render_template('confirm.html', team=team)
Example #55
0
def chal(chalid):
    if ctf_ended() and not view_after_ctf():
        return redirect(url_for('challenges.challenges_view'))
    if not user_can_view_challenges():
        return redirect(url_for('auth.login', next=request.path))
    if authed() and is_verified() and (ctf_started() or view_after_ctf()):
        fails = WrongKeys.query.filter_by(teamid=session['id'],
                                          chalid=chalid).count()
        logger = logging.getLogger('keys')
        data = (time.strftime("%m/%d/%Y %X"),
                session['username'].encode('utf-8'),
                request.form['key'].encode('utf-8'), get_kpm(session['id']))
        print("[{0}] {1} submitted {2} with kpm {3}".format(*data))

        # Anti-bruteforce / submitting keys too quickly
        if get_kpm(session['id']) > 10:
            if ctftime():
                wrong = WrongKeys(session['id'], chalid, request.form['key'])
                db.session.add(wrong)
                db.session.commit()
                db.session.close()
            logger.warn(
                "[{0}] {1} submitted {2} with kpm {3} [TOO FAST]".format(
                    *data))
            # return '3' # Submitting too fast
            return jsonify({
                'status':
                '3',
                'message':
                "You're submitting keys too fast. Slow down."
            })

        solves = Solves.query.filter_by(teamid=session['id'],
                                        chalid=chalid).first()

        # Challange not solved yet
        if not solves:
            chal = Challenges.query.filter_by(id=chalid).first_or_404()
            key = unicode(request.form['key'].strip().lower())
            keys = json.loads(chal.flags)

            # Hit max attempts
            max_tries = int(get_config("max_tries"))
            if fails >= max_tries > 0:
                return jsonify({
                    'status': '0',
                    'message': "You have 0 tries remaining"
                })

            for x in keys:
                if x['type'] == 0:  # static key
                    print(x['flag'], key.strip().lower())
                    if x['flag'] and x['flag'].strip().lower() == key.strip(
                    ).lower():
                        if ctftime():
                            solve = Solves(chalid=chalid,
                                           teamid=session['id'],
                                           ip=get_ip(),
                                           flag=key)
                            db.session.add(solve)
                            db.session.commit()
                            db.session.close()
                        logger.info(
                            "[{0}] {1} submitted {2} with kpm {3} [CORRECT]".
                            format(*data))
                        # return '1' # key was correct
                        return jsonify({'status': '1', 'message': 'Correct'})
                elif x['type'] == 1:  # regex
                    res = re.match(x['flag'], key, re.IGNORECASE)
                    if res and res.group() == key:
                        if ctftime():
                            solve = Solves(chalid=chalid,
                                           teamid=session['id'],
                                           ip=get_ip(),
                                           flag=key)
                            db.session.add(solve)
                            db.session.commit()
                            db.session.close()
                        logger.info(
                            "[{0}] {1} submitted {2} with kpm {3} [CORRECT]".
                            format(*data))
                        # return '1' # key was correct
                        return jsonify({'status': '1', 'message': 'Correct'})

            if ctftime():
                wrong = WrongKeys(session['id'], chalid, request.form['key'])
                db.session.add(wrong)
                db.session.commit()
                db.session.close()
            logger.info(
                "[{0}] {1} submitted {2} with kpm {3} [WRONG]".format(*data))
            # return '0' # key was wrong
            if max_tries:
                attempts_left = max_tries - fails
                tries_str = 'tries'
                if attempts_left == 1:
                    tries_str = 'try'
                return jsonify({
                    'status':
                    '0',
                    'message':
                    'Incorrect. You have {} {} remaining.'.format(
                        attempts_left, tries_str)
                })
            else:
                return jsonify({'status': '0', 'message': 'Incorrect'})

        # Challenge already solved
        else:
            logger.info(
                "{0} submitted {1} with kpm {2} [ALREADY SOLVED]".format(
                    *data))
            # return '2' # challenge was already solved
            return jsonify({
                'status': '2',
                'message': 'You already solved this'
            })
    else:
        return '-1'
def solves_private_endpoint():
    if not utils.authed():
        return jsonify({'solves': []})
    solves_public_endpoint(session['id'])
Example #57
0
File: auth.py Project: yuzunzz/CTFd
def logout():
    if authed():
        session.clear()
    return redirect(url_for('views.static_html'))
Example #58
0
File: auth.py Project: HackUCF/CTFd
def logout():
    if authed():
        session.clear()
    return redirect('/')
Example #59
0
def chal_contest(contestid, chalid):
    contest = Contests.query.filter_by(id=contestid).first()

    if utils.ctf_ended(
            contest=contest) and not utils.view_after_ctf(contest=contest):
        return redirect(url_for('challenges.challenges_view'))
    if not utils.user_can_view_challenges(contest=contest):
        return redirect(url_for('contests.contests_view'))
    if utils.authed() and utils.is_verified() and utils.is_participated(
            contest=contest) and (utils.ctf_started(contest=contest)
                                  or utils.view_after_ctf(contest=contest)):
        fails = WrongKeys.query.filter_by(teamid=session['id'],
                                          chalid=chalid).count()
        logger = logging.getLogger('keys')
        data = (time.strftime("%m/%d/%Y %X"),
                session['username'].encode('utf-8'),
                request.form['key'].encode('utf-8'),
                utils.get_kpm(session['id']))
        print("[{0}] {1} submitted {2} with kpm {3}".format(*data))

        # Anti-bruteforce / submitting keys too quickly
        if utils.get_kpm(session['id']) > 10:
            if utils.ctftime():
                wrong = WrongKeys(teamid=session['id'],
                                  chalid=chalid,
                                  ip=utils.get_ip(),
                                  flag=request.form['key'].strip())
                db.session.add(wrong)
                db.session.commit()
                db.session.close()
            logger.warn(
                "[{0}] {1} submitted {2} with kpm {3} [TOO FAST]".format(
                    *data))
            # return '3' # Submitting too fast
            return jsonify({
                'status':
                3,
                'message':
                "You're submitting keys too fast. Slow down."
            })

        solves = Solves.query.filter_by(teamid=session['id'],
                                        chalid=chalid).first()

        chal = Challenges.query.filter_by(id=chalid).first_or_404()
        provided_key = request.form['key'].strip()
        saved_keys = Keys.query.filter_by(chal=chal.id).all()

        # Hit max attempts
        max_tries = chal.max_attempts
        if max_tries and fails >= max_tries > 0:
            return jsonify({
                'status': 0,
                'message': "You have 0 tries remaining"
            })

        chal_class = get_chal_class(chal.type)
        status, message = chal_class.solve(chal, provided_key)
        if status:  # The challenge plugin says the input is right
            if utils.ctftime(contest=contest):
                solve = Solves(teamid=session['id'],
                               chalid=chalid,
                               ip=utils.get_ip(),
                               flag=provided_key,
                               contestid=contestid)
                db.session.add(solve)
                db.session.commit()
                db.session.close()
            else:
                message += '. But time is up'

            if solves:
                message += ". You already solved this"
                logger.info(
                    "{0} submitted {1} with kpm {2} [ALREADY SOLVED]".format(
                        *data))
                # return '2' # challenge was already solved
                return jsonify({'status': 2, 'message': message})

            logger.info(
                "[{0}] {1} submitted {2} with kpm {3} [CORRECT]".format(*data))
            return jsonify({'status': 1, 'message': message})
        else:  # The challenge plugin says the input is wrong
            if utils.ctftime(contest=contest):
                wrong = WrongKeys(teamid=session['id'],
                                  chalid=chalid,
                                  ip=utils.get_ip(),
                                  flag=provided_key,
                                  contestid=contestid)
                db.session.add(wrong)
                db.session.commit()
                db.session.close()
            else:
                message += '. But time is up'

            if solves:
                message += ". You already solved this"
                logger.info(
                    "{0} submitted {1} with kpm {2} [ALREADY SOLVED]".format(
                        *data))
                # return '2' # challenge was already solved
                return jsonify({'status': 2, 'message': message})

            logger.info(
                "[{0}] {1} submitted {2} with kpm {3} [WRONG]".format(*data))
            # return '0' # key was wrong
            if max_tries:
                attempts_left = max_tries - fails - 1  # Off by one since fails has changed since it was gotten
                tries_str = 'tries'
                if attempts_left == 1:
                    tries_str = 'try'
                if message[
                        -1] not in '!().;?[]\{\}':  # Add a punctuation mark if there isn't one
                    message = message + '.'
                return jsonify({
                    'status':
                    0,
                    'message':
                    '{} You have {} {} remaining.'.format(
                        message, attempts_left, tries_str)
                })
            else:
                return jsonify({'status': 0, 'message': message})

    else:
        return jsonify({
            'status': -1,
            'message': "You must be logged in to solve a challenge"
        })