109 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			109 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
from flask import Blueprint
 | 
						|
 | 
						|
from CTFd.models import (
 | 
						|
    db,
 | 
						|
    Flags,
 | 
						|
)
 | 
						|
from CTFd.plugins.challenges import BaseChallenge
 | 
						|
from CTFd.plugins.dynamic_challenges import DynamicValueChallenge
 | 
						|
from CTFd.plugins.flags import get_flag_class
 | 
						|
from CTFd.utils import user as current_user
 | 
						|
from .models import WhaleContainer, DynamicDockerChallenge
 | 
						|
from .utils.control import ControlUtil
 | 
						|
 | 
						|
 | 
						|
class DynamicValueDockerChallenge(BaseChallenge):
 | 
						|
    id = "dynamic_docker"  # Unique identifier used to register challenges
 | 
						|
    name = "dynamic_docker"  # Name of a challenge type
 | 
						|
    # Blueprint used to access the static_folder directory.
 | 
						|
    blueprint = Blueprint(
 | 
						|
        "ctfd-whale-challenge",
 | 
						|
        __name__,
 | 
						|
        template_folder="templates",
 | 
						|
        static_folder="assets",
 | 
						|
    )
 | 
						|
    challenge_model = DynamicDockerChallenge
 | 
						|
 | 
						|
    @classmethod
 | 
						|
    def read(cls, challenge):
 | 
						|
        challenge = DynamicDockerChallenge.query.filter_by(id=challenge.id).first()
 | 
						|
        data = {
 | 
						|
            "id": challenge.id,
 | 
						|
            "name": challenge.name,
 | 
						|
            "value": challenge.value,
 | 
						|
            "initial": challenge.initial,
 | 
						|
            "decay": challenge.decay,
 | 
						|
            "minimum": challenge.minimum,
 | 
						|
            "description": challenge.description,
 | 
						|
            "category": challenge.category,
 | 
						|
            "state": challenge.state,
 | 
						|
            "max_attempts": challenge.max_attempts,
 | 
						|
            "type": challenge.type,
 | 
						|
            "type_data": {
 | 
						|
                "id": cls.id,
 | 
						|
                "name": cls.name,
 | 
						|
                "templates": cls.templates,
 | 
						|
                "scripts": cls.scripts,
 | 
						|
            },
 | 
						|
        }
 | 
						|
        return data
 | 
						|
 | 
						|
    @classmethod
 | 
						|
    def update(cls, challenge, request):
 | 
						|
        data = request.form or request.get_json()
 | 
						|
 | 
						|
        for attr, value in data.items():
 | 
						|
            # We need to set these to floats so that the next operations don't operate on strings
 | 
						|
            if attr in ("initial", "minimum", "decay"):
 | 
						|
                value = float(value)
 | 
						|
            if attr == 'dynamic_score':
 | 
						|
                value = int(value)
 | 
						|
            setattr(challenge, attr, value)
 | 
						|
 | 
						|
        if challenge.dynamic_score == 1:
 | 
						|
            return DynamicValueChallenge.calculate_value(challenge)
 | 
						|
 | 
						|
        db.session.commit()
 | 
						|
        return challenge
 | 
						|
 | 
						|
    @classmethod
 | 
						|
    def attempt(cls, challenge, request):
 | 
						|
        data = request.form or request.get_json()
 | 
						|
        submission = data["submission"].strip()
 | 
						|
 | 
						|
        flags = Flags.query.filter_by(challenge_id=challenge.id).all()
 | 
						|
 | 
						|
        if len(flags) > 0:
 | 
						|
            for flag in flags:
 | 
						|
                if get_flag_class(flag.type).compare(flag, submission):
 | 
						|
                    return True, "Correct"
 | 
						|
            return False, "Incorrect"
 | 
						|
        else:
 | 
						|
            user_id = current_user.get_current_user().id
 | 
						|
            q = db.session.query(WhaleContainer)
 | 
						|
            q = q.filter(WhaleContainer.user_id == user_id)
 | 
						|
            q = q.filter(WhaleContainer.challenge_id == challenge.id)
 | 
						|
            records = q.all()
 | 
						|
            if len(records) == 0:
 | 
						|
                return False, "Please solve it during the container is running"
 | 
						|
 | 
						|
            container = records[0]
 | 
						|
            if container.flag == submission:
 | 
						|
                return True, "Correct"
 | 
						|
            return False, "Incorrect"
 | 
						|
 | 
						|
    @classmethod
 | 
						|
    def solve(cls, user, team, challenge, request):
 | 
						|
        super().solve(user, team, challenge, request)
 | 
						|
 | 
						|
        if challenge.dynamic_score == 1:
 | 
						|
            DynamicValueChallenge.calculate_value(challenge)
 | 
						|
 | 
						|
    @classmethod
 | 
						|
    def delete(cls, challenge):
 | 
						|
        for container in WhaleContainer.query.filter_by(
 | 
						|
            challenge_id=challenge.id
 | 
						|
        ).all():
 | 
						|
            ControlUtil.try_remove_container(container.user_id)
 | 
						|
        super().delete(challenge)
 |