def admin_create_chal(): files = request.files.getlist('files[]') ## TODO: Expand to support multiple flags flags = [{'flag':request.form['key'], 'type':int(request.form['key_type[0]'])}] # Create challenge chal = Challenges(request.form['name'], request.form['desc'], request.form['value'], request.form['category'], flags) if 'hidden' in request.form: chal.hidden = True else: chal.hidden = False db.session.add(chal) db.session.commit() for f in files: filename = secure_filename(f.filename) if len(filename) <= 0: continue md5hash = hashlib.md5(os.urandom(64)).hexdigest() if not os.path.exists(os.path.join(os.path.normpath(app.static_folder), 'uploads', md5hash)): os.makedirs(os.path.join(os.path.normpath(app.static_folder), 'uploads', md5hash)) f.save(os.path.join(os.path.normpath(app.static_folder), 'uploads', md5hash, filename)) db_f = Files(chal.id, os.path.join('static', 'uploads', md5hash, filename)) db.session.add(db_f) db.session.commit() db.session.close() return redirect(url_for('admin.admin_chals'))
def admin_create_chal(): if request.method == 'POST': files = request.files.getlist('files[]') # Create challenge chal = Challenges(request.form['name'], request.form['desc'], request.form['value'], request.form['category'], int(request.form['chaltype'])) if 'hidden' in request.form: chal.hidden = True else: chal.hidden = False db.session.add(chal) db.session.flush() flag = Keys(chal.id, request.form['key'], int(request.form['key_type[0]'])) if request.form.get('keydata'): flag.data = request.form.get('keydata') db.session.add(flag) db.session.commit() for f in files: upload_file(file=f, chalid=chal.id) db.session.commit() db.session.close() return redirect(url_for('admin_challenges.admin_chals')) else: return render_template('admin/chals/create.html')
def admin_create_chal(): files = request.files.getlist('files[]') # TODO: Expand to support multiple flags flags = [{ 'flag': request.form['key'], 'type': int(request.form['key_type[0]']) }] # Create challenge chal = Challenges(request.form['name'], request.form['desc'], request.form['value'], request.form['category'], flags) if 'hidden' in request.form: chal.hidden = True else: chal.hidden = False db.session.add(chal) db.session.commit() for f in files: upload_file(file=f, chalid=chal.id) db.session.commit() db.session.close() return redirect(url_for('admin.admin_chals'))
def admin_create_chal(): if request.method == 'POST': files = request.files.getlist('files[]') # Create challenge chal = Challenges(request.form['name'], request.form['desc'], request.form['value'], request.form['category'], int(request.form['chaltype'])) if 'hidden' in request.form: chal.hidden = True else: chal.hidden = False max_attempts = request.form.get('max_attempts') if max_attempts and max_attempts.isdigit(): chal.max_attempts = int(max_attempts) db.session.add(chal) db.session.flush() flag = Keys(chal.id, request.form['key'], int(request.form['key_type[0]'])) if request.form.get('keydata'): flag.data = request.form.get('keydata') db.session.add(flag) db.session.commit() for f in files: utils.upload_file(file=f, chalid=chal.id) db.session.commit() db.session.close() return redirect(url_for('admin_challenges.admin_chals')) else: return render_template('admin/chals/create.html')
def create(request): """ This method is used to process the challenge creation request. :param request: :return: """ files = request.files.getlist('files[]') # Create challenge chal = Challenges(name=request.form['name'], description=request.form['desc'], value=request.form['value'], category='Bonus Flags', type=request.form['chaltype']) chal.hidden = True db.session.add(chal) db.session.commit() flag = Keys(chal.id, request.form['key'], request.form['key_type[0]']) if request.form.get('keydata'): flag.data = request.form.get('keydata') db.session.add(flag) db.session.commit() for f in files: utils.upload_file(file=f, chalid=chal.id) db.session.commit()
def create(request): """ This method is used to process the challenge creation request. :param request: :return: """ # Create challenge chal = Challenges( name=request.form['name'], description=request.form['description'], value=request.form['value'], category=request.form['category'], type=request.form['chaltype'], penalty = request.form['penalty'] ) if 'hidden' in request.form: chal.hidden = True else: chal.hidden = False max_attempts = request.form.get('max_attempts') if max_attempts and max_attempts.isdigit(): chal.max_attempts = int(max_attempts) db.session.add(chal) db.session.commit() flag = Keys(chal.id, request.form['key'], request.form['key_type[0]']) if request.form.get('keydata'): flag.data = request.form.get('keydata') db.session.add(flag) db.session.commit() files = request.files.getlist('files[]') for f in files: utils.upload_file(file=f, chalid=chal.id) file_generators = request.files.getlist('file_generators[]') for g in file_generators: utils.upload_file(file=g, chalid=chal.id, isgenerator=True) db.session.commit()
def import_challenges(in_file, dst_attachments, exit_on_error=True, move=False): from CTFd.models import db, Challenges, Keys, Tags, Files chals = [] with open(in_file, 'r') as in_stream: chals = yaml.safe_load_all(in_stream) for chal in chals: skip = False for req_field in REQ_FIELDS: if req_field not in chal: if exit_on_error: raise MissingFieldError(req_field) else: print "Skipping challenge: Missing field '{}'".format(req_field) skip = True break if skip: continue for flag in chal['flags']: if 'flag' not in flag: if exit_on_error: raise MissingFieldError('flag') else: print "Skipping flag: Missing field 'flag'" continue flag['flag'] = flag['flag'].strip() if 'type' not in flag: flag['type'] = "static" # We ignore traling and leading whitespace when importing challenges chal_dbobj = Challenges( chal['name'].strip(), chal['description'].strip(), chal['value'], chal['category'].strip() ) if 'hidden' in chal and chal['hidden']: chal_dbobj.hidden = True matching_chals = Challenges.query.filter_by( name=chal_dbobj.name, description=chal_dbobj.description, value=chal_dbobj.value, category=chal_dbobj.category, hidden=chal_dbobj.hidden ).all() for match in matching_chals: if 'tags' in chal: tags_db = [tag.tag for tag in Tags.query.add_columns('tag').filter_by(chal=match.id).all()] if all([tag not in tags_db for tag in chal['tags']]): continue if 'files' in chal: files_db = [f.location for f in Files.query.add_columns('location').filter_by(chal=match.id).all()] if len(files_db) != len(chal['files']): continue hashes = [] for file_db in files_db: with open(os.path.join(dst_attachments, file_db), 'r') as f: hash = hashlib.md5(f.read()).digest() hashes.append(hash) mismatch = False for file in chal['files']: filepath = os.path.join(os.path.dirname(in_file), file) with open(filepath, 'r') as f: hash = hashlib.md5(f.read()).digest() if hash in hashes: hashes.remove(hash) else: mismatch = True break if mismatch: continue flags_db = Keys.query.filter_by(chal=match.id).all() for flag in chal['flags']: for flag_db in flags_db: if flag['flag'] != flag_db.flag: continue if flag['type'] != flag_db.key_type: continue skip = True break if skip: print "Skipping {}: Duplicate challenge found in DB".format(chal['name'].encode('utf8')) continue print "Adding {}".format(chal['name'].encode('utf8')) db.session.add(chal_dbobj) db.session.commit() if 'tags' in chal: for tag in chal['tags']: tag_dbobj = Tags(chal_dbobj.id, tag) db.session.add(tag_dbobj) for flag in chal['flags']: flag_db = Keys(chal_dbobj.id, flag['flag'], flag['type']) db.session.add(flag_db) if 'files' in chal: for file in chal['files']: filename = os.path.basename(file) dst_filename = secure_filename(filename) dst_dir = None while not dst_dir or os.path.exists(dst_dir): md5hash = hashlib.md5(os.urandom(64)).hexdigest() dst_dir = os.path.join(dst_attachments, md5hash) os.makedirs(dst_dir) dstpath = os.path.join(dst_dir, dst_filename) srcpath = os.path.join(os.path.dirname(in_file), file) if move: shutil.move(srcpath, dstpath) else: shutil.copy(srcpath, dstpath) file_dbobj = Files(chal_dbobj.id, os.path.relpath(dstpath, start=dst_attachments)) db.session.add(file_dbobj) db.session.commit() db.session.close()
def import_challenges(in_file, dst_attachments, exit_on_error=True, move=False): from CTFd.models import db, Challenges, Keys, Tags, Files, Hints, Unlocks with open(in_file, 'r') as in_stream: chals = yaml.safe_load_all(in_stream) for chal in chals: # ensure all required fields are present before adding or updating a challenge try: validate_yaml(chal) except MissingFieldError as err: if exit_on_error: raise else: print "Skipping challenge: " + str(err) continue # if the challenge already exists, update it chal_db = Challenges.query.filter_by(name=chal['name']).first() if chal_db is not None: print "Updating {}".format(chal['name'].encode('utf8')) chal_db.description = chal['description'] chal_db.value = chal['value'] chal_db.category = chal['category'] else: print "Adding {}".format(chal['name'].encode('utf8')) chal_db = Challenges( chal['name'], chal['description'], chal['value'], chal['category']) chal_db.type = chal['type'] chal_db.hidden = chal['hidden'] db.session.add(chal_db) db.session.commit() # delete all tags and re-add them Tags.query.filter_by(chal=chal_db.id).delete() for tag in chal['tags']: tag_dbobj = Tags(chal_db.id, tag) db.session.add(tag_dbobj) # delete all flags and re-add them Keys.query.filter_by(chal=chal_db.id).delete() for flag in chal['flags']: flag_db = Keys(chal_db.id, flag['flag'], flag['type']) db.session.add(flag_db) # delete or update existing hints hints = {h['id']: h for h in chal['hints']} hints_db = Hints.query.filter_by(chal=chal_db.id).all() for hint_db in hints_db: if hint_db.type in hints: # the hint is being updated hint_db.hint = hints[hint_db.type]['hint'] hint_db.cost = hints[hint_db.type]['cost'] del hints[hint_db.type] else: # the hint is being deleted - delete the hint and any related unlocks print " Removing hint {:d}".format(hint_db.type) Unlocks.query.filter_by(model='hints', itemid=hint_db.id).delete() Hints.query.filter_by(id=hint_db.id).delete() # add new hints for hint in hints.values(): print " Adding hint {:d}".format(hint['id']) hint_db = Hints(chal_db.id, hint['hint'], cost=hint['cost'], type=hint['id']) db.session.add(hint_db) # hash and compare existing files with the new uploaded files hashes_db = {} files_db = Files.query.filter_by(chal=chal_db.id).all() for file_db in files_db: with open(os.path.join(dst_attachments, file_db.location), 'rb') as f: h = hashlib.md5(f.read()).digest() hashes_db[h] = file_db to_upload = [] for file in chal['files']: path = os.path.join(os.path.dirname(in_file), file) with open(path, "rb") as f: h = hashlib.md5(f.read()).digest() if h in hashes_db and os.path.basename(file) == os.path.basename(hashes_db[h].location): # the file is up to date del hashes_db[h] else: # the file has changed name or content to_upload.append(path) # remove out of date files and add new uploads for file_db in hashes_db.values(): print " Removing file {}".format(file_db.location) utils.delete_file(file_db.id) for path in to_upload: basename = os.path.basename(path) print " Adding file {}".format(basename) with open(path, "rb") as f: f = FileStorage(stream=f, filename=basename) utils.upload_file(file=f, chalid=chal_db.id) if move: os.unlink(path) db.session.commit() db.session.commit() db.session.close()
def admin_create_chal(): if request.method == 'POST': print("[DEBUG] Post request sent to my modified admin_create_chal") files = request.files.getlist('files[]') # Create challenge chal = Challenges( name=request.form['name'], description=request.form['desc'], value=request.form['value'], category=request.form['category'], type=request.form['chaltype'], ) if 'hidden' in request.form: chal.hidden = True else: chal.hidden = False max_attempts = request.form.get('max_attempts') if max_attempts and max_attempts.isdigit(): chal.max_attempts = int(max_attempts) db.session.add(chal) db.session.flush() # This if added by me print("[DEBUG] chal.id: " + str(chal.id)) if chal.type == 'ethereum': solidity = request.form['solidity'] test_func = request.form['test_func'] args = request.form['args'] starting_ether = request.form['starting-ether'] flag = request.form['key'] print("[DEBUG] Type is ethereum!") if ethereumctf.compile_contract(str(chal.id), solidity, test_func, ast.literal_eval(args), starting_ether, flag): print("[DEBUG] successful compile!") else: db.session.rollback() print("[DEBUG] failed compile") return redirect( url_for('admin_challenges.admin_create_chal') ) # TODO: Fail better db.session.commit() flag = Keys(chal.id, request.form['key'], int(request.form['key_type[0]'])) if request.form.get('keydata'): flag.data = request.form.get('keydata') db.session.add(flag) db.session.commit() for f in files: utils.upload_file(file=f, chalid=chal.id) db.session.commit() db.session.close() return redirect(url_for('admin_challenges.admin_chals')) else: return render_template('admin/chals/create.html')