Seguridad en Java - LDC - Universidad Simón Bolívar

Anuncio
Seguridad en Java:
Permisos de Código
Autentificación,
Firma Digital y
Cifrado
Prof. Wílmer Pereira
USB / UCAB
Universidad Simón Bolívar
Prof. Wílmer Pereira
Especialización en Telematica
Principios de código seguro en Java
Mientras las aplicaciones sean locales la seguridad no es mayor problema ...
Sin embargo el desafio está en las aplicaciones que se instalan desde un servidor
remoto (por ejemplo los applets ...)
Java ofrece para ejecutar código remoto:
(1) Lenguaje fuertemente tipeado, sin permitir apuntadores
(2) Cargador de clases controlado y configurable.
(3) Comprobaciones automática de los .class (bytecodes)
(4) Administrador de seguridad y mecanismos de permisos.
(5) Autentificación y autorización.
(6) Firma de código.
(7) Manipulación de certificados digitales.
(8) Cifrado con algoritmos de clave simétrica y de pública.
Universidad Simón Bolívar
Prof. Wílmer Pereira
Especialización en Telematica
Modelo Cliente/Servidor
Máquina remota
Máquina local
Petición
Sockets
RMI
(interfaz)
Respuesta
Cliente
Sockets
RMI
(demonio)
Servidor
Todos los servicios sobre Internet funcionan bajo esta arquitectura
El medio de envío para petición/respuesta es la red
Un servidor debe poder manejar varios usuarios concurrentemente
Universidad Simón Bolívar
Prof. Wílmer Pereira
Especialización en Telematica
Páginas Web Dinámicas
(lado del servidor)
Máquina local
Browser
Petición
URL
Máquina remota
HTTP
Respuesta
Página HTML
Cliente
PHP
ASP
JSP
Base
de
Datos
Servidor
Una aplicación corre del lado del servidor
Construye una página Web con los datos extraídos de la BD
El browser sólo visualiza páginas HTML
Universidad Simón Bolívar
Prof. Wílmer Pereira
Especialización en Telematica
Página Web Dinámica
(lado del cliente)
Máquina local
Browser
javascript
applets
activeX
flash
Petición
URL
Respuesta
Página HTML
+
Aplicación
Cliente
Máquina remota
HTTP
Servidor
Una aplicación corre del lado del cliente
Construye una página Web ejecutando una aplicación que viajó desde
el servidor
El browser debe ser capaz de ejecutar aplicaciones (plug-ins)
Universidad Simón Bolívar
Prof. Wílmer Pereira
Especialización en Telematica
Seguridad del código movil
Las implementaciones más conocidas son:
Applets
ActiveX
Flash
Javascript ...
Applets: Propuesta de Java para ejecutar en JVM del
navegador. Inicialmente tenían todos los derechos
pero ... Ahora a partir de Java2 tienen tres restricciones
No pueden acceder a recursos locales
No puede correr ningun programa localmente
Sólo pueden conectarse con el servidor ...
ActiveX: Desarrollado de Microsoft sin ninguna restricción sólo
la que impone el conocimiento de quien es el creador
Esto se logra gracias a la firma de código y Authenticode
Javascript: lanzado al mercado por Netscape corre código del lado
cliente ... phishing usa una de sus funcionalidades para engañar ...
Universidad Simón Bolívar
Prof. Wílmer Pereira
Especialización en Telematica
(2) Seguridad con el cargador de clases
Cargan los .class (bytecodes) necesarios desde las librerías que se importan.
Normalmente el proceso es transparente salvo si se define un cargador de clases propio
Cargadores:
Arranque (rt.jar en C)
Extensión (todos los API según el CLASSPATH)
Aplicación (específicos del programa)
Los applets, servlets y fragmentos de RMI tiene cargadores
especiales
Para definir un cargador de clases propio basta con extender
de la clase ClassLoader y reescribir el método findClass
Universidad Simón Bolívar
Prof. Wílmer Pereira
Especialización en Telematica
(3) Verificación del bytecode
Comprobaciones de los .class pues pueden ser modificados con editores hexadecimales.
Siempre se realiza y sólo no se hace por solicitud expresa en la compilación
java -noverify Prueba
Algunas de las verificaciones:
Variables deben recibir valores iniciales
No se deben violar las reglas de acceso a datos y métodos privados
La pila de ejecución no debe desbordarse
Evita casting no autorizado ...
No se deberían saltar las verificaciones del bytecode y menos aún si
el código proviene de una máquina remota
Universidad Simón Bolívar
Prof. Wílmer Pereira
Especialización en Telematica
(4) Administrador de seguridad
y permisos
Comprueba ciertas propiedades de ejecución después de que se carga la clase y se
verifican los bytecode. Por defecto las aplicaciones locales no instalan
administrador de seguridad
Algunas de las comprobaciones se realizan sobre el hilo actual:
Si puede o no crear un cargador de clases
Si puede o no acceder a los archivos locales
Si puede o no abrir una conexión remota vía sockets
Si puede o no acceder al portapapeles …
Por ejemplo el método exit llama a checkExit para saber si puede aprobar
la solicitud. En caso contrario lanza una excepción: SecurityException
Instalar un administrador de seguridad específico es con setSecurityManager
de la clase System
Universidad Simón Bolívar
Prof. Wílmer Pereira
Especialización en Telematica
(4) Formato de permisos
Inicialmente se negaba a los applets el acceso de todos los recursos locales.
A partir de jdk1.1 si el applet estaba firmado se le daban todos los derechos.
Esta política de todo o nada se modificó con los archivos de permisos
Un permiso se implanta en el código con:
FilePermission p = new FilePermission(“/tmp/*”,”read,write”);
o en el archivo de permisos como:
permission java.io.FilePermission “/tmp/*” “read,write”;
La sintaxis completa de un archivo como miAplic.policy:
grant codeBase “http://www.horstmann.com/classes”
{
permission java.io.FilePermission “/tmp/*” “read,write”;
};
y se ejecuta habiendo obtenido el bytecode de miAplic.class:
java -Djava.security.policy=miAplic.policy miAplic
Universidad Simón Bolívar
Prof. Wílmer Pereira
Especialización en Telematica
(4) Archivos de permisos
Las ubicaciones de los archivos de permisos standards son:
El archivo java.policy del directorio principal de Java
El archivo .java.policy (oculto) situado en el directorio actual
Para que ejecute solamente el archivo de permisos se coloca ==
java -Djava.security.policy==miAplic.policy miAplic
así no verifica los archivos de permisos standards
Para instalar un nuevo administrador de seguridad se debe colocar:
System.setSecurityManager(new SecurityManager());
La sintaxis general del archivo de permisos es:
grant URL
{
permission nombreClase objetivo listaAcciones;
...
};
Universidad Simón Bolívar
Prof. Wílmer Pereira
Especialización en Telematica
(4) Ejemplo de archivos de permisos
Clases que se pueden asegurar:
java.io.FilePermission
java.net.SocketsPermission
java.awt.AWTPermission
java.net.NETPermission ...
Los objetivos serán diferentes dependiendo de la clase: directorios,
intervalos de puertos, URL de máquinas, etc ...
Ejemplo:
grant codeBase “http://www.horstmann.com/classes”
{
permission java.io.FilePermission “/tmp/*” “read,write”;
permission java.net.SocketsPermission “*.horstmann.com:8000-8999”
“connect”;
};
Universidad Simón Bolívar
Prof. Wílmer Pereira
Especialización en Telematica
(5) Autentificación y Autorización
Maneja autentificación con Kerberos, conexiones UNIX, con certificados, etc.
Se usa archivo de permisos y archivo de autentificación (roles para autorizar):
PruebaAuten.policy
grant principal com.sun.security.auth.UnixPrincipal “harry”
{
permission java.util.PropertyPermission “user.*” “read”; ...
};
jass.config
Conexion1
{
com.sun.security.auth.module.UnixLoginModule required;
com.whizzbang.auth.module.KeyStoreLoginModule sufficient;
} ...
En la corrida deben tener exito un módulo required o al menos un opcional:
java -classpath conexion.jar -Djava.security.policy=PruebaAuten.policy
-Djava.security.auth.login.config=jaas.config PruebaAuth
Universidad Simón Bolívar
Prof. Wílmer Pereira
Especialización en Telematica
(6) Compendio
Para calcular compendio se crea una instancia:
MessageDigest alg = MessageDigest.getInstance(“SHA-1”);
Se agrega texto al mensaje en un ciclo con
... alg.update((byte) ch); ...
y se calcula el compendio con:
byte[] hash = alg.digest();
Su principal uso sería para:
Integridad de datos.
Almacenamiento seguro de passwords
Extensión de password para hacerlo menos ingenuo
Forma parte de la firma digital ...
Universidad Simón Bolívar
Prof. Wílmer Pereira
Especialización en Telematica
(6) Firma digital
Inicialmente se deben generar las claves pública y privada. Para ello
se deben usar números aleatorios seguros:
KeyPairGenerator genclaves = KeyPairGenerator.getInstance(“DSA”);
SecureRandom aleseg = new SecureRandom();
aleseg.setSeed(...);
genclaves.initialize(512,aleseg);
KeyPair claves = genclaves.generateKeyPair();
PublicKey clavePub = claves.getPublic();
PrivateKey clavePriv = claves.getPrivate();
...
Signature algsign = Signature.getInstance(“DSA”);
algsign.initSign(clavepriv);
... algsign.update(bytes); ...
byte[] signatura = algsign.sign();
Para verificar la firma en el destinatario (con la clave pública del emisor ...)
Signature algverif = Signature.getInstance(“DSA”);
algverif.initVerify(clavepub);
... algverif.update(bytes); ...
boolean comprobacion = algverif.verify(signatura);
Universidad Simón Bolívar
Prof. Wílmer Pereira
Especialización en Telematica
(7) Certificados digitales en Java
Java usa el formato X509v3 que se guarda en formato binario.
Los certificados clase 1 apenas se verifican con e-mail y
los clase 3 requieren un notario ... en ambos casos es con una CA externa
keytool administra el almacen de claves, donde
keytool
keytool
keytool
keytool
keytool
-genkey -keystore almacen.store -alias wilmer
-export -keystore almacen1.store -alias wilmer -file wilmer.cert
-printcert -file wilmer.cert
-import -keystore almacen2.store -alias wilmer -file wilmer.cert
-list -v -keystore jre/lib/security/cacerts
Para firmar un documento empaquetado con jarsigner
jar cvf documento.jar documento.txt
jarsigner -keystore almacen.store documento.jar wilmer
Finalmente para verificar el documento firmado
jarsigner -verify -keystore almacen.store documento.jar
Universidad Simón Bolívar
Prof. Wílmer Pereira
Especialización en Telematica
(7) Firmar certificados en Java
Los certificados generados por keytool son autofirmados. Podría firmarse
creando una CA interna o propia ...
Inicialmente se crea una CA autofirmada que se importará a todos los clientes
keytool -genkey -keystore ACME.store -alias ACMEraiz
keytool -export -keystore ACME.store -alias ACMEraiz -file CApropia.cert
ACME debe tener un programa para firmar certificados pues tiene
ACME.store y la contraseña del almacen de claves. La llamada sería:
java FirmaCerts -keystore ACME.store -alias ACMEraiz
-infile wilmer.cert -outfile wilmerFirmadoACME.cert
Ahora cada usuario de la CA interna debe tener ACMraiz para verificar los
certificados de sus colegas.
keytool no permite explicitamente firmar certificados pero si dejarlos
preparados para ser firmado por una CA externa con la opción -certreq
Universidad Simón Bolívar
Prof. Wílmer Pereira
Especialización en Telematica
(7) Código para firmar en Java
Inicialmente se crea un almacen de claves
KeyStore almacen = KeyStore.getInstance(“JKS”,“UCAB”);
Se carga el almacen con la clave del almacen y se recupera
la clave privada de ACME con el passphrase:
... almacen.load(in,claveAlmacen); ...
... PrivateKey emisorClavePrivada =
(PrivateKey) almacen.getKey(alias,passphrase); ...
Se crea el nuevo certificado que será firmado:
CertificateFactory fabrica = CertificateFactory.getInstance(“X.509”);
X509Certificate certEntrada =
(X509Certificate) fabrica.generateCertificate(in);
Hay dos tipos de certificados, el de java.security y el de
java.security.cert. Se debe usar el último ...
Universidad Simón Bolívar
Prof. Wílmer Pereira
Especialización en Telematica
(7) Código para firmar en Java
Se recuperan los datos del certificado de ACME
byte[] bytesCertEntrada = certEntrada.getTBSCertificate();
X509Certificate certEmisor =
(X509certificate) almacen.getCertificate(“ACMEraiz”);
Principal emisor = certEmisor.getSubjectDN();
String algSigEmisor = certEmisor.getSigAlgName();
Lo que sigue no es standard, pertenece a la clase sun.security.x509 y
se firma el certificado del cliente:
X509CertInfo info = new X509CertInfo(bytesCertEntrada);
info.set(X509CertInfo.ISSUER, new certificateIssuerName((X509Name) emisor));
X509CertImpl certSalida = new X509CertImpl(info);
certSalida.sign(emisorClavePrivada,algSigEmisor);
certSalida.derEncode(out);
Es probable que se genere en el futuro un API standard ...
Universidad Simón Bolívar
Prof. Wílmer Pereira
Especialización en Telematica
(7) Verificar código firmado
Se debe ...
Utilizar autentificación para verificar de donde proviene el código
Ejecutar el código con las normas de permisos dependiendo del origen
Se dispone inicialmente de un archivo AppletFirmado.jar firmado y
se crea un almacen certs.store con el certificado de ACME. Con esto se
define el archivo de permiso applet.policy:
keystore “file://home/midir.certs.store”, “JKS”
grant signedBy “ACMEraiz”
{
permission java.io.FilePermission “<<ALL FILES>>”, “read”;
};
Para correrlo desde appletviewer:
appletviewer -J-DJava.security.policy=applet.policy AppletFirmado.html
Para correrlo desde el browser debe agregarse a deployement.properties
deployment.user.security.policy=file:///home/midir/applet.policy
Universidad Simón Bolívar
Prof. Wílmer Pereira
Especialización en Telematica
(8) Cifrado simétrico
Se genera la clave con números aleatorios seguros:
KeyGenerator genclaves = KeyGenerator.getInstance(“AES”);
SecureRandom aleatorio = new SecureRandom();
genclaves.init(aleatorio);
Key clave = genclaves.generateKey();
Se crea la instancia necesaria para cifrar con, por ejemplo, AES y usar update
para cifrar texto en claro que se deja en un archivo de salida:
Cipher cifrado = Cipher.getInstance(“AES”);
int tamanoBloque = cifrado.getBlockSize();
byte[] bytesEntrada = new byte[tamanoBloque];
... //leer bytesEntrada
int tamanoSalida = cifrado.getOutputSize(longitudEntrada);
byte[] bytesSalida = new byte[tamanoSalida];
int longitudSalida = cifrado.update(bytesEntrada,0,tamanoSalida);
... //Escribir los bytesSalida
Se puede cifrar y descifrar por flujo continuo ...
Universidad Simón Bolívar
Prof. Wílmer Pereira
Especialización en Telematica
(8) Cifrado asimétrico
Ante el problema de la distribución de la clave simétrica y la gran cantidad
(una para uso o cliente) se estila el uso de los algoritmos de clave pública.
Se usan juntos pues los algoritmos de clave simétrica son mucho más rápidos.
Se crea un par de claves: pública y privada. Se genera una clave simétrica que
se cifra con la clave pública del destinatario:
Key clave = ... // clave AES a compartir durante la sesion
Key clavePublica = ... // clave publica RSA del destinatario
Cipher cifrado = Cipher.getInstance(“RSA”);
cifrado.init(Cipher.WRAP_MODE,clavePublica);
byte[] claveCifrada = cifrado.wrap(clave);
Finalmente se envía por la red un archivo la clave simétrica encriptada
con WRAP y texto cifrado con la clave AES ...
Universidad Simón Bolívar
Prof. Wílmer Pereira
Especialización en Telematica
Cifrado con JSSE (Java Secure Sockets Extension)
Usando SSL (Sockets Secure Layer) como base para asegurar aplicaciones.
Ofrece cifrado simétrico, autentificación del servidor con certificados,
integridad y opcionalmente autentificación del cliente.
Key clave = ... // clave AES a compartir durante la sesion
Key clavePublica = ... // clave publica RSA del destinatario
Cipher cifrado = Cipher.getInstance(“RSA”);
cifrado.init(Cipher.WRAP_MODE,clavePublica);
byte[] claveCifrada = cifrado.wrap(clave);
Finalmente se envía por la red un archivo la clave simétrica encriptada
con WRAP y texto cifrado con la clave AES ...
Universidad Simón Bolívar
Prof. Wílmer Pereira
Especialización en Telematica
Descargar