En aquest exercici, implementarem controls de seguretat en una aplicació web per mitigar diverses vulnerabilitats comunes. L'objectiu és aplicar els coneixements adquirits en els mòduls anteriors per assegurar una aplicació web fictícia.
Objectius de l'Exercici
- Identificar vulnerabilitats en el codi existent.
- Implementar controls de seguretat per mitigar aquestes vulnerabilitats.
- Verificar que les vulnerabilitats han estat corregides.
Escenari
Disposem d'una aplicació web fictícia que permet als usuaris registrar-se, iniciar sessió i veure el seu perfil. Aquesta aplicació conté diverses vulnerabilitats que necessiten ser corregides.
Codi Inicial
A continuació, es mostra el codi inicial de l'aplicació web:
# app.py from flask import Flask, request, render_template_string app = Flask(__name__) users = {} @app.route('/register', methods=['POST']) def register(): username = request.form['username'] password = request.form['password'] users[username] = password return "User registered successfully!" @app.route('/login', methods=['POST']) def login(): username = request.form['username'] password = request.form['password'] if username in users and users[username] == password: return f"Welcome, {username}!" else: return "Invalid credentials!" @app.route('/profile/<username>') def profile(username): if username in users: return render_template_string(f"<h1>Profile of {username}</h1>") else: return "User not found!" if __name__ == '__main__': app.run(debug=True)
Vulnerabilitats Identificades
- Injecció SQL: No hi ha cap vulnerabilitat d'injecció SQL en aquest codi, però és important tenir-ho en compte en aplicacions més complexes.
- Pèrdua d'Autenticació: No es fa servir cap mecanisme d'autenticació robust.
- Exposició de Dades Sensibles: Les contrasenyes es guarden en text pla.
- Cross-Site Scripting (XSS): El perfil de l'usuari es mostra sense cap tipus de sanitització.
Tasques
- Implementar Hashing de Contrasenyes
Per evitar l'exposició de dades sensibles, hem de guardar les contrasenyes de manera segura utilitzant hashing.
# app.py (modificat) from flask import Flask, request, render_template_string from werkzeug.security import generate_password_hash, check_password_hash app = Flask(__name__) users = {} @app.route('/register', methods=['POST']) def register(): username = request.form['username'] password = request.form['password'] hashed_password = generate_password_hash(password) users[username] = hashed_password return "User registered successfully!" @app.route('/login', methods=['POST']) def login(): username = request.form['username'] password = request.form['password'] if username in users and check_password_hash(users[username], password): return f"Welcome, {username}!" else: return "Invalid credentials!" @app.route('/profile/<username>') def profile(username): if username in users: return render_template_string(f"<h1>Profile of {username}</h1>") else: return "User not found!" if __name__ == '__main__': app.run(debug=True)
- Implementar Autenticació Basada en Sessions
Per millorar la seguretat de l'autenticació, implementarem sessions.
# app.py (modificat) from flask import Flask, request, render_template_string, session, redirect, url_for from werkzeug.security import generate_password_hash, check_password_hash app = Flask(__name__) app.secret_key = 'supersecretkey' users = {} @app.route('/register', methods=['POST']) def register(): username = request.form['username'] password = request.form['password'] hashed_password = generate_password_hash(password) users[username] = hashed_password return "User registered successfully!" @app.route('/login', methods=['POST']) def login(): username = request.form['username'] password = request.form['password'] if username in users and check_password_hash(users[username], password): session['username'] = username return redirect(url_for('profile', username=username)) else: return "Invalid credentials!" @app.route('/profile/<username>') def profile(username): if 'username' in session and session['username'] == username: return render_template_string(f"<h1>Profile of {username}</h1>") else: return "User not found or not logged in!" @app.route('/logout') def logout(): session.pop('username', None) return "Logged out successfully!" if __name__ == '__main__': app.run(debug=True)
- Prevenir Cross-Site Scripting (XSS)
Per prevenir XSS, utilitzarem sanitització de dades.
# app.py (modificat) from flask import Flask, request, render_template_string, session, redirect, url_for, escape from werkzeug.security import generate_password_hash, check_password_hash app = Flask(__name__) app.secret_key = 'supersecretkey' users = {} @app.route('/register', methods=['POST']) def register(): username = request.form['username'] password = request.form['password'] hashed_password = generate_password_hash(password) users[username] = hashed_password return "User registered successfully!" @app.route('/login', methods=['POST']) def login(): username = request.form['username'] password = request.form['password'] if username in users and check_password_hash(users[username], password): session['username'] = username return redirect(url_for('profile', username=username)) else: return "Invalid credentials!" @app.route('/profile/<username>') def profile(username): if 'username' in session and session['username'] == username: return render_template_string(f"<h1>Profile of {escape(username)}</h1>") else: return "User not found or not logged in!" @app.route('/logout') def logout(): session.pop('username', None) return "Logged out successfully!" if __name__ == '__main__': app.run(debug=True)
Verificació
- Verificar Hashing de Contrasenyes
- Registra un nou usuari i comprova que la contrasenya es guarda de manera hashada.
- Verificar Autenticació Basada en Sessions
- Inicia sessió amb un usuari registrat i comprova que pots accedir al perfil.
- Tanca la sessió i comprova que no pots accedir al perfil sense iniciar sessió.
- Verificar Preveniment de XSS
- Intenta injectar codi maliciós en el nom d'usuari i comprova que es mostra de manera segura.
Conclusió
En aquest exercici, hem implementat controls de seguretat essencials per protegir una aplicació web contra vulnerabilitats comunes. Hem après a utilitzar hashing per a contrasenyes, sessions per a autenticació i sanitització per prevenir XSS. Aquests són passos fonamentals per assegurar qualsevol aplicació web.
Curs d'OWASP: Directrius i Estàndards per a la Seguretat en Aplicacions Web
Mòdul 1: Introducció a OWASP
Mòdul 2: Principals Projectes d'OWASP
- OWASP Top Ten
- OWASP ASVS (Application Security Verification Standard)
- OWASP SAMM (Software Assurance Maturity Model)
- OWASP ZAP (Zed Attack Proxy)
Mòdul 3: OWASP Top Ten
- A1: Injecció
- A2: Pèrdua d'Autenticació
- A3: Exposició de Dades Sensibles
- A4: Entitats Externes XML (XXE)
- A5: Control d'Accés Trencat
- A6: Configuració Incorrecta de Seguretat
- A7: Cross-Site Scripting (XSS)
- A8: Deserialització Insegura
- A9: Ús de Components amb Vulnerabilitats Conegudes
- A10: Registre i Monitoratge Insuficients
Mòdul 4: OWASP ASVS (Application Security Verification Standard)
Mòdul 5: OWASP SAMM (Software Assurance Maturity Model)
Mòdul 6: OWASP ZAP (Zed Attack Proxy)
- Introducció a ZAP
- Instal·lació i Configuració
- Escaneig de Vulnerabilitats
- Automatització de Proves de Seguretat
Mòdul 7: Bones Pràctiques i Recomanacions
- Cicle de Vida de Desenvolupament Segur (SDLC)
- Integració de Seguretat en DevOps
- Capacitació i Sensibilització en Seguretat
- Eines i Recursos Addicionals
Mòdul 8: Exercicis Pràctics i Casos d'Estudi
- Exercici 1: Identificació de Vulnerabilitats
- Exercici 2: Implementació de Controls de Seguretat
- Cas d'Estudi 1: Anàlisi d'un Incident de Seguretat
- Cas d'Estudi 2: Millora de la Seguretat en una Aplicació Web