示例#1
0
    def validate_captain_id(self, data):
        captain_id = data.get("captain_id")
        if captain_id is None:
            return

        if is_admin():
            team_id = data.get("id")
            if team_id:
                target_team = Teams.query.filter_by(id=team_id).first()
            else:
                target_team = get_current_team()
            captain = Users.query.filter_by(id=captain_id).first()
            if captain in target_team.members:
                return
            else:
                raise ValidationError("Invalid Captain ID", field_names=["captain_id"])
        else:
            current_team = get_current_team()
            current_user = get_current_user()
            if current_team.captain_id == current_user.id:
                return
            else:
                raise ValidationError(
                    "Only the captain can change team captain",
                    field_names=["captain_id"],
                )
    def compare(chal_key_obj, provided):
        saved = chal_key_obj.content
        data = chal_key_obj.data

        from fyp import generateFlag, checkShareFlag
        from CTFd.utils.user import get_current_team
        saved = generateFlag(saved, get_current_team())
        if len(saved) != len(provided):
            return False, False
        result = 0
        share = False
        if data == "case_insensitive":
            saved = saved.lower()
            provided = provided.lower()

        for x, y in zip(saved, provided):
            result |= ord(x) ^ ord(y)

        if result != 0:
            share = checkShareFlag(saved, provided)

        if share:
            from CTFd.utils.events import socketio
            socketio.emit(
                'notification', {
                    "title": "Share Flag Detected",
                    "content": "Suspect team name: " + get_current_team().name
                },
                broadcast=True)
        return result == 0, share
    def get(self, team_id):
        if team_id == 'me':
            if not authed():
                abort(403)
            team = get_current_team()
        else:
            if accounts_visible() is False or scores_visible() is False:
                abort(404)
            team = Teams.query.filter_by(id=team_id).first_or_404()

            if (team.banned or team.hidden) and is_admin() is False:
                abort(404)

        fails = team.get_fails(admin=is_admin())

        view = 'admin' if is_admin() else 'user'

        schema = SubmissionSchema(view=view, many=True)
        response = schema.dump(fails)

        if response.errors:
            return {'success': False, 'errors': response.errors}, 400

        if is_admin():
            data = response.data
        else:
            data = []
        count = len(response.data)

        return {'success': True, 'data': data, 'meta': {'count': count}}
示例#4
0
文件: teams.py 项目: cydave/CTFd
    def patch(self):
        team = get_current_team()
        if team.captain_id != session["id"]:
            return (
                {
                    "success": False,
                    "errors": {
                        "": ["Only team captains can edit team information"]
                    },
                },
                403,
            )

        data = request.get_json()

        response = TeamSchema(view="self", instance=team,
                              partial=True).load(data)

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

        db.session.commit()

        response = TeamSchema("self").dump(response.data)
        db.session.close()

        return {"success": True, "data": response.data}
    def validate_name(self, data):
        name = data.get('name')
        if name is None:
            return

        existing_team = Teams.query.filter_by(name=name).first()
        # Admins should be able to patch anyone but they cannot cause a collision.
        if is_admin():
            team_id = int(data.get('id', 0))
            if team_id:
                if existing_team and existing_team.id != team_id:
                    raise ValidationError('Team name has already been taken',
                                          field_names=['name'])
            else:
                # If there's no Team ID it means that the admin is creating a team with no ID.
                if existing_team:
                    raise ValidationError('Team name has already been taken',
                                          field_names=['name'])
        else:
            current_team = get_current_team()
            # We need to allow teams to edit themselves and allow the "conflict"
            if data['name'] == current_team.name:
                return data
            else:
                name_changes = get_config('name_changes', default=True)
                if bool(name_changes) is False:
                    raise ValidationError('Name changes are disabled',
                                          field_names=['name'])

                if existing_team:
                    raise ValidationError('Team name has already been taken',
                                          field_names=['name'])
示例#6
0
    def request_new_challenge(challenge_id):
        if is_admin():
            challenge = OracleChallenges.query.filter(
                Challenges.id == challenge_id).first_or_404()
        else:
            challenge = OracleChallenges.query.filter(
                OracleChallenges.id == challenge_id,
                and_(Challenges.state != "hidden",
                     Challenges.state != "locked"),
            ).first_or_404()

        data = request.form or request.get_json()

        team_id = get_current_team().id
        force_new = data["force_new"]

        try:
            r = requests.post(
                str(challenge.oracle) + "/create",
                json={
                    "team_id": team_id,
                    "force_new": force_new
                },
            )
        except requests.exceptions.ConnectionError:
            return "ERROR: Challenge oracle is not available. Talk to an admin."

        if r.status_code != 200:
            return "ERROR: Challenge oracle is not available. Talk to an admin."

        return r.text
示例#7
0
    def attempt(challenge, request):
        """
        This method is used to check whether a given input is right or wrong. It does not make any changes and should
        return a boolean for correctness and a string to be shown to the user. It is also in charge of parsing the
        user's input from the request itself.

        :param challenge: The Challenge object from the database
        :param request: The request the user submitted
        :return: (boolean, string)
        """
        data = request.form or request.get_json()
        # submission = data["submission"].strip()
        # instance_id = submission
        team_id = get_current_team().id

        try:
            r = requests.post(str(challenge.oracle) + "/attempt",
                              json={"team_id": team_id})
        except requests.exceptions.ConnectionError:
            return False, "Challenge oracle is not available. Talk to an admin."

        if r.status_code == 200:
            return True, "Correct"

        return False, "Incorrect"
示例#8
0
文件: __init__.py 项目: DevLuce/CTFd
    def _require_complete_profile(*args, **kwargs):
        if authed():
            if is_admin():
                return f(*args, **kwargs)
            else:
                user = get_current_user()

                if user.filled_all_required_fields is False:
                    info_for(
                        "views.settings",
                        "Please fill out all required profile fields before continuing",
                    )
                    return redirect(url_for("views.settings"))

                if is_teams_mode():
                    team = get_current_team()

                    if team and team.filled_all_required_fields is False:
                        # This is an abort because it's difficult for us to flash information on the teams page
                        return abort(
                            403,
                            description=
                            "Please fill in all required team profile fields",
                        )

                return f(*args, **kwargs)
        else:
            # Fallback to whatever behavior the route defaults to
            return f(*args, **kwargs)
示例#9
0
 def get_field_kwargs():
     team = get_current_team()
     field_kwargs = {"editable": True}
     if team.filled_all_required_fields is False:
         # Show all fields
         field_kwargs = {}
     return field_kwargs
示例#10
0
    def get(self):
        # This can return None (unauth) if visibility is set to public
        user = get_current_user()

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

        if user:
            solve_ids = (Solves.query.with_entities(
                Solves.challenge_id).filter_by(
                    account_id=user.account_id).order_by(
                        Solves.challenge_id.asc()).all())

            if is_admin():
                pass
            else:
                if config.is_teams_mode() and get_current_team() is None:
                    abort(403)
        else:
            solve_ids = []

        response = []
        tag_schema = TagSchema(view="user", many=True)
        for challenge in challenges:
            if challenge.requirements:
                requirements = challenge.requirements.get("prerequisites", [])
                anonymize = challenge.requirements.get("anonymize")
                if compare(requirements, solve_ids):
                    pass
                else:
                    if anonymize:
                        response.append({
                            "id": challenge.id,
                            "type": "hidden",
                            "name": "???",
                            "value": 0,
                            "category": "???",
                            "tags": [],
                            "template": "",
                            "script": "",
                        })
                    # Fallthrough to continue
                    continue

            challenge_type = get_chal_class(challenge.type)
            response.append({
                "id": challenge.id,
                "type": challenge_type.name,
                "name": challenge.name,
                "value": challenge.value,
                "category": challenge.category,
                "tags": tag_schema.dump(challenge.tags).data,
                "template": challenge_type.templates["view"],
                "script": challenge_type.scripts["view"],
            })

        db.session.close()
        return {"success": True, "data": response}
示例#11
0
文件: teams.py 项目: pt35t/CTFd
    def validate_captain_id(self, data):
        captain_id = data.get('captain_id')
        # if captain_id is None:
        #     return

        if is_admin():
            return
            # team_id = data.get('id')
            # if team_id:
            #     target_team = Teams.query.filter_by(id=team_id).first()
            # else:
            #     target_team = get_current_team()
            # captain = Users.query.filter_by(id=captain_id).first()
            # if captain in target_team.members:
            #     return
            # else:
            #     raise ValidationError('Invalid Captain ID', field_names=['captain_id'])
        else:
            if captain_id is None:
                return
            current_team = get_current_team()
            current_user = get_current_user()
            if current_team.captain_id == current_user.id:
                return
            else:
                raise ValidationError(
                    'Only the captain can change team captain',
                    field_names=['captain_id'])
示例#12
0
文件: teams.py 项目: palkers/CTFd
    def get(self, team_id):
        if team_id == "me":
            if not authed():
                abort(403)
            team = get_current_team()
            fails = team.get_fails(admin=True)
        else:
            if accounts_visible() is False or scores_visible() is False:
                abort(404)
            team = Teams.query.filter_by(id=team_id).first_or_404()

            if (team.banned or team.hidden) and is_admin() is False:
                abort(404)
            fails = team.get_fails(admin=is_admin())

        view = "admin" if is_admin() else "user"

        schema = SubmissionSchema(view=view, many=True)
        response = schema.dump(fails)

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

        if is_admin():
            data = response.data
        else:
            data = []
        count = len(response.data)

        return {"success": True, "data": data, "meta": {"count": count}}
示例#13
0
def get_current_account_name():
    team = get_current_team()
    if team is not None:
        return team.name

    user = get_current_user()
    return user.name
	def get(self):
		docker = DockerConfig.query.filter_by(id=1).first()
		if is_teams_mode():
			session = get_current_team()
			tracker = DockerChallengeTracker.query.filter_by(team_id=session.id)
		else:
			session = get_current_user()
			tracker = DockerChallengeTracker.query.filter_by(user_id=session.id)
		data = list()
		for i in tracker:
			data.append({
				'id' : i.id, 
				'team_id' : i.team_id, 
				'user_id' : i.user_id, 
				'docker_image' : i.docker_image, 
				'timestamp' : i.timestamp,
				'revert_time' : i.revert_time,
				'instance_id' : i.instance_id,
				'ports' : i.ports.split(','),
				'host' : str(docker.hostname).split(':')[0]
				})
		return {
					'success' : True,
					'data' : data
			}
def manual_get_submissions(id):
    # {
    #   "data": {
    #       "correct": [],
    #       "pending": [
    #           {
    #               "date": "2020-05-12T04:05:39.437160Z",
    #               "provided": "WASD"
    #           }
    #       ]
    #   },
    #   "success": true
    # }
    team = get_current_team()
    user = get_current_user()

    pending = Pending.query.filter_by(
        team_id=team.id if team else None,
        user_id=user.id,
        challenge_id=id,
    ).with_entities(Pending.date, Pending.provided).all()

    correct = Solves.query.filter_by(
        team_id=team.id if team else None,
        user_id=user.id,
        challenge_id=id,
    ).with_entities(Solves.date, Solves.provided).all()

    return jsonify({
        "success": True,
        "data": {
            "correct": correct,
            "pending": pending
        }
    })
示例#16
0
    def tracker():
        # TODO: This function shouldn't cause a DB hit for lookups if possible
        if authed():
            track = Tracking.query.filter_by(ip=get_ip(),
                                             user_id=session['id']).first()
            if not track:
                visit = Tracking(ip=get_ip(), user_id=session['id'])
                db.session.add(visit)
            else:
                track.date = datetime.datetime.utcnow()

            try:
                db.session.commit()
            except (InvalidRequestError, IntegrityError) as e:
                print(e.message)
                db.session.rollback()
                session.clear()

            if authed():
                user = get_current_user()
                team = get_current_team()

                if request.path.startswith('/themes') is False:
                    if user and user.banned:
                        return render_template(
                            'errors/403.html',
                            error='You have been banned from this CTF'), 403

                    if team and team.banned:
                        return render_template(
                            'errors/403.html',
                            error='Your team has been banned from this CTF'
                        ), 403

            db.session.close()
示例#17
0
    def validate_email(self, data):
        email = data.get("email")
        if email is None:
            return

        existing_team = Teams.query.filter_by(email=email).first()
        if is_admin():
            team_id = data.get("id")
            if team_id:
                if existing_team and existing_team.id != team_id:
                    raise ValidationError(
                        "Email address has already been used", field_names=["email"]
                    )
            else:
                if existing_team:
                    raise ValidationError(
                        "Email address has already been used", field_names=["email"]
                    )
        else:
            current_team = get_current_team()
            if email == current_team.email:
                return data
            else:
                if existing_team:
                    raise ValidationError(
                        "Email address has already been used", field_names=["email"]
                    )
示例#18
0
    def validate_password_confirmation(self, data):
        password = data.get("password")
        confirm = data.get("confirm")

        if is_admin():
            pass
        else:
            current_team = get_current_team()
            current_user = get_current_user()

            if current_team.captain_id != current_user.id:
                raise ValidationError(
                    "Only the captain can change the team password",
                    field_names=["captain_id"],
                )

            if password and (bool(confirm) is False):
                raise ValidationError(
                    "Please confirm your current password", field_names=["confirm"]
                )

            if password and confirm:
                test = verify_password(
                    plaintext=confirm, ciphertext=current_team.password
                )
                if test is True:
                    return data
                else:
                    raise ValidationError(
                        "Your previous password is incorrect", field_names=["confirm"]
                    )
            else:
                data.pop("password", None)
                data.pop("confirm", None)
示例#19
0
 def require_team_wrapper(*args, **kwargs):
     if get_config("user_mode") == TEAMS_MODE:
         team = get_current_team()
         if team is None:
             return redirect(
                 url_for("teams.private", next=request.full_path))
     return f(*args, **kwargs)
示例#20
0
    def get(self, attr_id, team_id):
        attr = Attributes.query.filter_by(id=attr_id).first_or_404()
        if (attr.hidden) and is_admin() is False:
            abort(404)

        intersec = IntersectionTeamAttr.query.filter_by(
            attr_id=attr_id).filter_by(team_id=team_id).first_or_404()
        if (attr.private) and is_admin() is False:
            t = get_current_team()
            if not (authed() and t and t.id == intersec.team_id):
                abort(404)

        view = IntersectionTeamAttrSchema.views.get(session.get(
            "type", "user"))
        response = IntersectionTeamAttrSchema(view=view).dump(intersec)

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

        if supported_input_types[attr.type] == "checkbox":
            if intersec.value and intersec.value != "false":
                response.data["value"] = True
            else:
                response.data["value"] = False
        return {"success": True, "data": response.data}
示例#21
0
    def get(self, team_id):
        if team_id == 'me':
            if not authed():
                abort(403)
            team = get_current_team()
        else:
            if accounts_visible() is False or scores_visible() is False:
                abort(404)
            team = Teams.query.filter_by(id=team_id).first_or_404()

        awards = team.get_awards(
            admin=is_admin()
        )

        schema = AwardSchema(many=True)
        response = schema.dump(awards)

        if response.errors:
            return {
                'success': False,
                'errors': response.errors
            }, 400

        return {
            'success': True,
            'data': response.data
        }
示例#22
0
    def get(self, team_id):
        if team_id == 'me':
            if not authed():
                abort(403)
            team = get_current_team()
        else:
            if accounts_visible() is False or scores_visible() is False:
                abort(404)
            team = Teams.query.filter_by(id=team_id).first_or_404()

        solves = team.get_solves(
            admin=is_admin()
        )

        view = 'admin' if is_admin() else 'user'
        schema = SubmissionSchema(view=view, many=True)
        response = schema.dump(solves)

        if response.errors:
            return {
                'success': False,
                'errors': response.errors
            }, 400

        return {
            'success': True,
            'data': response.data
        }
示例#23
0
    def delete(self):
        team_disbanding = get_config("team_disbanding", default="inactive_only")
        if team_disbanding == "disabled":
            return (
                {
                    "success": False,
                    "errors": {"": ["Team disbanding is currently disabled"]},
                },
                403,
            )

        team = get_current_team()
        if team.captain_id != session["id"]:
            return (
                {
                    "success": False,
                    "errors": {"": ["Only team captains can disband their team"]},
                },
                403,
            )

        # The team must not have performed any actions in the CTF
        performed_actions = any(
            [
                team.solves != [],
                team.fails != [],
                team.awards != [],
                Submissions.query.filter_by(team_id=team.id).all() != [],
                Unlocks.query.filter_by(team_id=team.id).all() != [],
            ]
        )

        if performed_actions:
            return (
                {
                    "success": False,
                    "errors": {
                        "": [
                            "You cannot disband your team as it has participated in the event. "
                            "Please contact an admin to disband your team or remove a member."
                        ]
                    },
                },
                403,
            )

        for member in team.members:
            member.team_id = None
            clear_user_session(user_id=member.id)

        db.session.delete(team)
        db.session.commit()

        clear_team_session(team_id=team.id)
        clear_standings()

        db.session.close()

        return {"success": True}
示例#24
0
    def get_challenges_by_categories():
        user = get_current_user()

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

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

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

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

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

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

        if response.errors:
            return {'success': False, 'errors': response.errors}, 400

        return {'success': True, 'data': response.data}
示例#26
0
    def get(self):
        team = get_current_team()
        response = TeamSchema(view="self").dump(team)

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

        return {"success": True, "data": response.data}
示例#27
0
    def validate_email(self, data):
        email = data.get('email')
        if email is None:
            return

        obj = Teams.query.filter_by(email=email).first()
        if obj:
            if is_admin():
                if data.get('id'):
                    target_user = Teams.query.filter_by(id=data['id']).first()
                else:
                    target_user = get_current_team()

                if target_user and obj.id != target_user.id:
                    raise ValidationError('Email address has already been used', field_names=['email'])
            else:
                if obj.id != get_current_team().id:
                    raise ValidationError('Email address has already been used', field_names=['email'])
示例#28
0
 def require_team_wrapper(*args, **kwargs):
     if get_config("user_mode") == TEAMS_MODE:
         team = get_current_team()
         if team is None:
             if request.content_type == "application/json":
                 abort(403)
             else:
                 return redirect(url_for("teams.private", next=request.full_path))
     return f(*args, **kwargs)
示例#29
0
文件: teams.py 项目: cydave/CTFd
    def get(self):
        team = get_current_team()
        awards = team.get_awards(admin=True)

        schema = AwardSchema(many=True)
        response = schema.dump(awards)

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

        return {"success": True, "data": response.data}
	def get(self):
		container = request.args.get('name')
		if not container:
			return abort(403)
		docker = DockerConfig.query.filter_by(id=1).first()
		containers = DockerChallengeTracker.query.all()
		if container not in get_repositories(docker, tags=True):
			return abort(403)
		if is_teams_mode():
			session = get_current_team()
			# First we'll delete all old docker containers (+2 hours)
			for i in containers:
				if int(session.id) == int(i.team_id) and (unix_time(datetime.utcnow()) - int(i.timestamp)) >= 7200:
					delete_container(docker, i.instance_id)
					DockerChallengeTracker.query.filter_by(instance_id=i.instance_id).delete()
					db.session.commit()
			check = DockerChallengeTracker.query.filter_by(team_id=session.id).filter_by(docker_image=container).first()
		else:
			session = get_current_user()
			for i in containers:
				if int(session.id) == int(i.user_id) and (unix_time(datetime.utcnow()) - int(i.timestamp)) >= 7200:
					delete_container(docker, i.instance_id)
					DockerChallengeTracker.query.filter_by(instance_id=i.instance_id).delete()
					db.session.commit()
			check = DockerChallengeTracker.query.filter_by(user_id=session.id).filter_by(docker_image=container).first()
		# If this container is already created, we don't need another one.
		if check != None and not (unix_time(datetime.utcnow()) - int(check.timestamp)) >= 300:
			return abort(403)
		# The exception would be if we are reverting a box. So we'll delete it if it exists and has been around for more than 5 minutes.
		elif check != None:
			delete_container(docker, check.instance_id)
			if is_teams_mode():
				DockerChallengeTracker.query.filter_by(team_id=session.id).filter_by(docker_image=container).delete()
			else:
				DockerChallengeTracker.query.filter_by(user_id=session.id).filter_by(docker_image=container).delete()
			db.session.commit()
		portsbl = get_unavailable_ports(docker)
		create = create_container(docker,container,session.name,portsbl)
		print(create)
		ports = json.loads(create[1])['HostConfig']['PortBindings'].values()
		entry = DockerChallengeTracker(
			team_id = session.id if is_teams_mode() else None,
			user_id = session.id if not is_teams_mode() else None,
			docker_image = container,
			timestamp = unix_time(datetime.utcnow()),
			revert_time = unix_time(datetime.utcnow()) + 300,
			instance_id = create[0]['Id'],
			ports = ','.join([p[0]['HostPort'] for p in ports]),
			host = str(docker.hostname).split(':')[0]
		)
		db.session.add(entry)
		db.session.commit()
		db.session.close()
		return