definiciones Clave: Permite encriptar y desencriptar los datos TextoPlano: Informatión que quieres mantener en secreto Texto Cifrado: Información de forma encriptadada Algoritmo de cifrado: convierte texto plano a cifrado y viceversa
advanced Salt – Secuencia aleatoria que se añade a la password IV (initialization vector) – previene ataques de diccionario o mediante rainbow tables Derived Key – Fortalece la generación de claves para que los ataques de fuerza bruta tengan menos éxito.
Introducción a la criptografía Cifrado de césar Funciones hash(MD5,SHA) Cifrado simétrico(AES) Cifrado asímétrico(RSA) PBKDF2-Key derivation function
Hash passwords en DB Websites almacenan el hash de la password hashlib.sha256(‘password').hexdigest() >>'5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d15 42d8'
Cifrado asimétrico RSA 2 claves(pública y privada) Clave pública(Pk) encriptar Clave secreta(Sk) descifrar La clave pública se puede generar a partir de la clave secreta
Encriptación vs Firma EncriptaciónUsas su clave pública para enviar un mensaje y el destinatario usa su clave privada para leerlo. FirmaPara firmar usas tu clave privada, y el destinatario usa tu clave pública para verificar que la documento lo ha firmado quién dice ser.
PyCrypto PBKDF import Crypto.Random from Crypto.Protocol.KDF import PBKDF2 password = 'europython' iterations = 5000 key = '' salt = Crypto.Random.new().read(32) key = PBKDF2(password, salt, dkLen=32, count=iterations) print 'Random salt (in hex):' print salt.encode('hex') print 'PBKDF2-derived key (in hex) of password after %d iterations: ' % iterations print key.encode('hex') Random salt (in hex): 724138b9d987a04bf05d285db678824f9b7e2b1232229711c2e0e2e556a0c19a PBKDF2-derived key (in hex) of password after 5000 iterations: d725de7de88e27d16c9c4f224d4c87159735708419d1c949074962b48ce26900
PyCrypto RSA from Crypto.PublicKey import RSA def generate_RSA(bits=1024): #Generate an RSA keypair with an exponent of 65537 in PEM format #param: bits The key length in bits #Return secret key and public key new_key = RSA.generate(bits, e=65537) public_key = new_key.publickey().exportKey("PEM") secret_key = new_key.exportKey("PEM") return secret_key, public_key
Mejores prácticas Evitar usar algoritmos MD5 /SHA-1 Usar al menos SHA-2(256-512 bits) Uso de técnicas más avanzadas como Key Stretching Prevenir ataques de diccionario o fuerza bruta for i in xrange(iterations): m = hashlib.sha512() m.update(key + password + salt) key = m.digest() PBKDF
Seguridad en Django Configuración SSL del servidor Vulnerabilidad HeartBleed Uso de algoritmos de cifrado débiles Gestión de claves secretas Autorización / autenticación de usuarios Manejo de cookies del usuario
class PBKDF2PasswordHasher(BasePasswordHasher): """ Secure password hashing using the PBKDF2 algorithm (recommended) Configured to use PBKDF2 + HMAC + SHA256. The result is a 64 byte binary string. Iterations may be changed safely but you must rename the algorithm if you change SHA256. """ algorithm = "pbkdf2_sha256" iterations = 30000 digest = hashlib.sha256 def encode(self, password, salt, iterations=None): assert password is not None assert salt and '$' not in salt if not iterations: iterations = self.iterations hash = pbkdf2(password, salt, iterations, digest=self.digest) hash = base64.b64encode(hash).decode('ascii').strip() return "%s$%d$%s$%s" % (self.algorithm, iterations, salt, hash) https://github.com/django/django/blob/master/django/contrib/auth/hashers.py/ Almacenamiento de passwords
Mejores prácticas Usar HTTPS para conexiónes seguras SSL Habilitar HTTPS junto con un certificado propio Forzar HTTPS en todo el dominio Flags de seguridad para las cookies Django only send session cookies over HTTPS SESSION_COOKIE_SECURE = true CSRF_COOKIE_SECURE_true
Mejores prácticas Guardar de forma segura claves secretas y credenciales Establecer DEBUG=false en producción en settings.py Usar ALLOWED_HOSTS en producción y asignarle aquellos dominios de los cuales se tenga control Limitar accesos admin mediante IP filter ALLOWED_HOSTS =[*] ALLOWED_HOSTS =['.yourdomain.com']
SQL injection No confiar en los datos que envía el usuario Correcto filtrado de los parámetros Uso de cursores y bind parameter from django.db import connection def select_user(request): user = request.GET['username'] sql = "SELECT * FROM users WHERE username = %s" cursor = connection.cursor() cursor.execute(sql, [user])
Cross site Scripting(XSS) Permite a un atacante obtener información de la sesión del usuario Usar el sistema de plantillas de renderizado para escapar los valores que se pintan en las páginas HTML from django.shortcuts import render def render_page(request): user = request.GET['username'] return render(request, ‘page.html', {‘user’:user})