Files
SecGen/lib/templates/CTFd/submit.html

129 lines
4.8 KiB
HTML

<div class="jumbotron">
<div class="container">
<h1>Flag submission</h1>
</div>
</div>
<div class="modal-dialog" role="document">
<div class="modal-content" style='border:none;'>
<div class="modal-body">
<div role="tabpanel">
<div class="tab-content">
<div role="tabpanel" class="tab-pane fade show active" id="challenge">
<div class="chal-tags text-center"></div>
<p>This will submit your flag against a set of challenges (such as a VM). Navigate to <a href="challenges">Challenges</a> for hints for specific flags.</p>
</div>
<div class="row submit-row">
<div class="col-md-12 form-group">
<input class="form-control" type="text" name="answer" id="answer-input" placeholder="Flag" />
</div>
<div class="col-md-12 form-group">
<select id="challenge_set" class="form-control" style="height:60px;">
</select>
</div>
<div class="col-md-12 form-group key-submit">
<button type="submit" onclick="submitflags()" id="submit-key" tabindex="5" class="btn btn-md btn-outline-secondary float-right">Submit</button>
</div>
</div>
<div class="row notification-row">
<div class="col-md-12">
<div id="result-notification" class="alert alert-dismissable text-center w-100" role="alert">
<strong id="result-message"></strong>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
// pause submitting, due to rate limits?
var cont = true;
// stop submitting
var abort = false;
var challenge_list;
// retrieve the list of challenges and add VMs options to selection box on load
function loadoptions() {
var chal_list = $.get(window.location.origin + "/chals", {}, function (json) {
// get the challenge list from the server, and store it for later
challenge_list = json;
// for each challenge, add the category to the selection box, if it's not been added already
$.each(json['game'], function (i, item) {
if (!$("#challenge_set option[value='" + item['category'] + "']").length) {
$('#challenge_set').append($('<option>', {
value: item['category'],
text : item['category']
}));
}
});
$('#challenge_set').append($('<option>', {
value: 'All',
text : 'All'
}));
}, 'json');
}
window.onload = loadoptions;
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// Spams the challenge submission with flags.
// This is necessary since with SecGen flags it's not always known which # challenge they are completing.
// Since this is all done client-side (all easily importable into CTFd), we have to pause when we hit rate limits.
// This involves some timing between asynchronous threads.
async function submitflags() {
var answer = $('#answer-input').val();
var nonce = csrf_nonce;
var url = window.location.origin + "/chal/";
$( "#result-message" ).empty();
cont = true;
abort = false;
var process_count = 0;
$.each(challenge_list['game'], async function (i, item) {
var selected = $( "#challenge_set option:selected" ).text();
if (selected == "All" || selected == item["category"]) {
process_count++;
await sleep(process_count * 500); // asynchronous spacing of queries
var chal_id = item["id"];
if (abort == true) {
return;
} else if (cont == false) {
await sleep(60000);
cont = true; // on waking this currently clobbers any subsequent pause
}
$( "#result-message" ).append('#' + chal_id + ': ');
var retval = $.post(url + chal_id, {
key: answer,
nonce: nonce
}, function (json) {
// success post
$( "#result-message" ).append(json['message'] + '<br/>');
if(json['status'] == 3) {
$( "#result-message" ).append( 'Waiting 60 seconds...<br/>' );
cont = false;
// currently doesn't retry the challenges that trigger a wait
} else if(json['status'] == 1) {
$( "#result-message" ).append( '<p class="text-success">Success! (Stopping)</p>' );
abort = true;
}
}, 'json');
retval.fail(function() {
alert( "error" );
})
}
});
}
</script>