def multi_upload(): form = MultiUploadForm() if request.method == 'POST': filenames = [] # 验证CSRF令牌 try: validate_csrf(form.csrf_token.data) except ValidationError: flash('CSRF token error.') return redirect(url_for('multi_upload')) # 检查文件是否存在 if 'image' not in request.files: flash('This field is required.') return redirect(url_for('multi_upload')) for f in request.files.getlist('image'): # 检查文件类型 if f and allowed_file(f.filename): filename = random_filename(f.filename) f.save(os.path.join(app.config['UPLOAD_PATH'], filename )) filenames.append(filename) else: flash('Invalid file type:') return redirect(url_for('multi_upload')) flash('Upload success.') session['filenames'] = filenames return redirect(url_for('show_images')) return render_template('upload.html', form=form)
def share(): """Route for posting image data to IMGUR to share via a link.""" img = request.values.get('data') try: validate_csrf(request.headers.get('X-Csrftoken')) except ValidationError as e: abort(400, str(e)) result = {'success': True, 'link': 'https://imgur.com/opoxoisdf.png'} # Add the authorization headers clientid = current_app.config['IMGUR_CLIENT_ID'] header = {'Authorization': 'Client-ID %s' % clientid} # POST parameters for imgur API payload = {'image': img.split('base64,')[-1], 'type': 'base64'} resp = requests.post('https://api.imgur.com/3/image', payload, headers=header) respdata = json.loads(resp.text) if respdata['success']: result = {'success': respdata['success'], 'link': respdata['data']['link']} return jsonify(result), 200 else: return jsonify({'success': False}), 400
def post_attachment(self, workspace_name, vuln_id): try: validate_csrf(request.form.get('csrf_token')) except wtforms.ValidationError: flask.abort(403) vuln_workspace_check = db.session.query(VulnerabilityGeneric, Workspace.id).join( Workspace).filter(VulnerabilityGeneric.id == vuln_id, Workspace.name == workspace_name).first() if vuln_workspace_check: if 'file' not in request.files: flask.abort(400) faraday_file = FaradayUploadedFile(request.files['file'].read()) filename = request.files['file'].filename get_or_create( db.session, File, object_id=vuln_id, object_type='vulnerability', name=filename, filename=filename, content=faraday_file ) db.session.commit() return flask.jsonify({'message': 'Evidence upload was successful'}) else: flask.abort(404, "Vulnerability not found")
def multiple_file(): form = Mutiple_File_Form() if request.method == 'POST': filenames = [] #多文件 用列表存放 try: validate_csrf(form.csrf_token.data) except ValidationError: flash('CSRF WRONG!') return redirect(url_for('multiple_file')) if 'photos' not in request.files: flash('EMPTY FILE!') return redirect(url_for('multiple_file')) for file in request.files.getlist('photos'): filename = file.filename if file and not check_suffix(filename): flash('WRONG FILE TYPE!') return redirect(url_for('multiple_file')) # pass filename = random_filename(filename) file.save(os.path.join(app.config['UPLOADS_URL'], filename)) filenames.append(filename) session['filenames'] = filenames flash('uploads success!') return redirect(url_for('show_multi_img')) return render_template('multi-file.html', form=form)
def post_attachment(self, workspace_name, vuln_id): try: validate_csrf(request.form.get('csrf_token')) except wtforms.ValidationError: flask.abort(403) vuln_workspace_check = db.session.query( VulnerabilityGeneric, Workspace.id).join(Workspace).filter( VulnerabilityGeneric.id == vuln_id, Workspace.name == workspace_name).first() if vuln_workspace_check: if 'file' not in request.files: flask.abort(400) faraday_file = FaradayUploadedFile(request.files['file'].read()) filename = request.files['file'].filename get_or_create(db.session, File, object_id=vuln_id, object_type='vulnerability', name=filename, filename=filename, content=faraday_file) db.session.commit() return flask.jsonify({'message': 'Evidence upload was successful'}) else: flask.abort(404, "Vulnerability not found")
def edit(id): if request.method == 'GET': if id: service = find_service(id) if service: form = ServiceForm() for ff in form.__dict__: for sf in service.__dict__: if ff == sf: if isinstance(form.__dict__[ff], TextAreaField): form.__dict__[ff].process_data( service.__dict__[sf]) return render_template('splash/actions/services/edit.html', service=service, form=form) return abort(404) else: form = ServiceForm(request.form) service = find_service(id) owner = service.owner_id category_items = service.category_items validate_csrf(form.csrf_token.data) service.__init__(**form.data) service.category_items = category_items service.owner_id = owner service.save() if find_service(id): return json.dumps({'success': True}), 200, { 'ContentType': 'application/json' } return abort(400)
def change_count(): # 如果用户未登录,返回相关信息给AJAX,手动处理重定向。 # 如果交给@login_required自动重定向的话, # AJAX不能正确处理这个重定向 if not current_user.is_authenticated: return jsonify({ 'status': 302, 'location': url_for( 'auth.login', next=request.referrer.replace( url_for('.index', _external=True)[:-1], '')) }) # 以post方式传的数据在存储在的request.form中,以get方式传输的在request.args中~~ # 同理,csrf token认证也要手动解决重定向 try: validate_csrf(request.headers.get('X-CSRFToken')) except ValidationError: return jsonify({ 'status': 400, 'location': url_for( 'auth.login', next=request.referrer.replace( url_for('.index', _external=True)[:-1], '')) }) po_id = int(request.form.get('po_id')) count = int(request.form.get('count')) ha = Have.query.filter_by(portal_id=po_id, user_id=current_user.id).first() if ha is not None: ha.count = count else: ha = Have(portal_id=po_id, user_id=current_user.id, count=count) db.session.add(ha) return 'ok'
def multi_upload(): form = MultiUploadForm() if request.method == 'POST': filenames = [] try: validate_csrf(form.csrf_token.data) except ValidationError: flash('CSRF token 错误!') return redirect(url_for('multi_upload')) if 'photo' not in request.files: flash('文件不存在!') return redirect(url_for('multi_upload')) for f in request.files.getlist('photo'): if f and allowed_file(f.filename): filename = random_filename(f.filename) f.save(os.path.join(app.config['UPLOAD_PATH'], filename)) filenames.append(filename) else: flash('文件无效!') return redirect(url_for('multi_upload')) flash('上传成功!') session['filenames'] = filenames return redirect(url_for('show_images')) return render_template('upload_file.html', form=form)
def favorites_delete(siret): """ Delete an office from the favorites of a user. """ # Since we are not using a FlaskForm but a hidden input with the token in the # form, CSRF validation has to be done manually. # CSRF validation can be disabled globally (e.g. in unit tests), so ensure that # `WTF_CSRF_ENABLED` is enabled before. if current_app.config['WTF_CSRF_ENABLED']: csrf.validate_csrf(request.form.get('csrf_token')) fav = UserFavoriteOffice.query.filter_by(office_siret=siret, user_id=current_user.id).first() if not fav: abort(404) fav.delete() message = u'"%s - %s" a été supprimé de vos favoris !' % (fav.office.name, fav.office.city) flash(message, 'success') next_url = request.form.get('next') if next_url and is_safe_url(next_url): return redirect(urllib.unquote(next_url)) return redirect(url_for('user.favorites_list'))
def favorites_add(siret): """ Add an office to the favorites of a user. """ # Since we are not using a FlaskForm but a hidden input with the token in the # form, CSRF validation has to be done manually. # CSRF validation can be disabled globally (e.g. in unit tests), so ensure that # `WTF_CSRF_ENABLED` is enabled before. if current_app.config['WTF_CSRF_ENABLED']: csrf.validate_csrf(request.form.get('csrf_token')) office = Office.query.filter_by(siret=siret).first() if not office: abort(404) UserFavoriteOffice.get_or_create(user=current_user, office=office) message = u'"%s - %s" a été ajouté à vos favoris !' % (office.name, office.city) flash(Markup(message), 'success') next_url = request.form.get('next') if next_url and is_safe_url(next_url): return redirect(urllib.unquote(next_url)) return redirect(url_for('user.favorites_list'))
def multi_upload(): form = MultiUploadForm() if request.method == 'POST': filenames = [] # check csrf token try: validate_csrf(form.csrf_token.data) except ValidationError: flash('CSRF token error.') return redirect(url_for('multi_upload')) photos = request.files.getlist('photo') # check if user has selected files. If not, the browser # will submit an empty file part without filename if not photos[0].filename: flash('No selected file.') return redirect(url_for('multi_upload')) for f in photos: # check the file extension if f and allowed_file(f.filename): filename = random_filename(f.filename) f.save(os.path.join(app.config['UPLOAD_PATH'], filename)) filenames.append(filename) else: flash('Invalid file type.') return redirect(url_for('multi_upload')) flash('Upload success.') session['filenames'] = filenames return redirect(url_for('show_images')) return render_template('upload.html', form=form)
def get_data(): payload = request.get_json() if not payload: raise Exception("No payload provided") page = int(payload['page']) or 1 num_rows = int(payload['num_rows']) or 10 csrf_token = request.headers.get('X-CSRFToken') validate_csrf(csrf_token) conn = sqlite3.connect('data.db') total = int( pd.read_sql_query('select count(*) from data', conn).iloc[0][0]) offset = (page - 1) * num_rows df = pd.read_sql_query('select * from data limit (?), (?)', conn, params=( offset, num_rows, )) df = df[df.columns[1:].tolist()] res = dict(total=total, columns=df.columns.tolist(), page=page, pagination=[5, 10, 20], num_rows=num_rows, data=df.to_dict(orient="records")) return Response(json.dumps(res), mimetype="application/json")
def check_csrf(): """Verifies one of the following is true, or aborts with 400. a) the request includes a valid CSRF token b) the origin is explicitly allowed c) the request includes a valid internal token """ if request.method in ['OPTIONS', 'GET']: return try: validate_csrf(request.headers.get('X-CSRFToken')) return except ValidationError: pass if request.headers.get('origin') in ADDITIONAL_ALLOWED_ORIGINS: return if request.path in csrf_exempt_paths: return try: validate_internal_request(request) return except InvalidInternalToken: pass abort(400, 'Invalid CSRF token.')
def check_csrf(): has_auth = "Authorization" in flask.request.headers no_username = not flask.session.get("username") if has_auth or no_username: return if not config.get("ENABLE_CSRF_PROTECTION", True): return if flask.request.method != "GET": try: csrf_header = flask.request.headers.get("x-csrf-token") csrf_formfield = flask.request.form.get("csrf_token") # validate_csrf checks the input (a signed token) against the raw # token stored in session["csrf_token"]. # (session["csrf_token"] is managed by flask-wtf.) # To pass CSRF check, there must exist EITHER an x-csrf-token header # OR a csrf_token form field that matches the token in the session. assert (csrf_header and validate_csrf(csrf_header) is None or csrf_formfield and validate_csrf(csrf_formfield) is None) referer = flask.request.headers.get("referer") assert referer, "Referer header missing" logger.debug("HTTP REFERER " + str(referer)) except Exception as e: raise UserError( "CSRF verification failed: {}. Request aborted".format(e))
def login_callback(): code = flask.request.args["code"] state = flask.request.args["state"] # Avoid CSRF attacks validate_csrf(state) discharged_token = candid.discharge_token(code) candid_macaroon = candid.discharge_macaroon( flask.session["publisher-macaroon"], discharged_token) # Store bakery authentication flask.session["macaroons"] = candid.get_serialized_bakery_macaroon( flask.session["publisher-macaroon"], candid_macaroon) try: publisher = publisher_api.whoami(flask.session) except StoreApiResponseErrorList as api_response_error_list: return _handle_error_list(api_response_error_list.errors) except (StoreApiError, ApiError) as api_error: return _handle_error(api_error) # whoami is the only Dashboard API endpoint # that support Candid. return publisher
def multi(): form = MultiUploadPhoto() if request.method == "POST": filenames = [] #验证CSRF令牌 try: validate_csrf(form.csrf_token.data) except: flash('CSRF token error') return redirect(url_for('multi')) #检查文件是否存在 if 'photo' not in request.files: flash("this field is required") redirect(url_for('multi')) for f in request.files.getlist('photo'): # 检查文件类型 if f and allowed_file(f.filename): filename = random_filename(f.filename) f.save(os.path.join(app.config['UPLOAD_PATH'], filename)) filenames.append(filename) else: flash("Invalid file type") return redirect(url_for('multi')) flash("Upload success") flash(filenames) session['photonames'] = filenames flash(session["photonames"]) flash("show start") return redirect(url_for('showphoto')) return render_template('uploadphoto.html', form=form)
def login_callback(): code = flask.request.args["code"] state = flask.request.args["state"] # Avoid CSRF attacks validate_csrf(state) discharged_token = candid.discharge_token(code) candid_macaroon = candid.discharge_macaroon( flask.session["publisher-macaroon"], discharged_token ) # Store bakery authentication flask.session["publisher-auth"] = candid.get_serialized_bakery_macaroon( flask.session["publisher-macaroon"], candid_macaroon ) flask.session["publisher"] = publisher_api.whoami( flask.session["publisher-auth"] ) return flask.redirect( flask.session.pop( "next_url", "/charms", ), 302, )
def favorites_add(siret: str, rome_code: Optional[str] = None): """ Add an office to the favorites of a user. """ # Since we are not using a FlaskForm but a hidden input with the token in the # form, CSRF validation has to be done manually. # CSRF validation can be disabled globally (e.g. in unit tests), so ensure that # `WTF_CSRF_ENABLED` is enabled before. if current_app.config['WTF_CSRF_ENABLED']: csrf.validate_csrf(request.form.get('csrf_token')) office = Office.query.filter_by(siret=siret).first() if not office: abort(404) UserFavoriteOffice.add_favorite(user=current_user, office=office, rome_code=rome_code) message = '"%s - %s" a été ajouté à vos favoris !' % (office.name, office.city) flash(Markup(message), 'success') activity.log('ajout-favori', siret=siret) return get_redirect_after_favorite_operation()
def bulk_create(self, workspace_name): try: validate_csrf(flask.request.form.get('csrf_token')) except wtforms.ValidationError: flask.abort(403) def parse_hosts(list_string): items = re.findall(r"([.a-zA-Z0-9_-]+)", list_string) return items workspace = self._get_workspace(workspace_name) logger.info("Create hosts from CSV") if 'file' not in flask.request.files: abort(400, "Missing File in request") hosts_file = flask.request.files['file'] stream = StringIO(hosts_file.stream.read().decode("utf-8"), newline=None) FILE_HEADERS = {'description', 'hostnames', 'ip', 'os'} try: hosts_reader = csv.DictReader(stream) if set(hosts_reader.fieldnames) != FILE_HEADERS: logger.error("Missing Required headers in CSV (%s)", FILE_HEADERS) abort(400, "Missing Required headers in CSV (%s)" % FILE_HEADERS) hosts_created_count = 0 hosts_with_errors_count = 0 for host_dict in hosts_reader: try: hostnames = parse_hosts(host_dict.pop('hostnames')) other_fields = { 'owned': False, 'mac': u'00:00:00:00:00:00', 'default_gateway_ip': u'None' } host_dict.update(other_fields) host = super(HostsView, self)._perform_create(host_dict, workspace_name) host.workspace = workspace for name in hostnames: get_or_create(db.session, Hostname, name=name, host=host, workspace=host.workspace) db.session.commit() except Exception as e: logger.error("Error creating host (%s)", e) hosts_with_errors_count += 1 else: logger.debug("Host Created (%s)", host_dict) hosts_created_count += 1 return make_response( jsonify(hosts_created=hosts_created_count, hosts_with_errors=hosts_with_errors_count), 200) except Exception as e: logger.error("Error parsing hosts CSV (%s)", e) abort(400, "Error parsing hosts CSV (%s)" % e)
def multi_upload(): form = MultiUploadForm() if form.validate_on_submit(): filenames = [] # check csrf token try: validate_csrf(form.csrf_token.data) except ValidationError: flash('CSRF token error.') return redirect(url_for('multi_upload')) photos = form.photo.data if not photos[0].filename: flash('No selected fle.') return redirect(url_for('multi_upload')) for f in photos: if f and allowed_file(f.filename): filename = random_filename(f.filename) f.save(os.path.join(app.config['UPLOAD_PATH'], filename)) filenames.append(filename) else: flash('Invalid file type.') return redirect(url_for('multi_upload')) flash('Upload success') session['filenames'] = filenames return redirect(url_for('show_images')) return render_template('upload.html', form=form)
def multi_upload(): form = MultiUploadForm() if request.method == 'POST': filenames = [] # 验证CSRF令牌 try: validate_csrf(form.csrf_token.data) except: flash('CSRF token error.') return redirect(url_for('multi_upload')) # 检查文件是否存在 # 如果用户没有选择文件就提交表单则request.files为空,相当于FileRequired验证器 if 'photo' not in request.files: flash('This field is required.') return redirect(url_for('multi_upload')) # 传入字段的name属性值会返回包含所有上传文件对象的列表 for f in request.files.getlist('photo'): # 检查文件类型 # 相当于FileAllowed验证器 if f and allowed_file(f.filename): filename = random_filename(f.filename) f.save(os.path.join(app.config['UPLOAD_PATH'], filename)) filenames.append(filename) else: flash('Invalid file type.') return redirect(url_for('multi_upload')) flash('Upload success!') session['filenames'] = filenames return redirect(url_for('show_images')) return render_template('upload.html', form=form)
def admin_login(): if request.method == 'POST': form = LoginForm(request.form) validate_csrf(form.csrf_token) account = Account.query.filter_by(username=form.username.data, password=generate_hash_pass(form.username.data, form.password.data)).first() if account: login_user(account) account.set_status(online=True).save() return redirect(url_for('admin.index'), code=302) else: return json.dumps( { 'success': False } ), 401, {'ContentType':'application/json'} else: if current_user.is_authenticated and current_user.is_staff(): redirect(url_for('admin.index')) return json.dumps( { 'success': False } ), 302, {'ContentType':'application/json'} print('Rendering page') return render_template('admin/pages/login.html', form=LoginForm())
def file_upload(workspace=None): """ Upload a report file to Server and process that report with Faraday client plugins. """ logger.info("Importing new plugin report in server...") # Authorization code copy-pasted from server/api/base.py ws = Workspace.query.filter_by(name=workspace).first() if not ws or not ws.active: # Don't raise a 403 to prevent workspace name enumeration abort(404, "Workspace disabled: %s" % workspace) if 'file' not in request.files: abort(400) try: validate_csrf(request.form.get('csrf_token')) except ValidationError: abort(403) report_file = request.files['file'] if report_file: chars = string.ascii_uppercase + string.digits random_prefix = ''.join(random.choice(chars) for x in range(12)) # nosec raw_report_filename = '{0}_{1}'.format( random_prefix, secure_filename(report_file.filename)) try: file_path = os.path.join(CONST_FARADAY_HOME_PATH, 'uploaded_reports', raw_report_filename) with open(file_path, 'wb') as output: output.write(report_file.read()) except AttributeError: logger.warning( "Upload reports in WEB-UI not configurated, run Faraday client and try again..." ) abort( make_response( jsonify( message= "Upload reports not configurated: Run faraday client and start Faraday server again" ), 500)) else: logger.info("Get plugin for file: %s", file_path) plugin = report_analyzer.get_plugin(file_path) if not plugin: logger.info("Could not get plugin for file") abort( make_response(jsonify(message="Invalid report file"), 400)) else: logger.info("Plugin for file: %s Plugin: %s", file_path, plugin.id) REPORTS_QUEUE.put( (workspace, file_path, plugin.id, flask.g.user)) return make_response(jsonify(message="ok"), 200) else: abort(make_response(jsonify(message="Missing report file"), 400))
def delete_message(id): try: validate_csrf(request.form.get("csrf_token")) db.session.delete(Message.query.get(id)) db.session.commit() return redirect(url_for("index")) except ValidationError: return redirect(url_for("index"))
def validate_csrf_token(): post = request.method == "POST" patch = request.method == "PATCH" delete = request.method == "DELETE" if post or patch or delete: print("") csrf_token = request.headers.get("X-CSRFToken") validate_csrf(csrf_token)
def csrf_cookie_handler(response): """ Called at end of every request. Uses session to track state (set/clear) Ideally we just need to set this once - however by default Flask-WTF has a time-out on these tokens governed by `WTF_CSRF_TIME_LIMIT`. While we could set that to None - and OWASP implies this is fine - that might not be agreeable to everyone. So as a basic usability hack - we check if it is expired and re-generate so at least the user doesn't have to log out and back in (just refresh). We also support a `CSRF_COOKIE_REFRESH_EACH_REQUEST` analogous to Flask's `SESSION_REFRESH_EACH_REQUEST` It is of course removed on logout/session end. Other info on web suggests replacing on every POST and accepting up to 'age' ago. """ csrf_cookie = config_value("CSRF_COOKIE") if not csrf_cookie or not csrf_cookie["key"]: return response op = session.get("fs_cc", None) if not op: return response if op == "clear": response.delete_cookie( csrf_cookie["key"], path=csrf_cookie.get("path", "/"), domain=csrf_cookie.get("domain", None), ) session.pop("fs_cc") return response # Send a cookie if any of: # 1) CSRF_COOKIE_REFRESH_EACH_REQUEST is true # 2) fs_cc == "set" - this is on first login # 3) existing cookie has expired send = False if op == "set": send = True session["fs_cc"] = "sent" elif config_value("CSRF_COOKIE_REFRESH_EACH_REQUEST"): send = True elif current_app.config["WTF_CSRF_TIME_LIMIT"]: current_cookie = request.cookies.get(csrf_cookie["key"], None) if current_cookie: # Lets make sure it isn't expired if app doesn't set TIME_LIMIT to None. try: csrf.validate_csrf(current_cookie) except ValidationError: send = True if send: kwargs = {k: v for k, v in csrf_cookie.items()} kwargs.pop("key") kwargs["value"] = csrf.generate_csrf() response.set_cookie(csrf_cookie["key"], **kwargs) return response
def bulk_create(self): try: validate_csrf(request.form.get('csrf_token')) except wtforms.ValidationError: abort(403) logger.info("Create vulns template from CSV") if 'file' not in request.files: abort(400, "Missing File in request") vulns_file = request.files['file'] required_headers = {'name', 'exploitation'} io_wrapper = TextIOWrapper(vulns_file, encoding=request.content_encoding or "utf8") vulns_reader = csv.DictReader(io_wrapper, skipinitialspace=True) intersect_required = set( vulns_reader.fieldnames).intersection(required_headers) if intersect_required != required_headers: logger.error("Missing Required headers in CSV (%s)", required_headers - intersect_required) abort( 400, "Missing Required headers in CSV (%s)" % (required_headers - intersect_required)) custom_fields = [ custom_field_schema.field_name for custom_field_schema in db.session.query(CustomFieldsSchema).all() ] vulns_created_count = 0 vulns_with_errors_count = 0 schema = self.schema_class() for index, vuln_dict in enumerate(vulns_reader): vuln_dict['customfields'] = {} vuln_dict['impact'] = {} for key in vuln_dict.keys(): if key in custom_fields: vuln_dict['customfields'][key] = vuln_dict[key] vuln_dict['impact']['accountability'] = vuln_dict.get( 'accountability', False) vuln_dict['impact']['availability'] = vuln_dict.get( 'availability', False) vuln_dict['impact']['confidentiality'] = vuln_dict.get( 'confidentiality', False) vuln_dict['impact']['integrity'] = vuln_dict.get( 'integrity', False) try: vuln_schema = schema.load(vuln_dict) super(VulnerabilityTemplateView, self)._perform_create(vuln_schema) db.session.commit() except ValidationError as e: logger.error("Error creating vuln from line (%s): (%s)", str(index), e) vulns_with_errors_count += 1 else: vulns_created_count += 1 return make_response( jsonify(vulns_created=vulns_created_count, vulns_with_errors=vulns_with_errors_count), 200)
def delete(id): try: validate_csrf(request.form.get('csrf_token')) db.session.delete(Employee.query.get(id)) db.session.commit() except ValidationError: pass finally: return redirect(url_for('employees.index'))
def ajax_simple(field): if (request.method == "GET"): if validate_csrf(request.headers.get(CSRF_TOKEN_H, None)): return backend.ajax_get(request, field, timeout=60 * 30) elif (request.method == "POST"): if validate_csrf(request.headers.get(CSRF_TOKEN_H, None)): return backend.ajax_batch_post(request, field, timeout=60 * 30) else: abort(403)
def delete(id): try: validate_csrf(request.form.get("csrf_token")) tag = Tag.query.get(id) db.session.delete(tag) db.session.commit() return redirect(url_for("tags.index")) except ValidationError: return redirect(url_for("tags.index"))
def __init__(self, name, csrf_token="", skip_csrf_check=False): self.name = name if not skip_csrf_check: if not csrf_token or csrf_token is None: raise TypeError( '__init__() missing 1 required positional argument: \'csrf_token\'' ) validate_csrf(csrf_token) self.csrf_token = csrf_token
def test_csrf_custom_token_key(self): with self.app.test_request_context(): # Generate a normal and a custom CSRF token default_csrf_token = generate_csrf() custom_csrf_token = generate_csrf(token_key='oauth_state') # Verify they are different due to using different session keys self.assertNotEqual(default_csrf_token, custom_csrf_token) # However, the custom key can validate as well validate_csrf(custom_csrf_token, token_key='oauth_state')
def _csrf_protect(): # many things come from django.middleware.csrf if not app.config['WTF_CSRF_ENABLED']: return if request.method not in app.config['WTF_CSRF_METHODS']: return if self._exempt_views or self._exempt_blueprints: if not request.endpoint: return if request.endpoint in self._exempt_views: return if request.blueprint in self._exempt_blueprints: return if not validate_csrf(_get_csrf_token()): reason = 'CSRF token missing or incorrect.' return self._error_response(reason) if request.is_secure and app.config['WTF_CSRF_SSL_STRICT']: if not request.referrer: reason = 'Referrer checking failed - no Referrer.' return self._error_response(reason) good_referrer = 'https://%s/' % request.host if not same_origin(request.referrer, good_referrer): reason = 'Referrer checking failed - origin not match.' return self._error_response(reason) request.csrf_valid = True # mark this request is csrf valid
def ajax_statistics(): if validate_csrf(request.headers.get(CSRF_TOKEN_H, None)): return backend.ajax_get( request, app_conf_get("STATISTICS_API_ENDPOINT"), timeout=60 * 60 * 1) else: abort(403)
def logout(user): """Clear the session, and redirect to home.""" if not validate_csrf(request.args.get('token', '')): flash('Missing or incorrect CSRF token.') abort(400) session.clear() flash('You have been logged out.', 'info') return redirect(url_for('.home_page'), code=303)
def file_upload(workspace=None): """ Upload a report file to Server and process that report with Faraday client plugins. """ get_logger(__name__).debug("Importing new plugin report in server...") # Authorization code copy-pasted from server/api/base.py ws = Workspace.query.filter_by(name=workspace).one() if not (ws.active ): # Don't raise a 403 to prevent workspace name enumeration abort(404, "Workspace disabled: %s" % workspace) if 'file' not in request.files: abort(400) try: validate_csrf(request.form.get('csrf_token')) except ValidationError: abort(403) report_file = request.files['file'] if report_file.filename == '': abort(400) if report_file: chars = string.ascii_uppercase + string.digits random_prefix = ''.join(random.choice(chars) for x in range(12)) raw_report_filename = '{0}{1}'.format(random_prefix, secure_filename(report_file.filename)) try: file_path = os.path.join( CONF.getConfigPath(), 'uploaded_reports/{0}'.format(raw_report_filename)) except AttributeError: get_logger().warning( "Upload reports in WEB-UI not configurated, run Faraday client and try again...") abort(make_response(jsonify(message="Upload reports not configurated: Run faraday client and start Faraday server again"), 500)) with open(file_path, 'w') as output: output.write(report_file.read()) UPLOAD_REPORTS_QUEUE.put((workspace, file_path, request.cookies)) return make_response(jsonify(message="ok"), 200)
def ajax_count(collection=None): if validate_csrf(request.headers.get(CSRF_TOKEN_H, None)): return backend.ajax_count_get( request, app_conf_get("COUNT_API_ENDPOINT"), collection, timeout=60 * 60 ) else: abort(403)
def ajax_batch(): if validate_csrf(request.headers.get(CSRF_TOKEN_H, None)): if request.data: return backend.ajax_batch_post( request, app_conf_get("BATCH_API_ENDPOINT"), timeout=60 * 20) else: abort(400) else: abort(403)
def ajax_distinct(resource, field): if validate_csrf(request.headers.get(CSRF_TOKEN_H, None)): # Workaround because the backend uses /test/group/... if (resource == "group"): resource = "test/group" return backend.ajax_get( request, "/%s/distinct" % resource, doc_id=field, timeout=60 * 30) else: abort(403)
def ajax_version(): if validate_csrf(request.headers.get(CSRF_TOKEN_H, None)): # Cache the version for two days, hard for it to change that often. return backend.ajax_get( request, app_conf_get("VERSION_API_ENDPOINT"), timeout=60*60*24*2) else: abort(400)
def ajax_bisect_call(doc_id=None): if validate_csrf(request.headers.get(CSRF_TOKEN_H, None)): return backend.ajax_bisect( request, doc_id, app_conf_get("BISECT_API_ENDPOINT"), timeout=60 * 60 * 4 ) else: abort(403)
def ajax_job_logs(doc_id=None): if validate_csrf(request.headers.get(CSRF_TOKEN_H, None)): if doc_id: api_path = app_conf_get("JOB_ID_LOGS_ENPOINT") else: api_path = app_conf_get("JOB_LOGS_ENPOINT") return backend.ajax_logs( request, api_path, doc_id=doc_id, timeout=60 * 60 * 3) else: abort(403)
def process_callback(callback_uri): code = request.args.get('code') state = request.args.get('state') error = request.args.get('error') error_desc = request.args.get('error_description', '') if error: return {'error': 'GitHub auth canceled or failed with error: {}, ' 'description: {}'.format(error, error_desc)} if not validate_csrf(state): return {'error': 'csrf token mismatch in GitHub callback.'} r = requests.post('https://github.com/login/oauth/access_token', data={ 'client_id': current_app.config['GITHUB_CLIENT_ID'], 'client_secret': current_app.config['GITHUB_CLIENT_SECRET'], 'code': code, 'redirect_uri': callback_uri, 'state': state, }) payload = parse_qs(r.text) current_app.logger.debug('auth responses from GitHub %s', payload) access_token = payload['access_token'][0] r = requests.get('https://api.github.com/user', headers={ 'Authorization': 'token ' + access_token, }) user_info = r.json() user_id = str(user_info.get('id')) account = Account.query.filter_by( service='github', user_id=user_id).first() if not account: account = Account(service='github', user_id=user_id) db.session.add(account) account.username = user_info.get('login') account.token = access_token account.user_info = user_info account.update_sites([GitHub( url='https://github.com/{}'.format(account.username), # overloading "domain" to really mean "user's canonical url" domain='github.com/{}'.format(account.username), site_id=account.user_id)]) db.session.commit() util.set_authed(account.sites) return {'account': account}
def test_csrf_url_safe(self): with self.app.test_request_context(): # Generate a normal and URL safe CSRF token default_csrf_token = generate_csrf() url_safe_csrf_token = generate_csrf(url_safe=True) # Verify they are not the same and the URL one is truly URL safe assert default_csrf_token != url_safe_csrf_token assert '#' not in url_safe_csrf_token assert re.match(r'^[a-f0-9]+--[a-f0-9]+$', url_safe_csrf_token) # Verify we can validate our URL safe key assert validate_csrf(url_safe_csrf_token, url_safe=True)
def multi_upload(): form = MultiUploadForm() if request.method == 'POST': filenames = [] # check csrf token try: validate_csrf(form.csrf_token.data) except ValidationError: flash('CSRF token error.') return redirect(url_for('multi_upload')) # check if the post request has the file part if 'photo' not in request.files: flash('This field is required.') return redirect(url_for('multi_upload')) for f in request.files.getlist('photo'): # if user does not select file, browser also # submit a empty part without filename # if f.filename == '': # flash('No selected file.') # return redirect(url_for('multi_upload')) # check the file extension if f and allowed_file(f.filename): filename = random_filename(f.filename) f.save(os.path.join( app.config['UPLOAD_PATH'], filename )) filenames.append(filename) else: flash('Invalid file type.') return redirect(url_for('multi_upload')) flash('Upload success.') session['filenames'] = filenames return redirect(url_for('show_images')) return render_template('upload.html', form=form)
def votepage(election_id): if request.method == 'GET': if db.elections.find({'_id': ObjectId(election_id), 'voters': session.get('email_address', None)}).count() > 0: flash(u'Usted ya votó en ésta elección') return redirect(url_for('index')) selected_election = db.elections.find_one({ '_id': ObjectId(election_id), 'selectedCampus': session.get('campus', None) }, projection=['date_from', 'date_until', 'reason', 'electionOptions'],) if selected_election is None: abort(404) else: return render_template('elections/vote.html', election=selected_election) elif request.method == 'POST' and request.is_xhr: if db.elections.find({'_id': ObjectId(election_id), 'voters': session.get('email_address', None)}).count() > 0: return u'Ya votó en dicha elección', 403 if not csrf.validate_csrf(request.headers['X-CSRF-Token'], None): return u'Falta token CSRF', 401 else: vote = request.get_json() election_options = db.elections.find_one({ '_id': ObjectId(election_id), 'electionOptions.name': unicode(vote.get('selectedOption', None)), 'selectedCampus': session.get('campus', None) }, projection=['electionOptions.name']) if election_options is None: return u'La opción para la votación no existe o no existe la votación', 404 db.elections.update_one({'_id': ObjectId(election_id)}, { '$inc': {'totalVoters': 1}, '$push': { 'voters': session.get('email_address', None), 'votes': { 'election': vote['selectedOption'], 'date': datetime.now() } } }, upsert=True ) return u'Exito', 200 else: return u'No se puede procesar respuesta', 405
def _check_user_permission(required_tokens, user): if "CSRF" not in request.headers: return False if not csrf.validate_csrf(request.headers.get("CSRF")): return False for token in required_tokens: if not user.has_permission(access_tokens[token]['permission']): return False request.api_user_method = "browser_session" request.api_user = current_user request.api_user_name = current_user.name return True
def ajax_compare(doc_id, api): if validate_csrf(request.headers.get(CSRF_TOKEN_H, None)): api_path = app_conf_get(api) if request.method == "GET": return backend.ajax_get( request, api_path, doc_id=doc_id, timeout=60 * 60 * 2) elif any([request.method == "POST", request.method == "OPTIONS"]): if request.data: return backend.ajax_batch_post( request, api_path, timeout=60 * 60 * 2) else: abort(400) else: abort(405) else: abort(403)
def delete_account(): sent_csrf_token = request.args.get("csrf_token") if sent_csrf_token != None: sent_csrf_token = sent_csrf_token.replace("-", "#") if not validate_csrf(sent_csrf_token): return csrf_error() username = session.get("username") if username != None: Bill.delete().where(Bill.creator == username).execute() QRCode.delete().where(QRCode.creator == username).execute() User.delete().where(User.username == username).execute() logout_user() return render_template( "generic.html", message=""" Your account and all associated bills have been deleted. You may recreate your account by simply logging back in. """, ) else: return must_be_logged_in()
def process_callback(redirect_uri): code = request.args.get('code') error = request.args.get('error') if error: return {'error': 'Blogger authorization canceled or ' 'failed with error: {}' .format(error)} if not validate_csrf(request.args.get('state')): return {'error': 'csrf token mismatch in blogger callback.'} r = requests.post(API_TOKEN_URL, data={ 'code': code, 'client_id': current_app.config['GOOGLE_CLIENT_ID'], 'client_secret': current_app.config['GOOGLE_CLIENT_SECRET'], 'redirect_uri': redirect_uri, 'grant_type': 'authorization_code', }) if util.check_request_failed(r): return {'error': 'failed to validate access token'} current_app.logger.info('Got Blogger access token response: %s', r.text) payload = r.json() access_token = payload.get('access_token') expires_in = payload.get('expires_in') refresh_token = payload.get('refresh_token') if expires_in: expiry = datetime.datetime.utcnow() + datetime.timedelta( seconds=int(expires_in)) else: expiry = None current_app.logger.info( 'Got Blogger access token: %s. expiry: %s. refresh token: %s', access_token, expiry, refresh_token) r = requests.get(API_SELF_URL, headers={ 'Authorization': 'Bearer ' + access_token, }) if util.check_request_failed(r): return {'error': 'failed to fetch {}'.format(API_SELF_URL)} payload = r.json() username = user_id = payload.get('id') # find or create the account account = Account.lookup_by_user_id(SERVICE_NAME, user_id) if not account: account = Account(service=SERVICE_NAME, user_id=user_id) db.session.add(account) account.username = username account.user_info = payload account.token = access_token account.refresh_token = refresh_token account.expiry = expiry r = requests.get(API_BLOGS_URL, headers={ 'Authorization': 'Bearer ' + account.token, }) if util.check_request_failed(r): return redirect(url_for('views.index')) payload = r.json() blogs = payload.get('items', []) # find or create the sites sites = [] for blog in blogs: sites.append(Blogger( url=blog.get('url'), domain=util.domain_for_url(blog.get('url')), site_id=blog.get('id'), site_info=blog)) account.update_sites(sites) db.session.commit() util.set_authed(account.sites) return {'account': account}
def test_validate_csrf(self): with self.app.test_request_context(): self.assertRaises(ValidationError, validate_csrf, None) self.assertRaises(ValidationError, validate_csrf, 'invalid') validate_csrf(generate_csrf())
def ajax_distinct(resource, field): if validate_csrf(request.headers.get(CSRF_TOKEN_H, None)): return backend.ajax_get( request, "/%s/distinct" % resource, doc_id=field, timeout=60*30) else: abort(403)
def ajax_get(api): if validate_csrf(request.headers.get(CSRF_TOKEN_H, None)): return backend.ajax_get(request, app_conf_get(api), timeout=60 * 20) else: abort(403)
def ajax_boot_regressions(): if validate_csrf(request.headers.get(CSRF_TOKEN_H, None)): return backend.ajax_get( request, app_conf_get("BOOT_REGRESSIONS_API_ENDPOINT")) else: abort(403)
def handle_ajax_get(req, endpoint, timeout=None): if validate_csrf(req.headers.get(CSRF_TOKEN_H, None)): return backend.ajax_get(req, endpoint, timeout=timeout) else: abort(403)
def test_validate_csrf(self): with self.app.test_request_context(): assert not validate_csrf('ff##dd') csrf_token = generate_csrf() assert validate_csrf(csrf_token)
def test_validate_not_expiring_csrf(self): with self.app.test_request_context(): csrf_token = generate_csrf(time_limit=False) assert validate_csrf(csrf_token, time_limit=False)
def ajax_boot(): if validate_csrf(request.headers.get(CSRF_TOKEN_H, None)): return backend.ajax_get(request, app_conf_get("BOOT_API_ENDPOINT")) else: abort(400)
def process_callback(callback_uri): code = request.args.get('code') state = request.args.get('state') error = request.args.get('error') error_desc = request.args.get('error_description', '') if error: return {'error': 'Facebook auth canceled or failed with error: {}, ' 'description: {}'.format(error, error_desc)} if not validate_csrf(state): return {'error': 'csrf token mismatch in Facebook callback.'} r = requests.get('https://graph.facebook.com/oauth/access_token', params={ 'client_id': current_app.config['FACEBOOK_CLIENT_ID'], 'client_secret': current_app.config['FACEBOOK_CLIENT_SECRET'], 'redirect_uri': callback_uri, 'code': code, 'scope': PERMISSION_SCOPES, }) if r.status_code // 100 != 2: error_obj = r.json() error = error_obj.get('error') error_desc = error_obj.get('error_description') return {'error': 'Error ({}) requesting access token: {}, ' 'description: {}' .format(r.status_code, error, error_desc)} payload = json.loads(r.text) current_app.logger.debug('auth responses from Facebook %s', payload) current_app.logger.debug('raw response %s', r.text) access_token = payload['access_token'] r = requests.get('https://graph.facebook.com/v2.5/me', params={ 'access_token': access_token, 'fields': 'id,name,picture', }) if r.status_code // 100 != 2: error_obj = r.json() error = error_obj.get('error') error_desc = error_obj.get('error_description') return {'error': 'Error ({}) requesting authed user info: {}, ' 'description: {}' .format(r.status_code, error, error_desc)} user_info = r.json() current_app.logger.debug('authed user info from Facebook %s', user_info) user_id = user_info.get('id') account = Account.query.filter_by( service='facebook', user_id=user_id).first() if not account: account = Account(service='facebook', user_id=user_id, username=user_id) db.session.add(account) account.user_info = user_info account.token = access_token account.update_sites([Facebook( url='https://www.facebook.com/{}'.format(account.user_id), # overloading "domain" to really mean "user's canonical url" domain='facebook.com/{}'.format(account.user_id), site_id=account.user_id)]) db.session.commit() util.set_authed(account.sites) return {'account': account}