class Cheaters(db.Model): __tablename__ = "cheaters" id = db.Column(db.Integer, primary_key=True) cheater_id = db.Column(db.Integer, db.ForeignKey("users.id", ondelete="CASCADE")) cheatee_id = db.Column(db.Integer, db.ForeignKey("users.id", ondelete="CASCADE")) cheater_challenge_id = db.Column( db.Integer, db.ForeignKey("challenges.id", ondelete="CASCADE")) cheatee_challenge_id = db.Column( db.Integer, db.ForeignKey("challenges.id", ondelete="CASCADE")) challenge_data = db.Column(db.Text) date = db.Column(db.DateTime, default=datetime.datetime.utcnow) cheater = db.relationship("Users", foreign_keys="Cheaters.cheater_id", lazy="select") cheatee = db.relationship("Users", foreign_keys="Cheaters.cheatee_id", lazy="select") cheater_challenge = db.relationship( "Challenges", foreign_keys="Cheaters.cheater_challenge_id", lazy="select") cheatee_challenge = db.relationship( "Challenges", foreign_keys="Cheaters.cheatee_challenge_id", lazy="select")
class WhaleContainer(db.Model): id = db.Column(db.Integer, primary_key=True, autoincrement=True) user_id = db.Column(None, db.ForeignKey("users.id")) challenge_id = db.Column(None, db.ForeignKey("challenges.id")) start_time = db.Column(db.DateTime, nullable=False, default=datetime.utcnow) renew_count = db.Column(db.Integer, nullable=False, default=0) status = db.Column(db.Integer, default=1) uuid = db.Column(db.String(256)) port = db.Column(db.Integer, nullable=True, default=0) flag = db.Column(db.String(128), nullable=False) # Relationships user = db.relationship("Users", foreign_keys="WhaleContainer.user_id", lazy="select") challenge = db.relationship("DynamicDockerChallenge", foreign_keys="WhaleContainer.challenge_id", lazy="select") @property def http_subdomain(self): return Template( get_config('whale:template_http_subdomain', '{{ container.uuid }}')).render(container=self) def __init__(self, user_id, challenge_id, port): self.user_id = user_id self.challenge_id = challenge_id self.start_time = datetime.now() self.renew_count = 0 self.uuid = str(uuid.uuid4()) self.port = port self.flag = Template( get_config('whale:template_chall_flag', '{{ "flag{"+uuid.uuid4()|string+"}" }}')).render( container=self, uuid=uuid, random=random, get_config=get_config) @property def user_access(self): return Template( WhaleRedirectTemplate.query.filter_by( key=self.challenge.redirect_type).first().access_template ).render(container=self, get_config=get_config) @property def frp_config(self): return Template( WhaleRedirectTemplate.query.filter_by( key=self.challenge.redirect_type).first().frp_template).render( container=self, get_config=get_config) def __repr__(self): return "<WhaleContainer ID:{0} {1} {2} {3} {4}>".format( self.id, self.user_id, self.challenge_id, self.start_time, self.renew_count)
class WhaleContainer(db.Model): id = db.Column(db.Integer, primary_key=True, autoincrement=True) user_id = db.Column(None, db.ForeignKey("users.id")) challenge_id = db.Column(None, db.ForeignKey("challenges.id")) start_time = db.Column(db.DateTime, nullable=False, default=datetime.utcnow) renew_count = db.Column(db.Integer, nullable=False, default=0) status = db.Column(db.Integer, default=1) uuid = db.Column(db.String(256)) port = db.Column(db.Integer, nullable=True, default=0) flag = db.Column(db.String(128), nullable=False) # Relationships user = db.relationship("Users", foreign_keys="WhaleContainer.user_id", lazy="select") challenge = db.relationship("Challenges", foreign_keys="WhaleContainer.challenge_id", lazy="select") def __init__(self, user_id, challenge_id, flag, uuid, port): self.user_id = user_id self.challenge_id = challenge_id self.start_time = datetime.now() self.renew_count = 0 self.flag = flag self.uuid = str(uuid) self.port = port def __repr__(self): return "<WhaleContainer ID:(0) {1} {2} {3} {4}>".format( self.id, self.user_id, self.challenge_id, self.start_time, self.renew_count)
class SteamChallengeModel(Challenges): __mapper_args__ = {"polymorphic_identity": "steam"} id = db.Column(None, db.ForeignKey("challenges.id"), primary_key=True) steam_key = db.Column(db.Text, default="") steam_gamename = db.Column(db.Text, default="") # I probably don't need todo this but don't really want to write the SQL query to get the first solver first_solver = db.Column(db.Integer, db.ForeignKey("users.id")) def __init__(self, *args, **kwargs): super(SteamChallengeModel, self).__init__(**kwargs)
class UnlockState(db.Model): id = db.Column(db.Integer, primary_key=True) selected = db.Column(db.Integer, db.ForeignKey('lah_challenge.id'), nullable=True, default=None) unlocker_id = db.Column(None, db.ForeignKey('users.id'), nullable=True, default=1) expiration = db.Column(db.DateTime, nullable=True, default=datetime.datetime.fromtimestamp(13569465600)) __table_args__ = ( db.CheckConstraint('(selected IS NULL) <> (unlocker_id IS NULL)'), db.CheckConstraint('(expiration IS NULL) = (unlocker_id IS NULL)'), )
class GenFlagsMap(db.model): id = db.Column(Integer, db.ForeignKey('challenges.id')) teamid = db.Column(None, db.ForeignKey('teams.id'), primary_key=True) description = db.Column(db.Text) flag = db.Column(db.Text) def __init__(self, teamid, description, type, flag): self.teamid = teamid self.flag = flag self.type = type self.description = description
class Dependencies(db.Model): id = db.Column(db.Integer, primary_key=True) chalid = db.Column(db.Integer, db.ForeignKey('challenges.id')) dependson = db.Column(db.Integer, db.ForeignKey('challenges.id')) def __init__(self, chalid, dependson): self.chalid = chalid self.dependson = dependson def __repr__(self): return '<dependency {}, {}>'.format(self.chalid, self.dependson)
class FirstBloodAward(Awards): __mapper_args__ = {"polymorphic_identity": "firstblood"} id = db.Column(db.Integer, db.ForeignKey("awards.id", ondelete="CASCADE"), primary_key=True) solve_id = db.Column( db.Integer, db.ForeignKey("solves.id", ondelete="RESTRICT") ) # It doesn't seem possible to do this well on the database level (FirstBloodAward always gets removed without the base Awards entry), so we do it on the application level solve_num = db.Column(db.Integer, nullable=False) solve = db.relationship("Solves", foreign_keys="FirstBloodAward.solve_id", lazy="select")
class LinearUnlockingEntry(db.Model): id = db.Column(db.Integer, primary_key=True) linearunlockid = db.Column(db.Integer, db.ForeignKey('linear_unlocking_model.id')) position = db.Column(db.Integer) chalid = db.Column(db.Integer, db.ForeignKey('challenges.id')) requires_chalid = db.Column(db.Integer, db.ForeignKey('challenges.id')) def __init__(self, linearunlockid, position, chalid, requires_chalid): self.linearunlockid = linearunlockid self.position = position self.chalid = chalid self.requires_chalid = requires_chalid
class TimeDecaySolves(db.Model): __table_args__ = (db.UniqueConstraint('chalid', 'teamid'), {}) id = db.Column(db.Integer, primary_key=True) chalid = db.Column(db.Integer, db.ForeignKey('challenges.id')) teamid = db.Column(db.Integer, db.ForeignKey('teams.id')) decayed_value = db.Column(db.Integer) def __init__(self, chalid, teamid, decayed_value): self.chalid = chalid self.teamid = teamid self.decayed_value = decayed_value def __repr__(self): return '<time-decay-solve {}, {}, {}, {}, {}, {}>'.format(self.id, self.chalid, self.teamid, self.decayed_value)
class MultiSolves(db.Model): __tablename__ = "multi_solves" user_id = db.Column(db.Integer, db.ForeignKey("users.id", ondelete="CASCADE"), primary_key=True) challenge_category = db.Column(db.String(80), primary_key=True) challenge_data = db.Column(db.String(80), primary_key=True)
class multiChallenge(Challenges): __mapper_args__ = {"polymorphic_identity": "multi"} id = db.Column(None, db.ForeignKey("challenges.id"), primary_key=True) json = db.Column(db.Text) def __init__(self, *args, **kwargs): super(multiChallenge, self).__init__(**kwargs)
class FirstBloodChallenge(Challenges): __mapper_args__ = {"polymorphic_identity": "firstblood"} id = db.Column(db.Integer, db.ForeignKey("challenges.id", ondelete="CASCADE"), primary_key=True) first_blood_bonus = db.Column(db.JSON) def __init__(self, *args, **kwargs): # This is kind of a hack because serializeJSON in CTFd does not support arrays first_blood_bonus = None for attr, value in kwargs.items(): if attr.startswith('first_blood_bonus'): first_blood_bonus = [] if first_blood_bonus is not None: for i in itertools.count(): attr = 'first_blood_bonus[{0}]'.format(i) if attr not in kwargs: break first_blood_bonus.append( int(kwargs[attr]) if kwargs[attr] != '' else None) del kwargs[attr] while first_blood_bonus[-1] is None: first_blood_bonus.pop() kwargs['first_blood_bonus'] = first_blood_bonus super(FirstBloodChallenge, self).__init__(**kwargs)
class DynamicChallenge(Challenges): __mapper_args__ = {'polymorphic_identity': 'dynamic'} id = db.Column(None, db.ForeignKey('challenges.id'), primary_key=True) initial = db.Column(db.Integer) minimum = db.Column(db.Integer) decay = db.Column(db.Integer) def __init__(self, name, description, value, category, category2, type='dynamic', minimum=1, decay=50): self.name = name self.description = description self.value = value self.initial = value self.category = category self.category2 = category2 self.type = type self.minimum = minimum self.decay = decay
class KeyedChallenge(Challenges): __mapper_args__ = {'polymorphic_identity': 'keyed'} id = db.Column(None, db.ForeignKey('challenges.id'), primary_key=True) value = db.Column(db.Integer, default=0) key = db.Column(db.Text, unique=True) identifier = db.Column(db.Text, unique=True) salt = db.Column(db.Text, unique=True) def __init__(self, *args, **kwargs): super(KeyedChallenge, self).__init__(**kwargs) self.key = nacl.encoding.Base64Encoder.encode( nacl.utils.random(nacl.secret.SecretBox.KEY_SIZE)) self.salt = nacl.encoding.Base64Encoder.encode( nacl.utils.random(nacl.secret.SecretBox.KEY_SIZE)) def getflag(self): user = get_current_user() team = get_current_team() user_id = user.id, team_id = team.id if team else None, box = nacl.secret.SecretBox( nacl.encoding.Base64Encoder.decode(self.key)) salt = nacl.encoding.Base64Encoder.decode(self.salt) flag = 'U' + str(user_id) + 'T' + str(team_id) + 'F' + salt return 'flag(' + nacl.encoding.Base64Encoder.encode( box.encrypt(flag)) + ')'
class JudgeCaseFiles(db.Model): id = db.Column(db.Integer, primary_key=True) challenge_id = db.Column(db.Integer, db.ForeignKey('challenges.id')) location = db.Column(db.Text) def __init__(self, challenge_id, location): self.challenge_id = challenge_id self.location = location
class OracleChallenges(Challenges): __mapper_args__ = {"polymorphic_identity": "oracle"} id = db.Column(None, db.ForeignKey("challenges.id"), primary_key=True) oracle = db.Column(db.String(255), default="") def __init__(self, *args, **kwargs): super(OracleChallenges, self).__init__(**kwargs) self.oracle = kwargs["oracle"]
class IntegratedChallenge(Challenges): __mapper_args__ = {"polymorphic_identity": "integrated"} id = db.Column(None, db.ForeignKey("challenges.id"), primary_key=True) challengeName = db.Column(db.String(200)) def __init__(self, *args, **kwargs): super(IntegratedChallenge, self).__init__(**kwargs) self.initial = kwargs["value"]
class LahChallenge(Challenges): __mapper_args__ = {'polymorphic_identity': 'lah'} id = db.Column(None, db.ForeignKey('challenges.id'), primary_key=True) unlock_order = db.Column(db.Integer, default=99) is_unlocked = db.Column(db.Boolean, default=False) def __init__(self, *args, **kwargs): super(LahChallenge, self).__init__(**kwargs) self.is_unlocked = int(kwargs['unlock_order']) == 0
class ChallengeQuiz(db.Model): id = db.Column(db.Integer, primary_key=True) challenge = db.Column(db.Integer, db.ForeignKey("challenges.id", ondelete="CASCADE")) quiz = db.Column(db.String(100)) def __init__(self, quiz: str, challenge: Challenges): self.quiz = quiz self.challenge = challenge
class WriteUpChallenges(Challenges): id = db.Column(None, db.ForeignKey('challenges.id'), primary_key=True) solve_req = db.Column(db.Boolean, default=True, nullable=False) for_id = db.Column(db.Integer, db.ForeignKey("challenges.id")) wu_for = db.relationship("Challenges", foreign_keys=[for_id], backref=db.backref('writeup_challenge', uselist=False)) __mapper_args__ = { 'polymorphic_identity': 'writeup', 'inherit_condition': (id == Challenges.id) } def __init__(self, *args, **kwargs): super(WriteUpChallenges, self).__init__(state='hidden', *args, **kwargs)
class VMs(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(80)) chalid = db.Column(db.Integer, db.ForeignKey('challenges.id')) desc = db.Column(db.Text) def __init__(self, name, chalid, desc): self.name = name self.chalid = chalid self.desc = desc
class DynamicChallenge(Challenges): __mapper_args__ = {'polymorphic_identity': 'dynamic'} id = db.Column(None, db.ForeignKey('challenges.id'), primary_key=True) initial = db.Column(db.Integer, default=0) minimum = db.Column(db.Integer, default=0) decay = db.Column(db.Integer, default=0) def __init__(self, *args, **kwargs): super(DynamicChallenge, self).__init__(**kwargs) self.initial = kwargs['value']
class CommunityChallengeModel(Challenges): __mapper_args__ = {'polymorphic_identity': 'community'} id = db.Column(None, db.ForeignKey('challenges.id'), primary_key=True) owner = db.Column(db.Integer, db.ForeignKey('teams.id')) def __init__(self, name, description, value, category, type='community', owner=1): self.name = name self.description = description self.value = value self.initial = value self.category = category self.type = type self.owner = owner
class WriteupDynamicChallenge(Challenges): __mapper_args__ = {"polymorphic_identity": "dynamic_wp"} id = db.Column(None, db.ForeignKey("challenges.id"), primary_key=True) initial = db.Column(db.Integer, default=0) minimum = db.Column(db.Integer, default=0) decay = db.Column(db.Integer, default=0) def __init__(self, *args, **kwargs): super(WriteupDynamicChallenge, self).__init__(**kwargs) self.initial = kwargs["value"]
class Partialsolve(db.Model): __table_args__ = (db.UniqueConstraint('chalid', 'teamid'), {}) id = db.Column(db.Integer, primary_key=True) chalid = db.Column(db.Integer, db.ForeignKey('challenges.id')) teamid = db.Column(db.Integer, db.ForeignKey('teams.id')) ip = db.Column(db.String(46)) flags = db.Column(db.Text) date = db.Column(db.DateTime, default=datetime.datetime.utcnow) # team = db.relationship('Teams', foreign_keys="Solves.teamid", lazy='joined') # chal = db.relationship('Challenges', foreign_keys="Solves.chalid", lazy='joined') def __init__(self, teamid, chalid, ip, flags): self.ip = ip self.chalid = chalid self.teamid = teamid self.flags = flags def __repr__(self): return '<solve {}, {}, {}, {}>'.format(self.teamid, self.chalid, self.ip, self.flags)
class MultiQuestionChallengeModel(Challenges): __mapper_args__ = {'polymorphic_identity': 'multiquestionchallenge'} id = db.Column(None, db.ForeignKey('challenges.id'), primary_key=True) def __init__(self, name, description, value, category, type='multiquestionchallenge'): self.name = name self.description = description self.value = value self.category = category self.type = type
class IntersectionTeamAttr(db.Model): __tablename__ = "intersecTeamAttr" id = db.Column(db.Integer, primary_key=True) team_id = db.Column(db.Integer, db.ForeignKey("teams.id", ondelete="CASCADE")) attr_id = db.Column(db.Integer, db.ForeignKey("attributes.id", ondelete="CASCADE")) value = db.Column(db.Text) team = db.relationship("Teams", foreign_keys="IntersectionTeamAttr.team_id", lazy="select") def __init__(self, **kwargs): super(IntersectionTeamAttr, self).__init__(**kwargs) def __repr__(self): return "<IntTeamAttr team{0} attr{1}>".format(self.team_id, self.attr_id)
class UserSalt(db.Model): __tablename__ = 'usersalt' id = db.Column(db.Integer, primary_key=True) user_id = db.Column(db.Integer, db.ForeignKey('users.id', ondelete='CASCADE')) challenge_id = db.Column( db.Integer, db.ForeignKey('challenges.id', ondelete='CASCADE')) salt = db.Column(db.Text, unique=True) user = db.relationship("Users", foreign_keys='UserSalt.user_id', lazy='select') #, back_populates="salt") challenge = db.relationship("Challenges", foreign_keys='UserSalt.challenge_id', lazy='select') #, back_populates="user_salts") def __init__(self, *args, **kwargs): super(UserSalt, self).__init__(**kwargs)
class VMChallengesModel(Challenges): __mapper_args__ = {"polymorphic_identity": "virtual_machine_challenges"} id = db.Column( db.Integer, db.ForeignKey("challenges.id", ondelete="CASCADE"), primary_key=True ) ip = db.Column(db.String(80)) proto = db.Column(db.String(80)) port = db.Column(db.String(80)) scenario_id = db.Column(db.String(80)) time_limit = db.Column(db.Integer, default=1440)