Esempio n. 1
0
def register():
    if not Config.get().register_open:
        return error("Registration is closed")

    username = request.json.get("username", "").strip()
    if not username:
        return error("Username is required")
    user = User.query.filter(User.name == username).first()
    if user:
        return error("The user `{}` already exists".format(username))

    email = request.json.get("email", "").strip()
    if not email:
        return error("Email address is required")
    user = User.query.filter(User.email == email).first()
    if user:
        return error("The email address is already used")
    # TODO: check email format
    # TODO check the number of teammates

    password = request.json.get("password", "").strip()
    if not password:
        return error("Password is required")

    if request.json.get("teamtoken"):
        token = request.json.get("teamtoken").strip()
        team = Team.query.filter(Team.token == token, Team.valid == True).first()
        if not team:
            return error("Team token is invalid")
    elif request.json.get("teamname"):
        teamname = request.json.get("teamname").strip()
        team = Team.query.filter(Team.name == teamname).first()
        if team and team.valid:
            return error("The team `{}` already exists".format(teamname))

        team = Team(name=teamname)
        team.valid = True
        team.renewToken()
        db.session.add(team)
        db.session.commit()
    else:
        return error("Either team token or team name is required")

    user = User()
    user.name = username
    user.password = password
    user.email = email
    user.team_id = team.id
    user.verified = False
    user.issueResetToken()

    db.session.add(user)
    db.session.commit()

    logger.log(":heavy_plus_sign: `{}@{}` registered".format(user.name, user.team.name))
    send_verification_mail(user)

    return jsonify({"id": user.id, "name": user.name})
Esempio n. 2
0
def challenge_recalc():
    """recalc challenge scores"""
    config = Config.get()  # type: Config

    # commit
    for chall in Challenge.query.all():  # type: Chall
        chall.recalc_score(config.score_expr)

        db.session.add(chall)
        db.session.commit()
        print("[+]{}: {}".format(chall.score, chall.name))
Esempio n. 3
0
def init():
    """initialize CTF by yaml file"""
    # initialize db
    db.create_all()
    db.session.commit()

    ctf = Config.get() or Config()  # type: Config
    ctf.name = app.config["CTF_NAME"]
    ctf.flag_format = app.config["FLAGFORMAT"]
    ctf.start_at = int(
        app.config["START_AT"].timestamp()
        # - app.config["START_AT"].utcoffset().total_seconds()
    )
    ctf.end_at = int(
        app.config["END_AT"].timestamp()
        # - app.config["END_AT"].utcoffset().total_seconds()
    )
    ctf.email = app.config["EMAIL"]
    ctf.email_password = app.config["EMAIL_PASSWORD"]
    ctf.invite_url = app.config["INVITE_URL"]
    ctf.score_expr = app.config["SCORE_EXPR"]
    ctf.is_open = ctf.is_open or False
    ctf.register_open = ctf.register_open or False

    admin = User.query.filter(User.is_admin == True).first() or User()  # type: User
    admin.name = app.config["ADMIN_NAME"]
    admin.email = "*****@*****.**"
    admin.verified = True
    admin.password = app.config["ADMIN_PASSWORD"]
    admin.is_admin = True

    # commit
    db.session.add(ctf)
    db.session.add(admin)
    db.session.commit()

    # print
    printConfig(ctf)
Esempio n. 4
0
def open(register, close):
    """open CTF and/or registration"""
    config = Config.get()
    config.register_open = not close
    if not register:
        config.is_open = not close

    # commit
    db.session.add(config)
    db.session.commit()

    # print
    printConfig(config)
    print("[+]Done")
Esempio n. 5
0
def update():
    user = get_login_user()
    config = Config.get()
    ctf_name = config.name
    register_open = config.register_open
    ctf_open = config.ctf_open
    ctf_frozen = config.ctf_frozen
    valid_only = not ctf_frozen
    users = get_users(valid_only=valid_only)
    teams = get_teams(valid_only=True)

    r = {
        "is_login":
        bool(user),
        "start_at":
        datetime.fromtimestamp(config.start_at).isoformat() + "Z",
        "end_at":
        datetime.fromtimestamp(config.end_at).isoformat() + "Z",
        "ctf_name":
        ctf_name,
        "flag_format":
        config.flag_format,
        "invite_url":
        config.invite_url,
        "ctf_open":
        ctf_open,
        "ctf_frozen":
        ctf_frozen,
        "score_expr":
        config.score_expr.replace("V",
                                  "base_score").replace("N", "solve_count"),
        "register_open":
        register_open,
        "users":
        users,
        "teams":
        teams,
        "challenges": {},
    }
    if user:
        userinfo, teaminfo = get_user_and_team(user, valid_only=valid_only)
        r["user"] = userinfo
        r["team"] = teaminfo
    if config.ctf_open or config.ctf_frozen:
        r["challenges"] = get_challenges(abst=not bool(user))
    return jsonify(r)
Esempio n. 6
0
def send_verification_mail(user: User):
    config = Config.get()  # type: Config
    body = """Hi, {username}

You have just registered {ctf}.
Please confirm your email address by visiting the following link.
{address}

Share your team token with your team members.
You can see your team token in the profile page of your team.

Thanks,
{ctf} Organizers""".format(
        username=user.name,
        ctf=config.name,
        address=os.path.join(request.url_root, "#/confirm/" + user.reset_token),
    )
    subject = "{} registration confirm".format(config.name)
    sendmail_async(body, subject, user.email, config.email, config.email_password)
Esempio n. 7
0
def send_passwordreset_mail(user: User):
    config = Config.get()  # type: Config
    body = """Hi, {username}

You have just requested to reset your password for {ctf}.
Visit the following link to reset your password:
{address}

If you did not request a password reset, please ignore this email or reply this email.

Thanks,
{ctf} Organizers""".format(
        username=user.name,
        ctf=config.name,
        address=os.path.join(request.url_root, "#/reset/" + user.reset_token),
    )
    subject = "{} password reset issue".format(config.name)

    sendmail_async(body, subject, user.email, config.email, config.email_password)
Esempio n. 8
0
def register():
    teamname = request.json.get("teamname", None)
    if not teamname:
        return error("Team name is required")

    if not Config.get().register_open:
        return error("Registration is closed")

    team = Team.query.filter(Team.name == teamname).first()
    if team and team.valid:
        return error("The team `{}` already exists".format(teamname))

    if not team:
        team = Team()
    team.name = teamname
    team.renewToken()
    db.session.add(team)
    db.session.commit()

    return jsonify({"id": team.id, "name": teamname, "token": team.token})
Esempio n. 9
0
 def wrap(*args, **kwargs):
     config = Config.get()
     if not config.is_open:
         return error("CTF has been closed", 403)
     return f(*args, **kwargs)
Esempio n. 10
0
def submit(user):
    challenge_id = request.json.get("id", None)
    if not challenge_id:
        return error("challenge id required")
    flag = request.json.get("flag", "").strip()
    if not challenge_id:
        return error("flag required")

    c = Challenge.query.filter(Challenge.id == challenge_id,
                               Challenge.is_open == True).first()
    if c is None:
        return error("invalid challenge id")

    if user.team:
        solves = user.team.getSolves(valid_only=False)
        team = user.team
    else:
        solves = user.getSolves(valid_only=False)
        team = Team()
        team.name = ""
    ids = [solved.id for solved in solves]
    already_solved = bool(c.id in ids)

    s = Submission()
    s.flag = flag
    s.challenge_id = c.id
    s.user_id = user.id
    if user.team:
        s.team_id = user.team.id

    if "survey" in c.tags:
        s.created_at = Config.get().start_at

    if c.flag == flag and already_solved:
        logger.log(
            ":heavy_check_mark: `{}@{}` has submitted flag `{}` to `{}`. It has already solved."
            .format(user.name, team.name, c.name, flag))
        return jsonify({
            "message":
            "Correct, and you or your team already has solved `{}`".format(
                c.name)
        })

    elif c.flag == flag and not already_solved:
        config = Config.get()
        if not config.ctf_frozen:
            s.is_valid = True
            s.is_correct = True
            db.session.add(s)
            db.session.commit()

            c.recalc_score(config.score_expr)
            db.session.add(c)
            db.session.commit()
        else:
            s.is_valid = False
            s.is_correct = True

            db.session.add(s)
            db.session.commit()

        logger.log(
            ":heavy_check_mark: `{}@{}` has submitted flag `{}` to `{}`. :100:"
            .format(user.name, team.name, c.name, flag))
        return jsonify({"message": "Correct! You solved `{}`.".format(c.name)})

    elif c.flag != flag and already_solved:
        logger.log(
            ":x: `{}@{}` has submitted flag `{}` to `{}`. The correct flag is `{}`. This team already solved this challenges."
            .format(user.name, team.name, c.name, flag, c.flag))
        return error(
            "Wrong flag, but you or your team already has solved `{}`".format(
                c.name))

    else:
        s.is_valid = False
        s.is_correct = False

        db.session.add(s)
        db.session.commit()
        logger.log(
            ":x: `{}@{}` has submitted flag `{}` to `{}`. The correct flag is `{}`"
            .format(user.name, team.name, c.name, flag, c.flag))
        return error("Wrong flag")