def load(app): print("Loading.........................") dir_path = os.path.dirname(os.path.realpath(__file__)) template_path = os.path.join(dir_path, 'confirm_override.html') override_template('confirm.html', open(template_path).read()) template_path = os.path.join(dir_path, 'register_override.html') override_template('register.html', open(template_path).read())
def load(app): dir_path = os.path.dirname(os.path.realpath(__file__)) template_path = os.path.join(dir_path, 'assets', 'register.html') override_template('register.html', open(template_path).read()) app.view_functions['auth.register'] = register register_plugin_assets_directory(app, base_path='/plugins/<DIR HERE>/assets/js')
def load(app): #register_plugin_assets_directory(app, base_path='/plugins/scenario_user_reports/assets/') dir_path = os.path.dirname(os.path.realpath(__file__)) template_path = os.path.join(dir_path, 'custom_user.html') override_template('admin/users/user.html', open(template_path).read()) app.view_functions['admin.users_detail'] = custom_users_detail
def test_override_template(): """Does override_template work properly for regular themes""" app = create_ctfd() with app.app_context(): override_template("login.html", "LOGIN OVERRIDE") with app.test_client() as client: r = client.get("/login") assert r.status_code == 200 output = r.get_data(as_text=True) assert "LOGIN OVERRIDE" in output destroy_ctfd(app)
def test_admin_override_template(): """Does override_template work properly for the admin panel""" app = create_ctfd() with app.app_context(): override_template("admin/users/user.html", "ADMIN TEAM OVERRIDE") client = login_as_user(app, name="admin", password="******") r = client.get("/admin/users/1") assert r.status_code == 200 output = r.get_data(as_text=True) assert "ADMIN TEAM OVERRIDE" in output destroy_ctfd(app)
def load(app): dir_path = os.path.dirname(os.path.realpath(__file__)) db.create_all() register_plugin_assets_directory( app, base_path="/plugins/CTFd-pwn-college-plugin/assets/") CHALLENGE_CLASSES["docker"] = DockerChallenge FLAG_CLASSES["user"] = UserFlag ssh_key_template_path = os.path.join(dir_path, "assets", "ssh_key", "settings.html") override_template("settings.html", open(ssh_key_template_path).read()) app.view_functions["views.settings"] = ssh_key_settings Forms.keys = {"SSHKeyForm": SSHKeyForm} scoreboard_template_path = os.path.join(dir_path, "assets", "scoreboard", "scoreboard.html") override_template("scoreboard.html", open(scoreboard_template_path).read()) app.view_functions["scoreboard.listing"] = scoreboard_listing blueprint = Blueprint("pwncollege_api", __name__) api = Api(blueprint, version="v1", doc=current_app.config.get("SWAGGER_UI")) api.add_namespace(docker_namespace, "/docker") api.add_namespace(user_flag_namespace, "/user_flag") api.add_namespace(ssh_key_namespace, "/ssh_key") api.add_namespace(download_namespace, "/download") api.add_namespace(terminal_namespace, "/terminal") api.add_namespace(binary_ninja_namespace, "/binary_ninja") api.add_namespace(belts_namespace, "/belts") app.register_blueprint(blueprint, url_prefix="/pwncollege_api/v1") app.register_blueprint(download) app.register_blueprint(terminal) register_user_page_menu_bar("Terminal", "/terminal") app.register_blueprint(grades) register_user_page_menu_bar("Grades", "/grades") register_admin_plugin_menu_bar("Grades", "/grades/all")
def view_single_rank(): # override templates dir_path = os.path.dirname(os.path.realpath(__file__)) template_path = os.path.join(dir_path, 'assets') template_path = os.path.join(template_path, 'scoreboard.html') override_template("scoreboard.html", open(template_path).read()) # get categories categories = get_all_categories() # load scores standings = get_standings() ranks = [] for index1, category in enumerate(categories): ranks.append([]) for standing in standings: account_id = standing.account_id name = standing.name oauth_id = standing.oauth_id score = get_user_scores_for_each_category( standing.account_id, categories)[index1] ranks[index1].append([account_id, name, oauth_id, score]) ranks[index1] = sorted(ranks[index1], key=(lambda x: x[3]), reverse=True) # rank[0] account_id # rank[1] name # rank[2] oauth_id # rank[3] score return render_template("scoreboard.html", categories=categories, enumerate=enumerate, ranks=ranks, standings=standings, score_frozen=config.is_scoreboard_frozen())
def load(app): # get plugin location dir_path = os.path.dirname(os.path.realpath(__file__)) dir_name = os.path.basename(dir_path) register_plugin_assets_directory(app, base_path="/plugins/" + dir_name + "/assets/", endpoint="split_scoreboard_assets") # Admin Pages override_template( 'split_scoreboard_attr.html', open(os.path.join(dir_path, 'assets/admin/split_scoreboard_attr.html')).read()) # Admin Modals override_template( 'admin_ss_form.html', open(os.path.join(dir_path, 'assets/admin/modals/admin_ss_form.html')).read()) # Team settings page override override_template( 'scoreboard.html', open(os.path.join(dir_path, 'assets/teams/scoreboard.html')).read()) # Team Modals app.view_functions['scoreboard.listing'] = view_split_scoreboard # Blueprint used to access the static_folder directory. blueprint = Blueprint("split_scores", __name__, template_folder="templates", static_folder="assets") api = Blueprint("split_scoreboard_api", __name__, url_prefix="/api/v1") Split_Scores_API_v1 = Api(api, version="v1", doc=app.config.get("SWAGGER_UI")) Split_Scores_API_v1.add_namespace(split_scores_namespace, "/split_scores") app.register_blueprint(api)
def load(app): dir_path = os.path.dirname(os.path.realpath(__file__)) template_path = os.path.join(dir_path, 'reddit-signin.html') override_template('login.html', open(template_path).read()) template_path = os.path.join(dir_path, 'reddit-register.html') override_template('register.html', open(template_path).read()) template_path = os.path.join(dir_path, 'reddit-scoreboard.html') override_template('scoreboard.html', open(template_path).read()) template_path = os.path.join(dir_path, 'reddit-scoreboard.html') override_template('scoreboard.html', open(template_path).read()) template_path = os.path.join(dir_path, 'reddit-users.html') override_template('users.html', open(template_path).read()) template_path = os.path.join(dir_path, 'reddit-public.html') override_template('public.html', open(template_path).read()) @app.route("/reddit") def reddit_login(): endpoint = (get_app_config("REDDIT_AUTHORIZATION_ENDPOINT") or get_config("reddit_authorization_endpoint") or "https://ssl.reddit.com/api/v1/authorize") client_id = get_app_config("REDDIT_CLIENT_ID") or get_config( "reddit_client_id") callback_url = get_app_config("REDDIT_CALLBACK_URL") or get_config( "reddit_callback_url") if client_id is None: error_for( endpoint="reddit.login", message="Reddit OAuth Settings not configured. " "Ask your CTF administrator to configure Reddit integration.", ) return redirect(url_for("auth.login")) redirect_url = "{endpoint}?client_id={client_id}&response_type=code&state={state}&redirect_uri={callback_url}&duration=temporary&scope=identity".format( endpoint=endpoint, client_id=client_id, state=session["nonce"], callback_url=callback_url) return redirect(redirect_url) @app.route("/reddit/callback", methods=["GET"]) @ratelimit(method="GET", limit=10, interval=60) def oauth_redirect(): oauth_code = request.args.get("code") state = request.args.get("state") if session["nonce"] != state: log("logins", "[{date}] {ip} - OAuth State validation mismatch") error_for(endpoint="auth.login", message="OAuth State validation mismatch.") return redirect(url_for("auth.login")) if oauth_code: url = (get_app_config("REDDIT_TOKEN_ENDPOINT") or get_config("reddit_token_endpoint") or "https://ssl.reddit.com/api/v1/access_token") client_id = get_app_config("REDDIT_CLIENT_ID") or get_config( "reddit_client_id") client_secret = get_app_config( "REDDIT_CLIENT_SECRET") or get_config("reddit_client_secret") reddit_user_agent = get_app_config( "REDDIT_USER_AGENT") or get_config("reddit_user_agent") callback_url = get_app_config("REDDIT_CALLBACK_URL") or get_config( "reddit_callback_url") client_auth = requests.auth.HTTPBasicAuth(client_id, client_secret) headers = { "content-type": "application/x-www-form-urlencoded", "User-Agent": reddit_user_agent } token_request = requests.post(url, auth=client_auth, data={ "grant_type": "authorization_code", "code": oauth_code, "redirect_uri": callback_url }, headers=headers) if token_request.status_code == requests.codes.ok: token = token_request.json()["access_token"] user_url = (get_app_config("REDDIT_API_ENDPOINT") or get_config("reddit_api_endpoint") or "https://oauth.reddit.com/api/v1/me") headers = { "Authorization": "Bearer " + str(token), "User-Agent": reddit_user_agent } api_response = requests.get(url=user_url, headers=headers) log("logins", str(api_response)) api_data = api_response.json() user_id = api_data["id"] user_name = api_data["name"] user_email = api_data["name"] + "@reddit.com" user = Users.query.filter_by(name=user_name).first() if user is None: # Check if we are allowing registration before creating users if registration_visible(): user = Users( name=user_name, email=user_email, oauth_id=user_id, verified=True, ) db.session.add(user) db.session.commit() else: log( "logins", "[{date}] {ip} - Public registration via Reddit blocked" ) error_for( endpoint="auth.login", message= "Public registration is disabled. Please try again later.", ) return redirect(url_for("auth.login")) if get_config("user_mode") == TEAMS_MODE: team_id = api_data["team"]["id"] team_name = api_data["team"]["name"] team = Teams.query.filter_by(oauth_id=team_id).first() if team is None: team = Teams(name=team_name, oauth_id=team_id, captain_id=user.id) db.session.add(team) db.session.commit() team_size_limit = get_config("team_size", default=0) if team_size_limit and len( team.members) >= team_size_limit: plural = "" if team_size_limit == 1 else "s" size_error = "Teams are limited to {limit} member{plural}.".format( limit=team_size_limit, plural=plural) error_for(endpoint="auth.login", message=size_error) return redirect(url_for("auth.login")) team.members.append(user) db.session.commit() if user.oauth_id is None: user.oauth_id = user_id user.verified = True db.session.commit() login_user(user) return redirect(url_for("challenges.listing")) else: log("logins", "[{date}] {ip} - OAuth token retrieval failure") log("logins", str(token_request)) log("logins", str(token_request.status_code)) log("logins", token_request.json()["access_token"]) error_for(endpoint="auth.login", message="OAuth token retrieval failure.") return redirect(url_for("auth.login")) else: log("logins", "[{date}] {ip} - Received redirect without OAuth code") error_for(endpoint="auth.login", message="Received redirect without OAuth code.") return redirect(url_for("auth.login"))
def load(app): app.db.create_all() ldap = Blueprint('ldap', __name__, ) # Change these settings to correspond to your ldap server settings = { "name": "ldap server", "host": "example.com", "port": 389, "encryption": "none", "base_dn": "dc=example,dc=com", "type_dn": "ou=people", "request": "(uid={})", "prefix": "" } # Replaces template files dir_path = os.path.dirname(os.path.realpath(__file__)) template_path = os.path.join(dir_path, 'modified_templates/login.html') override_template('login.html', open(template_path).read()) template_path = os.path.join(dir_path, 'modified_templates/settings.html') override_template('settings.html', open(template_path).read()) template_path = os.path.join(dir_path, 'modified_templates/base.html') override_template('base.html', open(template_path).read()) def login(): errors = get_errors() if request.method == "POST": login_info = { 'username': request.form["name"], 'password': request.form["password"] } # Check if the user submitted an email address or username if validators.validate_email(login_info['username']) is True: user = Users.query.filter_by(email=login_info['username']).first() # If this is the first time logging inn you need to use your username errors.append("Use your username instead of email for first login") else: user = Users.query.filter_by(name=login_info['username']).first() # Ldap credentials prep login = login_info["username"].strip().lower() login_dn = 'uid=' + login + ',' + settings['type_dn'] + ',' + settings['base_dn'] password = login_info["password"] if password.rstrip() == "": errors.append("Empty passwordfield") db.session.close() return render_template("login.html", errors=errors) try: # Connect to the ldap print("connection to ldap") server = ldap3.Server(settings['host'], port=settings['port'], use_ssl=settings["encryption"] == 'ssl', get_info=ldap3.ALL) conn = ldap3.Connection(server, user=login_dn, password=password, auto_bind='NONE', version=3, authentication='SIMPLE', client_strategy='SYNC', auto_referrals=True, check_names=True, read_only=False, lazy=False, raise_exceptions=False) # Start tls for confidentiality conn.start_tls() # Check authenticity of credentials if not conn.bind(): # I'll leave this print for troubleshooting with login. Tip: if login isn't working check 'type_dn' in settings. I assume all people are registered as 'ou=people' in the system # print("ERROR ", conn.result) errors.append("Your username or password is incorrect") log("logins", "[{date}] {ip} - submitted invalid password for {name}") db.session.close() return render_template("login.html", errors=errors) print("Connected") except Exception as e: errors.append("Can't initialze connection to " + settings['host'] + ': ' + str(e)) db.session.close() return render_template("login.html", errors=errors) # If we have gotten to this point it means that the user credentials matched an entry in ldap # Check if user has logged inn before if user: session.regenerate() login_user(user) log("logins", "[{date}] {ip} - {name} logged in") db.session.close() if request.args.get("next") and validators.is_safe_url(request.args.get("next")): return redirect(request.args.get("next")) return redirect(url_for("challenges.listing")) else: # Register the user in our system # First we get email from ldap try: ldap_request = settings["request"].format(login) conn.search(settings["base_dn"], ldap_request, attributes=["cn", "mail"]) response = conn.response except Exception as ex: errors.append("Can't get user data : " + str(ex)) conn.unbind() db.session.close() return render_template("login.html", errors=errors) try: # In some systems users have multiple entries on the same username, we search for one that has an email attribute. for entry in response: if entry["attributes"]["mail"] != []: email = entry["attributes"]["mail"][0] break conn.unbind() except KeyError as e: errors.append("Can't get field " + str(e) + " from your LDAP server") db.session.close() return render_template("login.html", errors=errors) except Exception as e: errors.append("Can't get some user fields", e) db.session.close() return render_template("login.html", errors=errors) # Add the new user to the DB with app.app_context(): # We create a random password, this won't be used and is simply here because it is required in CTFd # It is random so the account cannot be accessed by conventional loggin dummy_password = randomString(28) user = Users(name=login, email=email, password=dummy_password) db.session.add(user) db.session.commit() db.session.flush() login_user(user) log("registrations", "[{date}] {ip} - {name} registered with {email}") db.session.close() if is_teams_mode(): return redirect(url_for("teams.private")) return redirect(url_for("challenges.listing")) else: db.session.close() return render_template("login.html", errors=errors) def randomString(stringLength=28): letters = string.ascii_lowercase return ''.join(random.choice(letters) for i in range(stringLength)) # Removes registration of regular accounts def register_overwrite(): return redirect('/404') app.view_functions['auth.register'] = register_overwrite # Removes oauth login def oauth_overwrite(): return redirect('/404') app.view_functions['auth.oauth'] = oauth_overwrite app.view_functions['auth.login'] = login app.register_blueprint(ldap)
def load(app): app.db.create_all() # get plugin location dir_path = os.path.dirname(os.path.realpath(__file__)) register_plugin_assets_directory(app, base_path="/plugins/CTFd_Team_Attributes/assets/") # Admin Pages override_template('view_attributes.html', open(os.path.join(dir_path, 'assets/admin/view_attributes.html')).read()) override_template('create_attribute.html', open(os.path.join(dir_path, 'assets/admin/create_attribute.html')).read()) override_template('attribute_details.html', open(os.path.join(dir_path, 'assets/admin/attribute_details.html')).read()) override_template('set_team_attribute.html', open(os.path.join(dir_path, 'assets/admin/set_team_attribute.html')).read()) override_template('view_attribute_select_options.html', open(os.path.join(dir_path, 'assets/admin/view_attribute_select_options.html')).read()) override_template('create_attribute_select_option.html', open(os.path.join(dir_path, 'assets/admin/create_attribute_select_option.html')).read()) override_template('edit_attribute_select_option.html', open(os.path.join(dir_path, 'assets/admin/edit_attribute_select_option.html')).read()) # Admin Modals override_template('attribute_form.html', open(os.path.join(dir_path, 'assets/admin/modals/attribute_form.html')).read()) override_template('team_attribute.html', open(os.path.join(dir_path, 'assets/admin/modals/team_attribute.html')).read()) override_template('attribute_select_option_form.html', open(os.path.join(dir_path, 'assets/admin/modals/attribute_select_option_form.html')).read()) # Team settings page override register_script("/plugins/CTFd_Team_Attributes/assets/teams/js/team_attr.min.js") # Blueprint used to access the static_folder directory. blueprint = Blueprint( "attributes", __name__, template_folder="templates", static_folder="assets" ) api = Blueprint("attributes_api", __name__, url_prefix="/api/v1") Attributes_API_v1 = Api(api, version="v1", doc=app.config.get("SWAGGER_UI")) Attributes_API_v1.add_namespace(attributes_namespace, "/attributes") app.register_blueprint(api)