Skip to content

Commit

Permalink
Some more
Browse files Browse the repository at this point in the history
  • Loading branch information
huner2 committed Jun 17, 2018
1 parent c64d282 commit 7c9735f
Show file tree
Hide file tree
Showing 8 changed files with 517 additions and 4 deletions.
87 changes: 84 additions & 3 deletions __init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def create(request):
files = request.files.getlist('files[]')

# Create challenge
chal = GenFlags(
chal = GenFlagCDBM(
name=request.form['name'],
value=request.form['value'],
category=request.form['category'],
Expand Down Expand Up @@ -46,6 +46,86 @@ def create(request):

db.session.commit()

@staticmethod
def read(challenge, team):
challenge = GenFlagCDBM.query.filter_by(id=challenge.id).first()
data = {
'id': challenge.id,
'name': challenge.name,
'value': challenge.value,
'description': challenge.description,
'category': challenge.category,
'hidden': challenge.hidden,
'max_attempts': challenge.max_attempts,
'type': challenge.type,
'type_data': {
'id': GenFlagCDBM.id,
'name': GenFlagCDBM.name,
'templates': GenFlagCDBM.templates,
'scripts': GenFlagCDBM.scripts,
}
}
return challenge, data

@staticmethod
def update(challenge, request):
challenge = GenFlagCDBM.query.filter_by(id=challenge.id).first()

challenge.name = request.form['name']
challenge.description = request.form['description']
challenge.value = int(request.form.get('value', 0)) if request.form.get('value', 0) else 0
challenge.max_attempts = int(request.form.get('max_attempts', 0)) if request.form.get('max_attempts', 0) else 0
challenge.category = request.form['category']
challenge.hidden = 'hidden' in request.form

db.session.commit()
db.session.close()

@staticmethod
def delete(challenge):
WrongKeys.query.filter_by(chalid=challenge.id).delete()
Solves.query.filter_by(chalid=challenge.id).delete()
Keys.query.filter_by(chal=challenge.id).delete()
files = Files.query.filter_by(chal=challenge.id).all()
for f in files:
utils.delete_file(f.id)
Files.query.filter_by(chal=challenge.id).delete()
Tags.query.filter_by(chal=challenge.id).delete()
Hints.query.filter_by(chal=challenge.id).delete()
GenFlagCDBM.query.filter_by(id=challenge.id).delete()
GenFlagsMap.query.filter_by(id=challenge.id).delete()
Challenges.query.filter_by(id=challenge.id).delete()
db.session.commit()

@staticmethod
def attempt(chal, request):
provided_key = request.form['key'].strip()
chal_keys = GenFlagsMap.query.filter_by(chal=team.id).all()
for chal_key in chal_keys:
if get_key_class(chal_key.type).compare(chal_key, provided_key):
return True, 'Correct'
return False, 'Incorrect'

@staticmethod
def solve(team, chal, request):
chal = GenFlagCDBM.query.filter_by(id=chal.id).first()
solve_count = Solves.query.join(Teams, Solves.teamid == Teams.id).filter(Solves.chalid==chal.id, Teams.banned==False).count()

provided_key = request.form['key'].strip()
solve = Solves(teamid=team.id, chalid=chal.id, ip=utils.get_ip(req=request), flag=provided_key)
db.session.add(solve)

db.session.commit()
db.session.close()

@staticmethod
def fail(team, chal, request):
provided_key = request.form['key'].strip()
wrong = WrongKeys(teamid=team.id, chalid=chal.id, ip=utils.get_ip(request), flag=provided_key)
db.session.add(wrong)
db.session.commit()
db.session.close()


class GenFlagCDBM(challenges):
__mapper_args__ = {'polymorphic_identity': 'genflags'}
Expand All @@ -61,15 +141,16 @@ def __init__(self, name, value, category, type='genflag', key, generator):
self.key = key
self.generator = generator

class GenFlags(db.model):
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, flag):
def __init__(self, teamid, description, type, flag):
self.teamid = teamid
self.flag = flag
self.type = type
self.description = description

def load(app):
Expand Down
29 changes: 29 additions & 0 deletions assets/autogen-challenge-create.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Markdown Preview
$('#desc-edit').on('shown.bs.tab', function (event) {
if (event.target.hash == '#desc-preview'){
var editor_value = $('#desc-editor').val();
$(event.target.hash).html(
window.challenge.render(editor_value)
);
}
});
$('#new-desc-edit').on('shown.bs.tab', function (event) {
if (event.target.hash == '#new-desc-preview'){
var editor_value = $('#new-desc-editor').val();
$(event.target.hash).html(
window.challenge.render(editor_value)
);
}
});
$("#solve-attempts-checkbox").change(function() {
if(this.checked) {
$('#solve-attempts-input').show();
} else {
$('#solve-attempts-input').hide();
$('#max_attempts').val('');
}
});

$(document).ready(function(){
$('[data-toggle="tooltip"]').tooltip();
});
104 changes: 104 additions & 0 deletions assets/autogen-challenge-create.njk
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
<form method="POST" action="{{ script_root }}/admin/chal/newAutogen" enctype="multipart/form-data">
<div class="form-group">
Autogen challenges create a unique flag for each team. A challenge is passed to a generator class, and the class returns the generated flag.
</div>

<div class="form-group">
<label for="name">Name
<i class="far fa-question-circle text-muted cursor-help" data-toggle="tooltip" data-placement="right" title="The name of your challenge"></i>
</label>
<input type="text" class="form-control" name="name" placeholder="Enter challenge name">
</div>
<div class="form-group">
<label for="category">Category
<i class="far fa-question-circle text-muted cursor-help" data-toggle="tooltip" data-placement="right" title="The category of your challenge"></i>
</label>
<input type="text" class="form-control" name="category" placeholder="Enter challenge category">
</div>

<ul class="nav nav-tabs" role="tablist" id="new-desc-edit">
<li class="nav-item">
<a class="nav-link active" href="#new-desc-write" aria-controls="home" role="tab" data-toggle="tab">Write</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#new-desc-preview" aria-controls="home" role="tab" data-toggle="tab">Preview</a>
</li>
</ul>

<div class="tab-content">
<div role="tabpanel" class="tab-pane active" id="new-desc-write">
<div class="form-group">
<label for="message-text" class="control-label">Message:
<i class="far fa-question-circle text-muted cursor-help" data-toggle="tooltip" data-placement="right" title="Use this to give a brief introduction to your challenge. The description supports HTML and Markdown."></i>
</label>
<textarea id="new-desc-editor" class="form-control" name="description" rows="10"></textarea>
</div>
</div>
<div role="tabpanel" class="tab-pane content" id="new-desc-preview" style="height:234px; overflow-y: scroll;">
</div>
</div>

<div class="form-group">
<label for="value">Value
<i class="far fa-question-circle text-muted cursor-help" data-toggle="tooltip" data-placement="right" title="This is how many points the challenge is worth."></i>
</label>
<input type="number" class="form-control" name="value" placeholder="Enter value" required>
</div>

<div class="form-group">
<select class="custom-select" name="key_type[0]">
<option value="static">Static</option>
<option value="regex">Regex</option>
</select>
</div>

<div class="form-group">
<select class="custom-select" name="generator">
{% for generator in generators %}
<option value="{ generator.name }">{ generator.name }</option>
{% endfor %}
</select>
</div>

<div class="form-check">
<div class="checkbox">
<label class="form-check-label">
<input class="form-check-input" name="hidden" type="checkbox">
Hide challenge on creation
</label>
</div>
</div>

<div class="form-check">
<div class="checkbox">
<label class="form-check-label">
<input class="form-check-input" type="checkbox" id="solve-attempts-checkbox">
Limit amount of solve attempts
</label>
</div>
</div>

<div class="form-group">
<div id="solve-attempts-input" style="display: none;">
<label for="max_attempts">Maximum Attempts
<i class="far fa-question-circle text-muted cursor-help" data-toggle="tooltip" data-placement="right" title="How many attempts should a user have for this challenge? For unlimited attempts, use the value 0"></i>
</label>
<input class="form-control" id='max_attempts' name='max_attempts' type='number' placeholder="0">
</div>
</div>

<div class="form-group">
<label>Upload Challenge Files
<i class="far fa-question-circle text-muted cursor-help" data-toggle="tooltip" data-placement="right" title="Challenges files are provided to users for download alongside your challenge description"></i>
</label>
<input class="form-control-file" type="file" name="files[]" multiple="multiple">
<sub class="help-block">Attach multiple files using Control+Click or Cmd+Click.</sub>
</div>

<input type="hidden" value="{{ nonce }}" name="nonce" id="nonce">
<input type="hidden" value="dynamic" name="chaltype" id="chaltype">

<div class="form-group">
<button class="btn btn-primary float-right create-challenge-submit" type="submit">Create</button>
</div>
</form>
34 changes: 34 additions & 0 deletions assets/autogen-challenge-modal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
window.challenge.renderer = new markdownit({
html: true,
});

window.challenge.preRender = function () {

};

window.challenge.render = function (markdown) {
return window.challenge.renderer.render(markdown);
};


window.challenge.postRender = function () {

};

window.challenge.submit = function (cb, preview) {
var chal_id = $('#chal-id').val();
var answer = $('#answer-input').val();
var nonce = $('#nonce').val();

var url = "/chal/";
if (preview) {
url = "/admin/chal/";
}

$.post(script_root + url + chal_id, {
key: answer,
nonce: nonce
}, function (data) {
cb(data);
});
};
104 changes: 104 additions & 0 deletions assets/autogen-challenge-modal.njk
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-body">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
<ul class="nav nav-tabs">
<li class="nav-item">
<a class="nav-link active" href="#challenge">Challenge</a>
</li>
{% if solves == '-1 Solves' %}
{% else %}
<li class="nav-item">
<a class="nav-link chal-solves" href="#solves">{{solves}}</a>
</li>
{% endif %}
</ul>
<div role="tabpanel">
<div class="tab-content">
<div role="tabpanel" class="tab-pane fade show active" id="challenge">
<h2 class='chal-name text-center pt-3'>{{ name }}</h2>
<h3 class="chal-value text-center">{{ value }}</h3>
<div class="chal-tags text-center">
{% for tag in tags %}
<span class='badge badge-info chal-tag'>{{tag}}</span>
{% endfor %}
</div>
<span class="chal-desc">{{ description | safe }}</span>
<div class="chal-hints hint-row row">
{% for hint in hints %}
<div class='col-md-12 hint-button-wrapper text-center mb-3'>
<a class="btn btn-info btn-hint btn-block" href="javascript:;" onclick="javascript:loadhint({{hint.id}})">
{% if hint.hint %}
<small>
View Hint
</small>
{% else %}
{% if hint.cost %}
<small>
Unlock Hint for {{hint.cost}} points
</small>
{% else %}
<small>
View Hint
</small>
{% endif %}
{% endif %}
</a>
</div>
{% endfor %}
</div>
<div class="row chal-files text-center pb-3">
{% for file in files %}
<div class='col-md-4 col-sm-4 col-xs-12 file-button-wrapper d-block'>
<a class='btn btn-info btn-file mb-1 d-inline-block px-2 w-100 text-truncate' href='{{script_root}}/files/{{file}}'>
<i class="fas fa-download"></i>
<small>
{{ file.split('/')[1] }}
</small>
</a>
</div>
{% endfor %}
</div>

<div class="row submit-row">
<div class="col-md-9 form-group">
<input class="form-control" type="text" name="answer" id="answer-input" placeholder="Flag" />
<input id="chal-id" type="hidden" value="{{id}}">
</div>
<div class="col-md-3 form-group key-submit">
<button type="submit" 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" style="display: none;">
<strong id="result-message"></strong>
</div>
</div>
</div>
</div>
<div role="tabpanel" class="tab-pane fade" id="solves">
<div class="row">
<div class="col-md-12">
<table class="table table-striped text-center">
<thead>
<tr>
<td><b>Name</b>
</td>
<td><b>Date</b>
</td>
</tr>
</thead>
<tbody id="chal-solves-names">
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
Loading

0 comments on commit 7c9735f

Please sign in to comment.