From 46b05e9fab44932008cc4ee8cdc98060dd2f6ff3 Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 11 Jun 2024 15:21:56 -0300 Subject: [PATCH 1/2] =?UTF-8?q?adicionando=20descri=C3=A7=C3=A3o=20de=20lo?= =?UTF-8?q?g?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../a9/games-irados/app/requirements.txt | 1 + .../a9/games-irados/app/routes.py | 70 +++++++++++++------ owasp-top10-2021-apps/a9/games-irados/poc.txt | 10 +++ 3 files changed, 61 insertions(+), 20 deletions(-) create mode 100644 owasp-top10-2021-apps/a9/games-irados/poc.txt diff --git a/owasp-top10-2021-apps/a9/games-irados/app/requirements.txt b/owasp-top10-2021-apps/a9/games-irados/app/requirements.txt index 712b5fad3..1984b86e8 100644 --- a/owasp-top10-2021-apps/a9/games-irados/app/requirements.txt +++ b/owasp-top10-2021-apps/a9/games-irados/app/requirements.txt @@ -10,3 +10,4 @@ mysqlclient==1.3.13 six==1.11.0 visitor==0.1.3 Werkzeug==0.14.1 +pytz==2024.1 diff --git a/owasp-top10-2021-apps/a9/games-irados/app/routes.py b/owasp-top10-2021-apps/a9/games-irados/app/routes.py index eddd6a999..c49f68275 100644 --- a/owasp-top10-2021-apps/a9/games-irados/app/routes.py +++ b/owasp-top10-2021-apps/a9/games-irados/app/routes.py @@ -1,15 +1,11 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -from functools import wraps import uuid -import datetime +from functools import wraps from flask import ( Flask, render_template, request, redirect, flash, - make_response, session ) from util.init_db import init_db @@ -20,8 +16,8 @@ import logging import os + from flask_cors import CORS, cross_origin -from model.db import DataBase app = Flask(__name__) bootstrap = Bootstrap(app) @@ -29,6 +25,30 @@ app.config.from_pyfile('config.py') +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) + + +logger.removeHandler(default_handler) + + +formatter = logging.Formatter('%(levelname)s: %(message)s') +new_handler = logging.StreamHandler() +new_handler.setFormatter(formatter) +logger.addHandler(new_handler) + +# Configure werkzeug logging +werkzeug_logger = logging.getLogger('werkzeug') +werkzeug_logger.setLevel(logging.INFO) + +werkzeug_handler = logging.StreamHandler() +werkzeug_formatter = logging.Formatter('%(message)s') +werkzeug_handler.setFormatter(werkzeug_formatter) +werkzeug_logger.addHandler(werkzeug_handler) + +# Remove the default werkzeug handler to avoid duplicate logs +werkzeug_logger.removeHandler(logging.getLogger('werkzeug').handlers[0]) + def generate_csrf_token(): ''' Generate csrf token and store it in session @@ -37,7 +57,6 @@ def generate_csrf_token(): session['_csrf_token'] = str(uuid.uuid4()) return session.get('_csrf_token') - app.jinja_env.globals['csrf_token'] = generate_csrf_token @app.before_request @@ -55,7 +74,7 @@ def login_required(f): @wraps(f) def decorated_function(*args, **kwargs): if 'username' not in session: - flash('oops, session expired', "danger") + flash('Oops, session expired', "danger") return redirect('/login') return f(*args, **kwargs) return decorated_function @@ -76,10 +95,12 @@ def login(): username = request.form.get('username').encode('utf-8') psw = Password(request.form.get('password').encode('utf-8')) user_password, success = database.get_user_password(username) - if not success or user_password == None or not psw.validate_password(str(user_password[0])): - flash("Usuario ou senha incorretos", "danger") + if not success or user_password is None or not psw.validate_password(str(user_password[0])): + logger.info("login inválido!") # Adicionando comentário para login inválido + flash("Usuário ou senha incorretos", "danger") return render_template('login.html') session['username'] = username + logger.info("login efetuado com sucesso!") # Adicionando comentário para login efetuado com sucesso return redirect('/home') else: return render_template('login.html') @@ -96,13 +117,13 @@ def newuser(): hashed_psw = psw.get_hashed_password() message, success = database.insert_user(username, hashed_psw) if success == 1: - flash("Novo usuario adicionado!", "primary") + flash("Novo usuário adicionado!", "primary") return redirect('/login') else: flash(message, "danger") return redirect('/register') - flash("Passwords must be the same!", "danger") + flash("As senhas devem ser iguais!", "danger") return redirect('/register') else: return render_template('register.html') @@ -117,15 +138,24 @@ def home(): def cupom(): if request.method == 'POST': coupon = request.form.get('coupon') - rows, success = database.get_game_coupon(coupon, session.get('username')) - if not success or rows == None or rows == 0: - flash("Cupom invalido", "danger") + username = session.get('username') + if coupon: + coupon_display = '****' # Oculta o valor do cupom + else: + coupon_display = coupon + + logger.info(f'User: "id do usuário" attempted to redeem coupon: {coupon_display} - Result: Invalid') + + rows, success = database.get_game_coupon(coupon, username) + if not success or rows is None or rows == 0: + flash("Cupom inválido", "danger") return render_template('coupon.html') - game, success = database.get_game(coupon, session.get('username')) - if not success or game == None: - flash("Cupom invalido", "danger") + game, success = database.get_game(coupon, username) + if not success or game is None: + flash("Cupom inválido", "danger") return render_template('coupon.html') - flash("Voce ganhou {}".format(game[0]), "primary") + logger.info(f'User: "id do usuário" redeemed coupon: {coupon_display} - Result: Valid') + flash("Você ganhou {}".format(game[0]), "primary") return render_template('coupon.html') else: return render_template('coupon.html') @@ -137,4 +167,4 @@ def cupom(): dbName = os.environ.get('MYSQL_DB') database = DataBase(dbEndpoint, dbUser, dbPassword, dbName) init_db(database) - app.run(host='0.0.0.0',port=10010, debug=True) + app.run(host='0.0.0.0', port=10010, debug=True) diff --git a/owasp-top10-2021-apps/a9/games-irados/poc.txt b/owasp-top10-2021-apps/a9/games-irados/poc.txt new file mode 100644 index 000000000..92a0820c4 --- /dev/null +++ b/owasp-top10-2021-apps/a9/games-irados/poc.txt @@ -0,0 +1,10 @@ +admin +password +123 +qweasd +1qaz +123456789 +flamengo +zxc +asd123qwe +YOURVALIDPASSWORD \ No newline at end of file From 41078aebbea26fee7ab6e2d5cdad888b5633c6cb Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 12 Jun 2024 01:39:59 -0300 Subject: [PATCH 2/2] =?UTF-8?q?Adicionando=20altera=C3=A7=C3=B5es=20no=20l?= =?UTF-8?q?og?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../a9/games-irados/app/routes.py | 55 +++++++++++-------- 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/owasp-top10-2021-apps/a9/games-irados/app/routes.py b/owasp-top10-2021-apps/a9/games-irados/app/routes.py index c49f68275..3dad003ae 100644 --- a/owasp-top10-2021-apps/a9/games-irados/app/routes.py +++ b/owasp-top10-2021-apps/a9/games-irados/app/routes.py @@ -15,7 +15,7 @@ from model.db import DataBase import logging import os - +from datetime import datetime from flask_cors import CORS, cross_origin @@ -24,35 +24,45 @@ app.config.from_pyfile('config.py') +# Remove default logging configuration +logging.getLogger().setLevel(logging.NOTSET) +app.logger.handlers = [] -logging.basicConfig(level=logging.INFO) +# Configure logger for __main__ logger = logging.getLogger(__name__) - - -logger.removeHandler(default_handler) - - formatter = logging.Formatter('%(levelname)s: %(message)s') -new_handler = logging.StreamHandler() -new_handler.setFormatter(formatter) -logger.addHandler(new_handler) +stream_handler = logging.StreamHandler() +stream_handler.setFormatter(formatter) +logger.addHandler(stream_handler) +logger.setLevel(logging.INFO) -# Configure werkzeug logging +# Configure werkzeug logger werkzeug_logger = logging.getLogger('werkzeug') werkzeug_logger.setLevel(logging.INFO) - werkzeug_handler = logging.StreamHandler() werkzeug_formatter = logging.Formatter('%(message)s') werkzeug_handler.setFormatter(werkzeug_formatter) werkzeug_logger.addHandler(werkzeug_handler) -# Remove the default werkzeug handler to avoid duplicate logs -werkzeug_logger.removeHandler(logging.getLogger('werkzeug').handlers[0]) +# Remove default werkzeug logger handler +if werkzeug_logger.hasHandlers(): + werkzeug_logger.handlers.clear() + +# Custom Request Logger +class RequestLogger(logging.LoggerAdapter): + def process(self, msg, kwargs): + request_info = request + ip = request_info.remote_addr + timestamp = datetime.now().strftime('%d/%b/%Y %H:%M:%S') + method = request_info.method + path = request_info.path + status_code = kwargs.pop('status_code', '-') + msg += f' - {ip} - - [{timestamp}] "{method} {path} HTTP/1.1" {status_code} -' + return msg, kwargs + +request_logger = RequestLogger(logger, {}) def generate_csrf_token(): - ''' - Generate csrf token and store it in session - ''' if '_csrf_token' not in session: session['_csrf_token'] = str(uuid.uuid4()) return session.get('_csrf_token') @@ -61,9 +71,6 @@ def generate_csrf_token(): @app.before_request def csrf_protect(): - ''' - CSRF PROTECION - ''' if request.method == "POST": token_csrf = session.get('_csrf_token') form_token = request.form.get('_csrf_token') @@ -96,11 +103,11 @@ def login(): psw = Password(request.form.get('password').encode('utf-8')) user_password, success = database.get_user_password(username) if not success or user_password is None or not psw.validate_password(str(user_password[0])): - logger.info("login inválido!") # Adicionando comentário para login inválido + request_logger.info("login inválido!", extra={'status_code': 200}) flash("Usuário ou senha incorretos", "danger") return render_template('login.html') session['username'] = username - logger.info("login efetuado com sucesso!") # Adicionando comentário para login efetuado com sucesso + request_logger.info("login efetuado com sucesso!", extra={'status_code': 302}) return redirect('/home') else: return render_template('login.html') @@ -144,7 +151,7 @@ def cupom(): else: coupon_display = coupon - logger.info(f'User: "id do usuário" attempted to redeem coupon: {coupon_display} - Result: Invalid') + request_logger.info(f'User: "id do usuário" attempted to redeem coupon: {coupon_display} - Result: Invalid', extra={'status_code': 200}) rows, success = database.get_game_coupon(coupon, username) if not success or rows is None or rows == 0: @@ -154,7 +161,7 @@ def cupom(): if not success or game is None: flash("Cupom inválido", "danger") return render_template('coupon.html') - logger.info(f'User: "id do usuário" redeemed coupon: {coupon_display} - Result: Valid') + request_logger.info(f'User: "id do usuário" redeemed coupon: {coupon_display} - Result: Valid', extra={'status_code': 200}) flash("Você ganhou {}".format(game[0]), "primary") return render_template('coupon.html') else: