Evolución y conceptos de seguridad de Java, Parte 3: Seguridad de applet

El crecimiento inicial de Java fue impulsado por el código descargable a través de una red, mejor conocido como applets. La seguridad de los applets ha evolucionado con el crecimiento de Java y hoy en día es una fuente de confusión frecuente debido a la variedad de versiones de Java, navegadores y complementos disponibles comercialmente.

Este artículo, el tercero de la serie, cubrirá los diversos requisitos para ejecutar de forma segura el código Java descargado de una red. Aunque el código móvil no es un concepto revolucionario, Java e Internet presentan algunos desafíos únicos para la seguridad informática. La evolución de la arquitectura Java y su impacto en la seguridad central de Java se discutió en las Partes 1 y 2. Este artículo toma un rumbo diferente: un enfoque práctico para unir todos los conceptos mediante la implementación de un subprograma simple que escribe en el sistema de archivos local .

Evolución y conceptos de seguridad de Java: ¡Lea toda la serie!

  • Parte 1: Aprenda los conceptos y términos de seguridad informática en esta descripción general introductoria
  • Parte 2: Descubra los entresijos de la seguridad de Java
  • Parte 3: Aborde la seguridad del subprograma Java con confianza
  • Parte 4: Descubra cómo los paquetes opcionales amplían y mejoran la seguridad de Java
  • Parte 5: J2SE 1.4 ofrece numerosas mejoras a la seguridad de Java

En el núcleo del subprograma de ejemplo se encuentra la criptografía de clave pública, presentada anteriormente en esta serie. El código firmado con la clave privada del firmante se puede ejecutar en las máquinas cliente una vez que la clave pública correspondiente al firmante se considere confiable en la máquina respectiva. También discutiremos cómo los archivos de políticas, que otorgan permisos y almacenamiento de claves, se pueden usar como un repositorio de claves públicas y privadas. Además, destacaremos las herramientas de seguridad Java 2 SDK y Netscape signtool, ya que permiten la implementación.

Este artículo sigue la evolución de la seguridad de Java, comenzando con la seguridad de las aplicaciones en la versión inicial de Java 2 y pasando a la última versión de Java 2, la versión 1.3. Este enfoque ayuda a introducir los conceptos gradualmente, comenzando con conceptos muy simples y culminando con un ejemplo bastante avanzado.

Esta serie no pretende proporcionar una guía completa de seguridad informática. La seguridad informática es un tema multifacético que afecta a varias disciplinas, departamentos y culturas. Las inversiones en tecnologías deben ir seguidas de inversiones en capacitación de personal, aplicación estricta de políticas y revisión periódica de la política de seguridad general.

Nota: Este artículo presenta un subprograma Java en ejecución diseñado para demostrar problemas de seguridad del subprograma. Lea abajo para más detalles.

Seguridad de la aplicación

Comencemos nuestra investigación analizando la seguridad de las aplicaciones. En la Parte 2, vimos cómo la seguridad de Java ha evolucionado de un modelo de espacio aislado a un modelo de seguridad detallado. También vimos que las aplicaciones (código local) por defecto obtienen un dominio libre y no están sujetas al mismo control que los applets (código descargable de la red), que normalmente se consideran no confiables. En un cambio con respecto al pasado, en Java 2 las aplicaciones de seguridad pueden estar sujetas opcionalmente al mismo nivel de control que los applets.

Primero, una nota rápida sobre writeFile.javael código utilizado en este artículo para ilustrar las características de seguridad en Java 2. Este programa es una versión ligeramente modificada del código del subprograma proporcionado por Sun, disponible en la Web para ilustrar algunas de las características de Java 2 seguridad. El programa, modificado para brindar soporte a la aplicación, intenta crear y escribir un archivo en el sistema de archivos local. El administrador de seguridad controla el acceso a un sistema de archivos local. Veremos a lo largo de este artículo cómo se puede permitir esta operación en particular de manera segura.

/ ** * De forma predeterminada, esto genera una excepción de seguridad como un subprograma. * * Con el visor de subprogramas JDK 1.2, * si configura su sistema para otorgar subprogramas firmados por "Duke" * y descargados del sitio web de software de Java para escribir un archivo * en su directorio / tmp (o en el archivo llamado "C: \ tmpfoo "en un sistema * Windows), este subprograma se puede ejecutar. * * @version JDK 1.2 * @author Marianne Mueller * @Modificado por Raghavan Srinivas [Rags] * / import java.awt. *; importar java.io. *; importar java.lang. *; importar java.applet. *; La clase pública writeFile extiende el applet {String myFile = "/ tmp / foo"; Archivo f = nuevo archivo (myFile); DataOutputStream dos; public void init () {String osname = System.getProperty ("os.name"); if (osname.indexOf ("Windows")! = -1) {myFile = "C:" + File.separator + "tmpfoo";}} pintura vacía pública (Gráficos g) {try {dos = new DataOutputStream (nuevo BufferedOutputStream (nuevo FileOutputStream (myFile), 128)); dos.writeBytes ("Los gatos pueden hipnotizarte cuando menos lo esperas \ n"); dos.flush (); dos.close (); g.drawString ("Se escribió con éxito en el archivo llamado" + myFile + "- ¡échale un vistazo!", 10, 10); } catch (SecurityException e) {g.drawString ("writeFile: capturada excepción de seguridad", 10, 10); } catch (IOException ioe) {g.drawString ("writeFile: capturada excepción de E / S", 10, 10); }} public static void main (String args []) {Frame f = new Frame ("writeFile"); writeFile writefile = new writeFile (); writefile.init (); writefile.start (); f.add ("Centro", archivo de escritura); f.setSize (300, 100); f.show (); }}}}}}Los gatos pueden hipnotizarte cuando menos te lo esperas \ n "); dos.flush (); dos.close (); g.drawString (" Se escribió correctamente en el archivo llamado "+ myFile +" - ve y échale un vistazo ! ", 10, 10);} catch (SecurityException e) {g.drawString (" writeFile: capturado una excepción de seguridad ", 10, 10);} catch (IOException ioe) {g.drawString (" writeFile: atrapado i / o excepción ", 10, 10);}} public static void main (String args []) {Frame f = new Frame (" writeFile "); writeFile writefile = new writeFile (); writefile.init (); writefile.start ( ); f.add ("Centro", archivo de escritura); f.setSize (300, 100); f.show ();}}Los gatos pueden hipnotizarte cuando menos te lo esperas \ n "); dos.flush (); dos.close (); g.drawString (" Se escribió correctamente en el archivo llamado "+ myFile +" - ve y échale un vistazo ! ", 10, 10);} catch (SecurityException e) {g.drawString (" writeFile: capturado una excepción de seguridad ", 10, 10);} catch (IOException ioe) {g.drawString (" writeFile: atrapado i / o excepción ", 10, 10);}} public static void main (String args []) {Frame f = new Frame (" writeFile "); writeFile writefile = new writeFile (); writefile.init (); writefile.start ( ); f.add ("Centro", archivo de escritura); f.setSize (300, 100); f.show ();}}} catch (SecurityException e) {g.drawString ("writeFile: capturada excepción de seguridad", 10, 10); } catch (IOException ioe) {g.drawString ("writeFile: capturada excepción de E / S", 10, 10); }} public static void main (String args []) {Frame f = new Frame ("writeFile"); writeFile writefile = new writeFile (); writefile.init (); writefile.start (); f.add ("Centro", archivo de escritura); f.setSize (300, 100); f.show (); }}} catch (SecurityException e) {g.drawString ("writeFile: capturada excepción de seguridad", 10, 10); } catch (IOException ioe) {g.drawString ("writeFile: capturada excepción de E / S", 10, 10); }} public static void main (String args []) {Frame f = new Frame ("writeFile"); writeFile writefile = new writeFile (); writefile.init (); writefile.start (); f.add ("Centro", archivo de escritura); f.setSize (300, 100); f.show (); }}

La ejecución del código de bytes generado en un entorno de ejecución Java 2, Standard Edition (JRE) permitirá que la aplicación modifique el archivo en el sistema de archivos local de forma predeterminada, ya que la política predeterminada no somete las aplicaciones Java 2 a un administrador de seguridad. Esta política se justifica porque las aplicaciones suelen ser código generado localmente y no se descargan a través de la red. La siguiente línea de comando produce la ventana que se muestra en la Figura 1, que indica que el archivo fue creado y escrito.

$ Java writeFile 

Para someter el código al administrador de seguridad de Java 2, invoque la siguiente línea de comando, que debería producir los resultados indicados en la Figura 2. Observe que la aplicación generó una excepción de seguridad causada por un intento de modificar el sistema de archivos local. El administrador de seguridad incluido explícitamente generó la excepción.

$ java -Djava.security.manager writeFile 

Los casos ilustrados anteriormente representan ejemplos extremos de política de seguridad. En el primer caso, la aplicación no estuvo sujeta a ningún control; en el segundo, estaba sujeto a un control muy rígido. En la mayoría de los casos, será necesario establecer la política en algún punto intermedio.

Puede lograr una política intermedia utilizando un archivo de política. Para hacerlo, cree un archivo de política llamado all.policyen el directorio de trabajo:

conceder {permiso java.io.FilePermission "<>", "escribir"; };

Ejecutar el mismo fragmento de código con la siguiente línea de comando permitirá la modificación del sistema de archivos local:

$ java -Djava.security.manager -Djava.security.policy = all.policy writeFile 

En este ejemplo, la aplicación estaba sujeta al administrador de seguridad, pero la política general se regía por el archivo de políticas, que permitía modificar todos los archivos del sistema de archivos local. Una política más estricta podría haber sido permitir la modificación solo del archivo relevante, tmpfooen este caso.

Cubriré más detalles del archivo de póliza, incluida la sintaxis de las entradas, más adelante en este artículo. Pero primero, veamos la seguridad del subprograma y comparémosla con la seguridad de la aplicación.

Seguridad del applet

So far, we've studied application security. As such, most of the security features can be accessed and modified via the command line. Providing an adequately secure and yet somewhat flexible policy in an applet environment proves substantially more challenging. We will start by looking at the deployment of an applet in Appletviewer. We'll look at browser-deployed applets later.

Java code policy is primarily dictated by CodeSource, which comprises two pieces of information: the place where the code originated and the person who signed it.

Appletviewer

Create a file called writeFile.html with the following contents:

  Java Security Example: Writing Files 
   

Running the applet with the following command line would result in the window shown in Figure 3:

$ appletviewer writeFile.html 

Notice that -- in contrast to what would happen with an application -- the applet generated an exception since the applet is subject to the security manager by default. The installation can be governed by a customizable policy, if required. Running the following command line:

appletviewer -J"-Djava.security.policy=all.policy" writeFile.html 

would, as you might expect, allow modification of the tmpfoo file, since this was permitted in accordance with the policy file.

Browsers

Applet security in browsers strives to prevent untrusted applets from performing potentially dangerous operations, while simultaneously allowing optimal access to trusted applets. Applet security deployment in browsers is substantially different from what we have seen so far, primarily due to the following reasons:

  • A default lack of trust in code downloaded over the network
  • Insufficient access to the command-line options for running the JVM, since the JVM is hosted in the context of a browser
  • Inadequate support for some of the latest security features in the JVMs bundled with browsers

As for the first problem, to obviate the potential problems resulting from running untrusted code, earlier versions of Java used the sandbox model (see "Sidebar 1: Sandbox Model"). Trust is a largely philosophical or emotional issue, rather than a technical issue; however, technology can help. For example, Java code can be signed using certificates. In this example, the signer implicitly vouches for the code by signing it. The onus is ultimately upon the user running the code to trust the signing entity or not, given that these certificates guarantee that the code was indeed signed by the intended person or organization.

The second problem stems from the lack of access to the options for running the JVM in the browser context. For example, there is no simple way to deploy and use customized policy files as we could in the previous example. Instead, such policies will have to be set by files based on the JRE installation. Customized class loaders or security managers cannot be installed easily.

The third problem, the lack of support for the latest versions of the JRE in the default JVM with the browser, is solved by using the Java plug-in (see "Sidebar 2: Java Plug-in Primer"). Indeed, an underlying issue is that modification of policy files is not very straightforward. Since applets may be deployed on thousands or even millions of client machines, there might be environments where users might not have a good understanding of security or may not be acquainted with methods for modifying the policy file. The Java plug-in provides a workaround, although it's recommended to use policy files wherever practical and applicable.

Next, we'll look in more detail at applet security involving code-signing examples in a browser environment with a Java plug-in. We will confine the discussion to Java plug-in version 1.3 unless explicitly stated otherwise.

The Java plug-in and security

The Java plug-in supports the standard Java 2 SDK, Standard Edition (J2SE), including the security model. All applets run under the standard applet security manager, which prevents potentially malicious applets from performing dangerous operations, such as reading local files. RSA-signed applets can be deployed using the Java plug-in. Additionally, the Java plug-in attempts to run applets in an identical way in both Netscape Navigator and Internet Explorer by avoiding browser-specific resources. This ensures that an RSA-signed applet will run identically in both browsers with the Java plug-in. The Java plug-in also supports HTTPS, a secure version of HTTP.

In order for a plug-in-enhanced browser to trust an applet and grant it all privileges or a set of fine-grained permissions (as specified in a J2EE policy file), the user has to preconfigure his or her cache of trusted signer certificates (the .keystore file in JRE 1.3) to add the applet's signer to it. However, this solution does not scale well if the applet needs to be deployed on thousands of client machines, and may not always be feasible because users may not know in advance who signed the applet that they are trying to run. Also, earlier versions of the Java plug-in supported code signing using DSA, which is not as widely prevalent as RSA.

A new class loader, sun.plugin.security.PluginClassLoader in the Java plug-in 1.3, overcomes the limitations mentioned above. It implements support for RSA verification and dynamic trust management.

The Software Development Kit (SDK) tools

The three tools dealing with security, available as part of the Java 2 SDK, are:

  • keytool -- Manages keystores and certificates
  • jarsigner -- Generates and verifies JAR signatures
  • policytool -- Manages policy files via a GUI-based tool

We will look at some of these tools' important options in the sections below. Refer to Resources for more detailed documentation associated with particular tools.