Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions dojo_plugin/api/v1/ssh_key.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
from CTFd.utils.user import get_current_user
from sshpubkeys import SSHKey, InvalidKeyError
import base64
import markupsafe

from ...models import SSHKeys

Expand All @@ -34,7 +33,7 @@ def post(self):
return (
{
"success": False,
"error": f"Invalid SSH Key, error: <code>{markupsafe.escape(e)}</code> <br>Refer below for how to generate a valid ssh key"
"error": str(e)
},
400,
)
Expand Down
22 changes: 12 additions & 10 deletions dojo_theme/static/js/dojo/challenges.js
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ function unlockChallenge(challenge_button) {
const challenge_id = item.find("#challenge").val();
const description = item.find(".challenge-description");

// This returns html that is parsed markdown, so it is fine to set the description to the raw html
CTFd.fetch(`/pwncollege_api/v1/dojos/${init.dojo}/${module_id}/${challenge_id}/description`)
.then(response => response.json())
.then(data => description.html(data.description));
Expand Down Expand Up @@ -201,18 +202,18 @@ function startChallenge(event) {
var result_message = item.find('#result-message');
result_notification.removeClass('alert-danger');
result_notification.addClass('alert alert-warning alert-dismissable text-center');
result_message.html("Loading.");
result_message.text("Loading.");
result_notification.slideDown();
var dot_max = 5;
var dot_counter = 0;
setTimeout(function loadmsg() {
if (result_message.html().startsWith("Loading")) {
if (result_message.text().startsWith("Loading")) {
if (dot_counter < dot_max - 1){
result_message.append(".");
dot_counter++;
}
else {
result_message.html("Loading.");
result_message.text("Loading.");
dot_counter = 0;
}
setTimeout(loadmsg, 500);
Expand Down Expand Up @@ -246,6 +247,7 @@ function startChallenge(event) {

if (result.success) {
var message = `Challenge successfully started! You can interact with it through a <a href="/workspace/code" target="dojo_workspace">VSCode Workspace</a> or a <a href="/workspace/desktop" target="dojo_workspace">GUI Desktop Workspace</a>.`;
// This is a message that we set, so it is safe to use the html method
result_message.html(message);
result_notification.addClass('alert alert-info alert-dismissable text-center');

Expand All @@ -254,12 +256,12 @@ function startChallenge(event) {
setTimeout(() => updateNavbarDropdown(), 1000);
}
else {
var message = "";
message += "Error:";
message += "<br>";
message += "<code>" + result.error + "</code>";
message += "<br>";
result_message.html(message);
result_message.empty();

result_message.append("Error: <br>");
var errorInfo = $("<code></code>").text(result.error);
result_message.append(errorInfo);
result_message.append("<br>");
result_notification.addClass('alert alert-warning alert-dismissable text-center');
}

Expand All @@ -277,7 +279,7 @@ function startChallenge(event) {
}).catch(function (error) {
console.error(error);
var result_message = item.find('#result-message');
result_message.html("Submission request failed: " + ((error || {}).message || error));
result_message.text("Submission request failed: " + ((error || {}).message || error));
result_notification.addClass('alert alert-warning alert-dismissable text-center');
})
}
Expand Down
1 change: 1 addition & 0 deletions dojo_theme/static/js/dojo/course.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ function form_fetch_and_show(name, endpoint, method, success_message) {
}).then(response => {
return response.json()
}).then(result => {
// This is a message that we set, so it is safe to use the html method
if (!result.success) {
results.html(error_template);
results.find("#message").html(result.error);
Expand Down
30 changes: 16 additions & 14 deletions dojo_theme/static/js/dojo/navbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ async function updateNavbarDropdown() {
$("#current #module").val(data.c_current.module_id);
$("#current #challenge").val(data.c_current.challenge_reference_id);
$("#current #challenge-id").val(data.c_current.challenge_id);
// This returns html that is parsed markdown, so it is fine to set the description to the raw html
$("#dropdown-description").html(data.c_current.description);

if ("dojo_name" in data.c_previous) {
Expand Down Expand Up @@ -107,18 +108,18 @@ function DropdownStartChallenge(event) {
var result_message = dropdown_controls.find('#result-message');
result_notification.removeClass('alert-danger');
result_notification.addClass('alert alert-warning alert-dismissable text-center');
result_message.html("Loading.");
result_message.text("Loading.");
result_notification.slideDown();
var dot_max = 5;
var dot_counter = 0;
setTimeout(function loadmsg() {
if (result_message.html().startsWith("Loading")) {
if (result_message.text().startsWith("Loading")) {
if (dot_counter < dot_max - 1){
result_message.append(".");
dot_counter++;
}
else {
result_message.html("Loading.");
result_message.text("Loading.");
dot_counter = 0;
}
setTimeout(loadmsg, 500);
Expand Down Expand Up @@ -152,6 +153,7 @@ function DropdownStartChallenge(event) {

if (result.success) {
let message = `Challenge successfully started! You can interact with it through a <a href="/workspace/code" target="dojo_workspace">VSCode Workspace</a> or a <a href="/workspace/desktop">GUI Desktop</a>.`;
// This is a message that we set, so it is safe to use the html method
result_message.html(message);
result_notification.addClass('alert alert-info alert-dismissable text-center');
await updateNavbarDropdown();
Expand All @@ -164,11 +166,11 @@ function DropdownStartChallenge(event) {
});
}
else {
let message = "Error:";
message += "<br>";
message += "<code>" + result.error + "</code>";
message += "<br>";
result_message.html(message);
result_message.empty();
result_message.append("Error: <br>");
var errorInfo = $("<code></code>").text(result.error);
result_message.append(errorInfo);
result_message.append("<br>");
result_notification.addClass('alert alert-warning alert-dismissable text-center');
}

Expand All @@ -183,7 +185,7 @@ function DropdownStartChallenge(event) {
}).catch(function (error) {
console.error(error);
let result_message = dropdown_controls.find('#result-message');
result_message.html("Submission request failed: " + ((error || {}).message || error));
result_message.text("Submission request failed: " + ((error || {}).message || error));
result_notification.addClass('alert alert-warning alert-dismissable text-center');
})
event.stopPropagation();
Expand All @@ -203,7 +205,7 @@ function submitFlag(event) {
var result_message = dropdown_controls.find('#result-message');
result_notification.removeClass();
result_notification.addClass('alert alert-warning alert-dismissable text-center');
result_message.html("Loading...");
result_message.text("Loading...");
result_notification.slideDown();

var timer = setTimeout(() => {
Expand All @@ -213,7 +215,7 @@ function submitFlag(event) {
if (submission === "pwn.college{practice}") {
result_notification.removeClass();
result_notification.addClass('alert alert-success alert-dismissable text-center');
result_message.html('You have submitted the "practice" flag from launching the challenge in Practice mode! This flag is not valid for scoring. Run the challenge in non-practice mode by pressing Start above, then use your solution to get the "real" flag and submit it!');
result_message.text('You have submitted the "practice" flag from launching the challenge in Practice mode! This flag is not valid for scoring. Run the challenge in non-practice mode by pressing Start above, then use your solution to get the "real" flag and submit it!');
event.stopPropagation();
return
}
Expand All @@ -223,7 +225,7 @@ function submitFlag(event) {
if (result.status === 'correct') {
result_notification.removeClass();
result_notification.addClass('alert alert-success alert-dismissable text-center');
result_message.html('Flag submitted successfully!');
result_message.text('Flag submitted successfully!');
$("#dropdown-challenge-input").val("");

const broadcast_send = new BroadcastChannel('broadcast');
Expand All @@ -234,15 +236,15 @@ function submitFlag(event) {
} else {
result_notification.removeClass();
result_notification.addClass('alert alert-danger alert-dismissable text-center');
result_message.html('Flag submission failed: '+ result.message);
result_message.text('Flag submission failed: '+ result.message);
}
clearTimeout(timer);
setTimeout(() => result_notification.slideUp(), 5000);
}).catch(err => {
const result = err.data;
result_notification.removeClass();
result_notification.addClass('alert alert-danger alert-dismissable text-center');
result_message.html('Flag submission failed: '+ result.message);
result_message.text('Flag submission failed: '+ result.message);
clearTimeout(timer);
setTimeout(() => result_notification.slideUp(), 5000);
});
Expand Down
1 change: 1 addition & 0 deletions dojo_theme/static/js/dojo/scoreboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ function loadScoreboard(duration, page) {

const endpoint = `/pwncollege_api/v1/scoreboard/${dojo}/${module}/${duration}/${page}`;
scoreboard.empty();
// This is a message that we set, so it is safe to use the html method
message = "Loading."
scoreboard.html(`<td colspan=6>${message}</td>`);
setTimeout(function loadmsg() {
Expand Down
34 changes: 28 additions & 6 deletions dojo_theme/static/js/dojo/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,28 @@ var loading_template =
' <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>\n' +
'</div>';

function form_fetch_and_show(name, endpoint, method, success_message, confirm_msg=null) {

function showSafeError(template, errorText, $target) {
const [before, after] = template.split("{e}");

$target.empty();

$("<span>").html(before).appendTo($target);

$("<code>").text(errorText).appendTo($target);

$("<span>").html(after).appendTo($target);
}

function form_fetch_and_show(name, endpoint, method, success_message, confirm_msg=null, error_message="{e}") {
const form = $(`#${name}-form`);
const results = $(`#${name}-results`);
form.submit(e => {
e.preventDefault();
results.empty();
const params = form.serializeJSON();
if (confirm_msg && !confirm(confirm_msg(form, params))) return;
// This is a message that we set, so it is safe to use the html method
results.html(loading_template);
CTFd.fetch(endpoint, {
method: method,
Expand All @@ -40,11 +54,16 @@ function form_fetch_and_show(name, endpoint, method, success_message, confirm_ms
return response.json()
}).then(result => {
if (result.success) {
// This is a message that we set, so it is safe to use the html method
results.html(success_template);
results.find("#message").text(success_message);
} else {
results.html(error_template);
results.find("#message").html(result.error);
// This is a message that we set, and it sets the error as text on that html so it is safe to use the html method
const $errorHtml = $(error_template);

showSafeError(error_message, result.error, $errorHtml.find("#message"));

results.html($errorHtml);
}
});
});
Expand All @@ -57,10 +76,12 @@ function button_fetch_and_show(name, endpoint, method,data, success_message, abo
button.click(()=>{
results.empty();
if (confirm_msg && !confirm_msg(data)) {
// This is a message that we set, so it is safe to use the html method
results.html(error_template);
results.find("#message").html(abort_message);
results.find("#message").text(abort_message);
return
};
// This is a message that we set, so it is safe to use the html method
results.html(loading_template);
CTFd.fetch(endpoint, {
method: method,
Expand All @@ -74,18 +95,19 @@ function button_fetch_and_show(name, endpoint, method,data, success_message, abo
return response.json()
}).then(result => {
if (result.success) {
// This is a message that we set, so it is safe to use the html method
results.html(success_template);
results.find("#message").text(success_message);
} else {
results.html(error_template);
results.find("#message").html(result.error);
results.find("#message").text(result.error);
}
});
});
}

$(() => {
form_fetch_and_show("ssh-key", "/pwncollege_api/v1/ssh_key", "POST", "Your public key has been updated");
form_fetch_and_show("ssh-key", "/pwncollege_api/v1/ssh_key", "POST", "Your public key has been updated", null, "Invalid SSH Key, error: {e} <br>Refer below for how to generate a valid ssh key");
form_fetch_and_show("discord", "/pwncollege_api/v1/discord", "DELETE", "Your discord account has been disconnected");
form_fetch_and_show("dojo-create", "/pwncollege_api/v1/dojos/create", "POST", "Your dojo has been created");
form_fetch_and_show("dojo-promote-admin", `/pwncollege_api/v1/dojos/${init.dojo}/admins/promote`, "POST", "User has been promoted to admin.", confirm_msg = (form, params) => {
Expand Down